Docker · Containers in practice

What are multi-stage builds and when do you use them?

Mediummulti-stageimage-sizebuildUpdated Oct 2026
Quiz this track

Short answer

A multi-stage build uses several FROM stages in one Dockerfile and copies only the needed artifacts into the final stage. It keeps compilers, test tools and source out of the runtime image.

Each FROM starts a new stage. You can build in a heavy image, then copy the compiled binary or installed dependencies into a small runtime image. Earlier stages are discarded from the final image, so build tooling and intermediate files do not ship.

dockerfile
FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/api ./cmd/api

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/api /api
USER nonroot:nonroot
ENTRYPOINT ["/api"]
The final image contains only the static binary and the distroless runtime files.

Benefits and costs

  • Smaller images mean faster pulls and a smaller vulnerability surface
  • Build secrets and toolchains stay out of the shipped layers
  • The Dockerfile is longer and needs named stages for clarity
  • You can stop at a stage with --target for testing or debugging

For interpreted languages, copy only production dependencies into the runtime stage, or run the install in the final stage with dev dependencies excluded. Do not copy a node_modules directory that contains build tooling.

Multi-stage builds reduce image size but do not remove vulnerabilities in the base image you choose for the final stage. Scan the final image, not only the builder.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1How does the final image avoid including the compiler?
  2. 2What does --target do?
  3. 3How would you use a stage to run tests in CI?
  4. 4What is still included from the final base image?

Say it in the interview

A multi-stage build defines several FROM stages and copies only the artifact I need into the final one. For example, I compile a Go binary in a full toolchain image and copy it into distroless, so the compiler and source never ship. It keeps images small and reduces the attack surface, at the cost of a slightly longer Dockerfile.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Docker mock interview and get scored feedback on depth, clarity and confidence.