Overview
Multi-stage builds allow you to use multiple FROM statements in a Dockerfile, keeping your final image lean by excluding build tools and dependencies.
Benefits
- Smaller Images: Reduce image size by 80-95%
- Security: Exclude development tools from production
- Build Cache: Leverage Docker's layer caching
- Clean Dependencies: Only runtime dependencies in final stage
- Fast Deployments: Smaller images = faster pulls and starts
Basic Pattern
# Stage 1: Build
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Runtime
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]
Image Size Comparison
# Without multi-stage: 1.2 GB
docker build -f Dockerfile.single -t myapp .
# With multi-stage: 150 MB
docker build -f Dockerfile.multi -t myapp .
Advanced Pattern with caching
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY src ./src
RUN npm run build
FROM node:18-alpine
RUN apk add --no-cache dumb-init
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
ENTRYPOINT ["dumb-init", "node", "dist/index.js"]
Multi-stage builds are essential for production-grade containerization.