Safeguard
Security Guides•

Go in Docker: FROM scratch or distroless static, and what must you add?

A static Go binary runs on scratch, but you must add certificates, time zones and a user yourself. Distroless static ships them. Compare the two.

Safeguard Security Team
4 min read

A static Go binary runs on scratch, but scratch is empty: you must add CA certificates, time zone data and a non-root user yourself. The distroless static image already includes certificates, tzdata, a tmp directory and a nonroot tag. Use scratch if you want to control every byte, and distroless static for sane defaults.

Build a static binary first

Both options need a binary with no libc dependency. The distroless documentation shows the standard approach: build with CGO disabled so the result does not need libc, then copy it into the runtime image.

FROM golang:1.25 AS build
WORKDIR /go/src/app
COPY . .
RUN go mod download
RUN CGO_ENABLED=0 go build -trimpath -o /go/bin/app

FROM gcr.io/distroless/static-debian13:nonroot
COPY --from=build /go/bin/app /
CMD ["/app"]

Use the Go version your project supports. If your code or a dependency needs cgo, a static binary is not possible in the usual way, and the distroless docs point those applications to the base image that includes glibc.

What distroless static contains

According to the distroless project, the static image includes ca-certificates, an etc/passwd entry for a root user, a tmp directory and tzdata. Tags include latest, nonroot, debug and debug-nonroot. The project describes the smallest image as around 2 MiB.

What scratch is missing

Scratch has nothing. If your program makes HTTPS calls, it needs certificates to verify servers. If it formats times in a named zone, it needs time zone data. Go offers a way around the second: the time/tzdata package provides an embedded copy of the timezone database, used if the time package cannot find tzdata files on the system. Importing it increases the program size by about 450 KB, according to the package documentation.

NeedScratchDistroless static
CA certificatesCopy from build stageIncluded
Time zone dataEmbed with time/tzdata or copy filesIncluded
Non-root userCreate passwd entry and numeric USERnonroot tag
A tmp directoryCreate itIncluded
Shell for debuggingNoneNone, use debug tag
Update owner for those filesYouThe distroless project, you rebuild

Which to choose

Scratch makes sense when the binary is the only thing in the image and you are willing to maintain the certificate bundle yourself. A stale certificate bundle in a frozen scratch image is a quiet failure that shows up as TLS errors later.

Distroless static trades a little size for defaults that are tracked upstream. The project says it tracks upstream Debian releases and uses automation to open pull requests when updates are available. You still need to rebuild your image to pick them up.

Verify what you ship

Run the built image and check the user. Check that outbound HTTPS works. Check the time zone behaviour if you rely on it. Then verify the signature of the base. The distroless project says its images are signed with cosign using keyless signing, and recommends verifying before you build on them.

Where Safeguard fits

A static Go binary hides its dependency list from tools that only read operating system packages. Safeguard scans Go modules from your repository and builds an SBOM, with policy gates on pull requests. Try the free scan.

Quick check

Why does my scratch based Go program fail on HTTPS calls?

It has no CA certificates to verify the server. Copy a certificate bundle from the build stage or use an image that includes one.

Is a scratch image automatically free of vulnerabilities?

No. It has no operating system packages to report, but the Go standard library version and your module dependencies are still in the binary.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.