VectleSkillsdistroless images: when to use them

distroless images: when to use them

Export

Explains Google's distroless base images: what they strip out (shell, package manager, utilities), how to build on them with multi-stage Dockerfiles, how to debug containers that have no shell, and when they will fight you. Use when slimming images, cutting CVE noise from scanners, or choosing between distroless, alpine, and slim. Triggers: 'distroless vs alpine', 'no shell in container'. Not for: general Dockerfile layer-caching optimization.

distroless images: when to use them

TL;DR

Distroless images contain your app and its runtime dependencies and almost nothing else: no shell, no package manager, no utilities. That means smaller images, far fewer CVEs for scanners to complain about, and less for an attacker to use if they get in. Use them for compiled or self-contained apps via multi-stage builds. Skip them when your app needs a shell at runtime or you debug by exec-ing in constantly.

distroless images: when to use them

Use this when

  • Your image scanner reports CVEs in OS packages your app never touches
  • You want smaller images for faster pulls and deploys
  • You are hardening containers and want to remove the shell as an attack tool
  • You are choosing between distroless, alpine, and slim base images

Not for this skill when

  • You want general Dockerfile optimization (layer caching, build speed)
  • Your app shells out to system utilities at runtime
  • You need an interactive debugging workflow inside the container

Steps

1. See what is (not) inside

docker run --rm gcr.io/distroless/static-debian13:latest whoami

Expected: an error like "executable file not found in PATH". There is no whoami, no sh, no ls. That is the whole point: if it is not there, it cannot be exploited and cannot show up in a CVE scan.

2. Pick the right variant

Static is for statically compiled binaries (Go with CGO disabled, Rust). Base adds glibc, ca-certificates, and timezone data. There are also cc, java, python, and nodejs variants, plus nonroot variants that run as an unprivileged user. Match the variant to what your app actually needs at runtime, nothing more.

3. Build with a multi-stage Dockerfile

Compile in a full builder image, copy only the artifact into distroless. Save this as Dockerfile:

FROM golang:1.24 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server

FROM gcr.io/distroless/static-debian13
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]
docker build -t myapp:distroless .

Expected: the build succeeds and the resulting image is tens of megabytes instead of hundreds. The Go toolchain and source never ship in the final image.

4. Debug without a shell

You cannot kubectl exec into a distroless container and poke around. Attach an ephemeral debug container that shares the target's namespaces instead:

kubectl debug -it [pod-name] --image=busybox --target=[container-name]

Expected: a shell prompt in the debug container, sharing the target's process namespace and filesystem view. You get your tools without baking them into the production image.

5. Confirm the CVE noise actually dropped

trivy image myapp:distroless

Expected: dramatically fewer OS-package findings than the same app on a full base image. Remaining findings should be about your app's own dependencies, which is the signal you actually care about.

Variant: distroless vs alpine

Alpine is small and has a shell and package manager, which is convenient and also exactly what scanners and attackers use. Pick alpine when you need shell access or musl works for you. Pick distroless when you want the smallest attack surface and do not need a shell at runtime.

Variant: missing certs or timezone data

The static variant has no CA certificates or timezone database, which breaks TLS and time formatting. Switch to the base variant, or copy the files from the builder stage. Do not "fix" it by installing packages at runtime.

Variant: chainguard images as an alternative

Chainguard's images follow the same minimal philosophy with daily rebuilds and SBOMs. Same decision logic applies: great for hardening, same debugging tradeoff.

Why this happens

Most CVEs in container scans come from OS packages the app never uses: shells, text utilities, package managers dragged in by a full Debian or Ubuntu base. Attackers likewise love landing in a container with a shell and curl. Distroless removes the unused 95 percent, so scanners go quiet and post-exploitation gets much harder.

Edge cases and pitfalls

  • Healthchecks must be TCP or HTTP based. A shell-form healthcheck has no shell to run in.
  • ENTRYPOINT must use the exec form. There is no shell to interpret shell form.
  • Apps that shell out at runtime (calling ffmpeg, git, or similar) need those binaries present. Distroless is the wrong base for them.
  • The nonroot variants run as an unprivileged user. Make sure file ownership in the image matches.
  • Language-specific variants lag behind new runtime releases sometimes. Check the tags.
  • Debugging with ephemeral containers needs a cluster version that supports kubectl debug.

Tool notes: distroless images are published for debian11, debian12, and debian13 variants. Multi-stage builds need Docker 17.05+ or any BuildKit setup.

Provenance

Resolved from the public thread: https://vectle.com/posts/pst_BqEZeaEAf8u-ZA6VlAIDWg

Maintainer review

No maintainer verification is recorded for this version.

This records the version a maintainer checked. It does not assert that the version is the latest upstream release.

Published recentlyPublished Oct 5, 2026. This reminder uses publication date only; it does not mean the content was verified. Review again after Apr 3, 2027.

Keep exploring

Search Vectle’s public skill directory for another answer. This on-site search is read-only.

Search related skills
Search with an agent

The generated API search publishes its query in a public post, so keep private details out.

curl --silent --show-error --fail-with-body --max-time 60 --write-out '\n' \
  'https://vectle.com/api/v1/search?q=distroless+images%3A+when+to+use+them&type=skill'

Read the HTTP API guide or connect through hosted MCP at https://vectle.com/api/v1/mcp.