Skip to content

Commit 8f965b8

Browse files
committed
Fix Docker build: build to local dist/ then copy to output volume
Astro 6 uses fs.rename() internally during builds, which fails with EXDEV when source and destination are on different Docker volume mounts. Instead of using --outDir to write directly to the cross-device /output mount, build to the default dist/ directory (same filesystem) and copy the result afterward.
1 parent 1cdacf0 commit 8f965b8

3 files changed

Lines changed: 2 additions & 25 deletions

File tree

astro/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
"url": "https://github.com/DuendeSoftware/docs.duendesoftware.com.git"
1313
},
1414
"notes": {
15-
"Astro SVG validation issue": "https://github.com/withastro/astro/issues/13006",
16-
"Astro EXDEV rename issue": "fs.rename fails across Docker mount boundaries (cross-device); patched to fall back to copy+unlink"
15+
"Astro SVG validation issue": "https://github.com/withastro/astro/issues/13006"
1716
},
1817
"scripts": {
1918
"dev": "astro dev",

astro/patches/astro+6.1.4.patch

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,3 @@ index 0f22881..41cd9ef 100644
1111
calculate(input) {
1212
const root = extractorRegExps.root.exec(toUTF8String(input));
1313
if (root) {
14-
diff --git a/node_modules/astro/dist/core/build/static-build.js b/node_modules/astro/dist/core/build/static-build.js
15-
index 79f476a..afb77e9 100644
16-
--- a/node_modules/astro/dist/core/build/static-build.js
17-
+++ b/node_modules/astro/dist/core/build/static-build.js
18-
@@ -384,7 +384,7 @@ async function ssrMoveAssets(opts, internals, prerenderOutputDir) {
19-
if (!fs.existsSync(currentUrl)) return;
20-
const dir = new URL(path.parse(clientUrl.href).dir);
21-
if (!fs.existsSync(dir)) await fs.promises.mkdir(dir, { recursive: true });
22-
- return fs.promises.rename(currentUrl, clientUrl);
23-
+ try { return await fs.promises.rename(currentUrl, clientUrl); } catch (e) { if (e.code === 'EXDEV') { await fs.promises.copyFile(currentUrl, clientUrl); await fs.promises.unlink(currentUrl); } else { throw e; } }
24-
})
25-
);
26-
}
27-
@@ -400,7 +400,7 @@ async function ssrMoveAssets(opts, internals, prerenderOutputDir) {
28-
if (!fs.existsSync(currentUrl)) return;
29-
const dir = new URL(path.parse(clientUrl.href).dir);
30-
if (!fs.existsSync(dir)) await fs.promises.mkdir(dir, { recursive: true });
31-
- return fs.promises.rename(currentUrl, clientUrl);
32-
+ try { return await fs.promises.rename(currentUrl, clientUrl); } catch (e) { if (e.code === 'EXDEV') { await fs.promises.copyFile(currentUrl, clientUrl); await fs.promises.unlink(currentUrl); } else { throw e; } }
33-
})
34-
);
35-
removeEmptyDirs(fileURLToPath(serverRoot));

build.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ await RunAsync("docker",
5454
"-w /app " +
5555
"-e NODE_OPTIONS=\"--max-old-space-size=4096\" " +
5656
"node:22-slim " +
57-
"sh -c \"npm ci && npm run build -- --outDir /output\"",
57+
"sh -c \"npm ci && npm run build && cp -r dist/. /output/\"",
5858
configureEnvironment: env => env.Add("MSYS_NO_PATHCONV", "1"));
5959
});
6060

0 commit comments

Comments
 (0)