What are Docker multi-stage builds and how do they reduce image size?
Multi-stage builds allow you to use multiple FROM statements in a Dockerfile, enabling you to use a large build image for compilation while producing a minimal final image.
The Problem Without Multi-Stage Builds
Traditionally, developers would need separate Dockerfiles for development and production:
- Development: Includes SDK, build tools, test dependencies
- Production: Should only contain the runtime artifact
Result: Large production images with unnecessary build tools, larger attack surface, slower deployments.
How Multi-Stage Builds Work
Each FROM instruction starts a new build stage. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t need.
Example: Go Application
# Stage 1: Build
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .
# Stage 2: Production
FROM scratch
COPY --from=builder /app/main /main
COPY --from=builder /app/certs /etc/ssl/certs
EXPOSE 8080
CMD ["/main"]Result: Builder image ~800MB → Production image ~10MB
Example: Node.js Application
# Stage 1: Dependencies
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Stage 2: Build
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 3: Production
FROM node:20-alpine
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
CMD ["node", "dist/server.js"]Targeting Specific Stages
# Build only up to a specific stage (useful for testing)
docker build --target builder -t myapp:builder .
# Build the final production image
docker build -t myapp:latest .Benefits
- Smaller images: Only production artifacts in final image
- Better security: No compilers, debuggers, or dev tools in production
- Single Dockerfile: No need to maintain separate dev/prod Dockerfiles
- Improved caching: Each stage caches independently
- Faster CI: Parallel stages with BuildKit