intermediate

Multi-stage builds

Separate build tooling from runtime images so production containers stay smaller, safer, and easier to scan.

Multi-stage builds keep compilers, dev dependencies, test tooling, and source-only files out of the runtime image. A common Node pattern builds in one stage and copies only `dist` plus production `node_modules` into a slim final stage.

					FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev

FROM node:20-bookworm-slim
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER node
CMD ["node", "dist/server.js"]
				

Match glibc/musl and CPU architecture between build and runtime when copying native modules.

On interviews: image size, vulnerability surface, reproducible artifacts, native module compatibility, and when build and runtime bases must align.

Common pitfalls: copying `node_modules` across incompatible platforms; omitting migrations, static assets, or Prisma engines from the final stage.

The trade-off is smaller safer images versus build complexity and cross-stage copy discipline.

Checklist:

  • Separate build and runtime stages.
  • Copy only required outputs.
  • Verify native dependency compatibility.
  • Render or test the final stage artifact in CI.