12.2.4.2 Go Multi Stage Compile
A focused guide to Go Multi Stage Compile, connecting core concepts with practical Docker and container operations.
Go multi-stage compile separates Go's relatively heavy build-time toolchain — the full compiler and module cache — from the final runtime image, which needs nothing beyond the single, statically compiled binary the build stage produces.
The Standard Multi-Stage Structure for Go
A build stage uses the full Go toolchain image; the final stage starts fresh with only the compiled binary copied in.
FROM golang:1.22 AS build
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server .
FROM gcr.io/distroless/static-debian12
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
Why the Build Stage's Size Doesn't Matter for the Final Image
The full Go toolchain image, including the compiler and standard library source, is substantial in size — but since multi-stage builds only carry forward what's explicitly copied with --from, none of that build-time bulk affects the final image at all.
docker images
golang:1.22 950MB
myapp-go-final 12MB
Why Module Caching Still Benefits Go Builds
Copying go.mod and go.sum before the full source, then running go mod download, allows Docker to cache this potentially slow dependency resolution step separately from compilation.
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o server .
Building Multiple Binaries From the Same Build Stage
A project producing several binaries can compile each one within the same build stage, then selectively copy whichever specific binary each final image actually needs.
RUN go build -o /app/server ./cmd/server
RUN go build -o /app/worker ./cmd/worker
Why Go Multi-Stage Compile Matters
This separation between Go's build-time toolchain and its minimal runtime needs is what allows Go applications to achieve some of the smallest, most efficient final container images across any language ecosystem, and understanding this pattern is foundational to containerizing Go applications well.