fix: frontend built from repo root, dist/ copied into nginx image

vite.config.ts, package.json, and src/ are at the repo root.
pnpm build outputs to dist/ at the root. COPY dist/ not apps/frontend/dist/.
This commit is contained in:
ZhenYi 2026-04-15 13:17:07 +08:00
parent 65a34a627f
commit 603e14e53b
2 changed files with 14 additions and 14 deletions

View File

@ -1,8 +1,8 @@
# Runtime only — frontend built externally via pnpm # Runtime only — frontend built externally via pnpm
FROM nginx:alpine FROM nginx:alpine
# Copy pre-built SPA assets # Copy pre-built SPA assets (pnpm build outputs to dist/)
COPY apps/frontend/dist /usr/share/nginx/html COPY dist /usr/share/nginx/html
# nginx configuration for SPA # nginx configuration for SPA
RUN echo 'server { \ RUN echo 'server { \

View File

@ -4,7 +4,7 @@
* *
* Workflow: * Workflow:
* 1. cargo build --release --target x86_64-unknown-linux-gnu (compile Rust binaries) * 1. cargo build --release --target x86_64-unknown-linux-gnu (compile Rust binaries)
* 2. pnpm build (build frontend SPA) * 2. pnpm build (build frontend SPA, outputs to dist/)
* 3. docker build (copy pre-built artifacts into minimal runtime images) * 3. docker build (copy pre-built artifacts into minimal runtime images)
* *
* Usage: * Usage:
@ -34,6 +34,7 @@ const targets = args.length > 0 ? args : ALL_SERVICES;
const rustTargets = targets.filter(s => RUST_SERVICES.includes(s)); const rustTargets = targets.filter(s => RUST_SERVICES.includes(s));
const needsFrontend = targets.includes(FRONTEND_SERVICE); const needsFrontend = targets.includes(FRONTEND_SERVICE);
const rootDir = path.join(__dirname, '..');
console.log(`\n=== Build Configuration ===`); console.log(`\n=== Build Configuration ===`);
console.log(`Registry: ${REGISTRY}`); console.log(`Registry: ${REGISTRY}`);
@ -54,7 +55,7 @@ if (rustTargets.length > 0) {
}; };
return `--package ${pkgMap[s]}`; return `--package ${pkgMap[s]}`;
}).join(' ')} -j ${cpus}`, }).join(' ')} -j ${cpus}`,
{ stdio: 'inherit', cwd: path.join(__dirname, '..') } { stdio: 'inherit', cwd: rootDir }
); );
console.log(` [OK] Rust binaries built`); console.log(` [OK] Rust binaries built`);
} catch (error) { } catch (error) {
@ -63,19 +64,18 @@ if (rustTargets.length > 0) {
} }
} }
// Step 2: Build frontend (requires apps/frontend to exist locally) // Step 2: Build frontend (frontend source is at repo root)
if (needsFrontend) { if (needsFrontend) {
const frontendDir = path.join(__dirname, '..', 'apps', 'frontend'); console.log(`\n==> Step 2: Building frontend`);
if (!fs.existsSync(frontendDir)) { if (!fs.existsSync(path.join(rootDir, 'vite.config.ts'))) {
console.error(`\n [FAIL] apps/frontend not found. Please ensure frontend source exists.`); console.error(`\n [FAIL] vite.config.ts not found`);
process.exit(1); process.exit(1);
} }
console.log(`\n==> Step 2: Building frontend`);
try { try {
execSync(`corepack enable && corepack prepare pnpm@10 --activate && pnpm install --frozen-lockfile && pnpm build`, { execSync(
stdio: 'inherit', `corepack enable && corepack prepare pnpm@10 --activate && pnpm install --frozen-lockfile && pnpm build`,
cwd: frontendDir, { stdio: 'inherit', cwd: rootDir }
}); );
console.log(` [OK] Frontend built`); console.log(` [OK] Frontend built`);
} catch (error) { } catch (error) {
console.error(` [FAIL] Frontend build failed`); console.error(` [FAIL] Frontend build failed`);
@ -101,7 +101,7 @@ for (const service of targets) {
try { try {
execSync( execSync(
`docker build -f "${dockerfile}" -t "${image}" .`, `docker build -f "${dockerfile}" -t "${image}" .`,
{ stdio: 'inherit', cwd: path.join(__dirname, '..') } { stdio: 'inherit', cwd: rootDir }
); );
console.log(` [OK] ${image}`); console.log(` [OK] ${image}`);
} catch (error) { } catch (error) {