Skip to content

fix(docker): make prod images actually build and boot#98

Merged
f-amine merged 1 commit into
masterfrom
fix/docker-build-public-env
Jun 18, 2026
Merged

fix(docker): make prod images actually build and boot#98
f-amine merged 1 commit into
masterfrom
fix/docker-build-public-env

Conversation

@f-amine

@f-amine f-amine commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Why

Dokploy deploy failed at pnpm --filter ./apps/web run build (exit 1). Reproduced the exact docker build locally and found three bugs in docker/Dockerfile.next — none caught by CI, because CI builds with pnpm build (env present) and never exercises the Dockerfile.

Bugs + fixes

  1. NEXT_PUBLIC_* undefined at build@vibestack/env/web throws, next build dies. These are inlined into the client bundle at build time, but env_file only reaches runtime. → Pass public vars as build args (compose interpolates them via a shared x-public-build-args anchor); builder sets them as ENV. Server vars get shape-valid placeholders at build so validation + module-load (new URL(APP_URL) in auth) pass; real secrets only arrive at runtime via env_file, and the runner is a separate stage so nothing leaks into image layers.
  2. COPY ... public ... 2>/dev/null || trueCOPY isn't shell; Docker treated the redirect as a literal source and failed once the build reached it. web/admin have no public/. → mkdir -p public in the builder, unconditional COPY.
  3. CMD ["node","apps/${APP_NAME}/server.js"] — exec-form JSON doesn't expand vars → Cannot find module apps/${APP_NAME}/server.js. → persist APP_NAME as ENV, CMD ["sh","-c","exec node apps/$APP_NAME/server.js"] (expands + keeps SIGTERM).

Verified locally (not just CI)

  • docker build web (no public dir) and marketing (has public dir): both succeed end to end.
  • docker run web with only runtime env: container boots, ▲ Next.js Ready, /api/health serves (503 only because no DB attached; auth up, optional services disabled).

Deploy note

NEXT_PUBLIC_* must be present in the Dokploy Environment tab before building (they're build args now) — they already are in the documented env block.

🤖 Generated with Claude Code

Three bugs in docker/Dockerfile.next, none caught by CI (CI builds via
pnpm, never through the Dockerfile):

1. NEXT_PUBLIC_* are inlined at build time, but env_file only reaches
   runtime, so `next build` died on missing NEXT_PUBLIC_APP_URL. Pass
   the public vars as build args (compose interpolates them from the
   deploy env via a shared YAML anchor) and set them as ENV in the
   builder. Server vars get shape-valid placeholders at build only
   (real secrets arrive at runtime via env_file; the runner is a
   separate stage, so no secret enters any image layer).
2. `COPY ... public ... 2>/dev/null || true` is not shell — Docker
   COPY parsed the redirect as a literal source and failed once the
   build got far enough to reach it. web/admin ship no public/ dir, so
   mkdir -p it in the builder and make the COPY unconditional.
3. CMD was exec-form JSON with ${APP_NAME}, which Docker does not
   expand → "Cannot find module apps/${APP_NAME}/server.js". Persist
   APP_NAME as ENV and use `sh -c 'exec node ...'` so it expands and
   node still receives SIGTERM.

Verified locally: web + marketing images build; web container boots
(Next ready, /api/health serves) with only runtime env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@f-amine f-amine merged commit cd677b2 into master Jun 18, 2026
3 checks passed
@f-amine f-amine deleted the fix/docker-build-public-env branch June 18, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant