Multi-Stage Docker Builds
Use multiple FROM instructions in a Dockerfile to separate build dependencies from the final production image.
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
Related Terms
Docker Containerization
Package applications and their dependencies into isolated, portable containers using Docker.
Dockerfile Best Practices
Write efficient, secure, and maintainable Dockerfiles that produce minimal, production-ready images.
Container Security Scanning
Scan container images for known vulnerabilities, misconfigurations, and embedded secrets before deployment.
CI/CD Pipeline Design
Automate building, testing, and deploying code through a structured pipeline triggered by version control events.