Back to all terms
ServerNode 1Node 2Infrastructure
Infraintermediate

Multi-Stage Docker Builds

Use multiple FROM instructions in a Dockerfile to separate build dependencies from the final production image.

Also known as: multi-stage builds, multi-stage Dockerfile, Docker build stages, builder pattern

Description

Multi-stage Docker builds use multiple FROM instructions in a single Dockerfile, each starting a new build stage that can selectively copy artifacts from previous stages. This pattern separates the build environment (which needs compilers, dev dependencies, and build tools) from the production runtime (which needs only the compiled application and production dependencies), resulting in dramatically smaller and more secure images.

A typical Node.js multi-stage build has three stages: a dependencies stage that installs all packages, a builder stage that compiles TypeScript, runs code generation, and prunes dev dependencies, and a production stage based on a minimal image (Alpine, distroless, or scratch) that copies only the built artifacts and production node_modules. This can reduce image sizes from 1GB+ to under 100MB, significantly improving pull times and reducing the attack surface.

BuildKit (Docker's modern build engine) enhances multi-stage builds with parallel stage execution (independent stages build concurrently), cache mounts (--mount=type=cache for package manager caches that persist between builds), secret mounts (--mount=type=secret for build-time secrets that don't persist in layers), and build arguments for conditional stage selection. Named stages (FROM node:20-alpine AS builder) improve readability and allow targeting specific stages with --target for development or testing purposes.

Prompt Snippet

Write a multi-stage Dockerfile with three named stages: 'deps' for dependency installation using --mount=type=cache,target=/root/.npm for npm cache persistence, 'builder' for TypeScript compilation and Prisma client generation (COPY only package.json, lockfile, then source), and 'runner' using gcr.io/distroless/nodejs20-debian12 with only the built output, production node_modules, and Prisma engine binaries. Use COPY --from=builder to cherry-pick artifacts. Set NODE_ENV=production, run as USER nonroot:nonroot (uid 65534), and configure HEALTHCHECK with --interval=30s --timeout=3s --retries=3 CMD ['/nodejs/bin/node', '-e', 'fetch("http://localhost:3000/healthz").then(r => process.exit(r.ok ? 0 : 1))'].

Tags

dockermulti-stageoptimizationbuildimage-sizesecurity