z-go-dockerfile
Installation
SKILL.md
Go Dockerfile
Multi-stage build: a deps stage that caches modules, a build stage that compiles a static binary, and a minimal final stage that only carries the binary. Every layer earns its place — no shell, no package manager, no root user in the shipped image unless a specific need demands it.
Final image choice
| Base | Certs & tzdata | Shell / exec debugging | Reach for it when |
|---|---|---|---|
gcr.io/distroless/static-debian13:nonroot |
bundled (ca-certificates + tzdata) | none in :nonroot; swap to the :debug tag (busybox shell) to triage |
default for a CGO_ENABLED=0 Go binary |
scratch |
none — COPY both from the builder yourself |
none, ever — no :debug variant exists |
absolute minimal footprint is a hard requirement and you're fine hand-rolling certs/tzdata |
alpine |
apk add --no-cache ca-certificates tzdata (neither ships by default) |
ash shell + apk built in |
you need a shell for an entrypoint script, kubectl exec triage, or a musl-linked CGO build |
distroless/static is the sane default: it already carries what scratch forces you to reinvent, and it's smaller than alpine with a strictly smaller attack surface (no shell, no package manager). Reach for scratch only when a security policy mandates zero non-binary content, and for alpine only when something in the running container genuinely needs a shell.
Reference Dockerfile
# syntax=docker/dockerfile:1