Multi-stage Builds
Multi-stage builds use one stage to compile your app and a second, minimal stage to ship only the finished result.
FROM image AS stagename
...
FROM smaller-image
COPY --from=stagename /path /pathA multi-stage build uses several FROM instructions in one Dockerfile. Early stages do heavy work like compiling; the final stage copies only the finished artifacts, leaving build tools behind.
Why use them
- Keep compilers, dev dependencies and source code out of the final image.
- Produce dramatically smaller, more secure images.
- Keep everything in a single Dockerfile.
How it works
Name a stage with AS build, then copy files from it in a later stage using COPY --from=build. Only the last stage becomes the final image.
Example
# Stage 1: build the frontend
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: serve the built files with Nginx
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80When to use it
- A Go team uses a multi-stage build so the final image ships only the compiled binary, not the Go toolchain (saving 600 MB).
- A React team compiles assets in a Node.js stage and copies only the dist/ folder into an Nginx stage for serving.
- A Java team runs Maven in one stage to build a JAR, then copies the JAR into a slim JRE image, excluding sources and test dependencies.
More examples
Go multi-stage build
Compiles the Go binary in a full Go image, then copies only the binary into a tiny Alpine runtime image.
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY . .
RUN go build -o /api .
FROM alpine:3.19
COPY --from=builder /api /api
ENTRYPOINT ["/api"]React + Nginx multi-stage
Builds the React app in a Node stage and serves only the static output from a minimal Nginx stage.
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/htmlNamed stages for targeted builds
Uses --target to stop the build at a named stage, which is useful for running tests without building the final image.
# Build only up to the test stage during CI
docker build --target test -t myapp:test .
# Build the full production image
docker build --target production -t myapp:prod .
Discussion