Docker cookbook · Beginner

Ship a Go service in a tiny distroless image

Compile a static Go binary and run it in an image with no shell or package manager.

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

Approach

Build with CGO_ENABLED=0 for a static binary, then copy it into gcr.io/distroless/static with the nonroot user. Cache Go modules and the build cache with BuildKit mounts.

Solution

# syntax=docker/dockerfile:1
FROM golang:1.26-alpine 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-debian13:nonroot
COPY --from=build /out/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]

Pitfalls

  • Forgetting CGO_ENABLED=0: the binary needs libc and fails in a static image.
  • Needing CA certificates or time zones: distroless static includes them; scratch doesn't.
  • Expecting to docker exec sh into it for debugging; use a debug container instead.

Variations

  • FROM scratch with explicit ca-certificates and tzdata copies for the very smallest image.
  • Cross-compile for arm64 with GOARCH instead of emulation.

Further reading: Distroless images

Reference: https://github.com/GoogleContainerTools/distroless

More Docker recipes

Was this page helpful?