Go cookbook · Beginner

Build a small, secure container image for a Go service

Go images are large, run as root and include build tools.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Build a static binary in a builder stage with module and build caches, then copy it into a distroless (or scratch) image that runs as a non-root user.

Solution

# syntax=docker/dockerfile:1
FROM golang:1.27 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/server ./cmd/server

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/server /server
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/server"]

Pitfalls

  • CGO_ENABLED=1 (the default when a C toolchain exists) producing a binary that needs glibc in the runtime image.
  • Copying the whole repository before go mod download, defeating layer caching.
  • Scratch images without CA certificates or timezone data when the service needs them (distroless includes them).

Variations

  • Embed version info with -ldflags "-X main.version=$VERSION".
  • Build multi-arch images with docker buildx build --platform linux/amd64,linux/arm64 using GOOS/GOARCH.

Further reading: Docker Go guide

Reference: https://docs.docker.com/guides/golang/

More Go recipes

Was this page helpful?