Multi-stage builds for compiled languages
image slimming and build hygiene.
build in a stage with the full toolchain, then COPY --from only the artifact into a tiny final base, shrinking image size and attack surface.
WHAT THIS TESTS It checks whether you know how to separate build-time tooling from the runtime artifact so production images stay small and hardened.
A GOOD ANSWER COVERS A multi-stage build defines multiple FROM stages in a single Dockerfile. A builder stage uses a heavy base with the compiler and dependencies to produce the artifact. The final stage starts from a minimal base and uses COPY --from=builder to bring over only the compiled output, discarding the toolchain, source code, and intermediate caches. The benefits are a much smaller final image, a reduced attack surface since no compilers or shells need to be present, and faster pulls and deploys. You can name stages with AS and even target intermediate stages for testing.
COMMON WRONG ANSWERS Building everything in one stage and shipping the SDK plus source to production. Thinking multi-stage requires multiple Dockerfiles. Forgetting that only what you explicitly COPY --from survives into the final image.
LIKELY FOLLOW-UPS How does this combine with distroless or scratch bases? Can you copy from an external image with COPY --from=image? How do you build a specific stage with --target?
ONE CONCRETE EXAMPLE A Go service: FROM golang:1.22 AS build, then WORKDIR /src, COPY . ., RUN CGO_ENABLED=0 go build -o /app ./cmd/server. Final stage: FROM gcr.io/distroless/static, COPY --from=build /app /app, ENTRYPOINT ["/app"]. The result is a few-megabyte image containing just the static binary, with no Go toolchain, package manager, or source in production.
Read the original → docs.docker.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.