Free tech learning for everyone, from basics to pro

Container SecurityCloud SecurityIntermediate

Container image security: minimal bases, scanning, secrets and pinning

In short: Every package in an image is something you must patch and something an attacker can use. Start from a minimal base, build in stages so tools stay out of the final image, scan each build, keep secrets out, run as a non-root user and pin by digest. Rebuild regularly so fixes actually reach production.

Why images need care

A container image is the software you actually ship. If the base image contains an old OpenSSL library, a shell and a package manager, so does your production container. Large images bring more known vulnerabilities (CVEs) to triage, more tools for an intruder to use and slower deploys. Image security is about shipping only what the application needs, and knowing exactly what that is.

Secure image pipelineMinimal basedistroless,slimBuildmulti-stageScanCVEs, secretsSign and pushprivateregistryRebuild oftennew patches
Figure 1. A secure image pipeline starts small, scans every build and rebuilds regularly to pick up fixes.

Choose a minimal base and build in stages

  • Minimal bases: options include Alpine, Debian or Ubuntu "slim" variants, distroless images (no shell or package manager) and scratch for static binaries. Fewer packages means fewer CVEs and fewer tools for attackers.
  • Trusted sources: prefer official or verified publisher images, or an internal "golden" base maintained by your platform team.
  • Multi-stage builds: compile in a full build image, then copy only the finished artefact into a small runtime image. Compilers and source code stay behind.
  • Non-root user: create a user and switch to it with USER, so a compromised process does not start as root.
# build stage
FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app

# runtime stage
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

Scanning and keeping secrets out

Image scanners compare the packages in each layer against vulnerability databases and flag known CVEs. Popular open-source options include Trivy and Grype, and most registries (Amazon ECR, Azure Container Registry with Defender for Cloud, Google Artifact Registry) offer built-in scanning. Many scanners also detect secrets and misconfigurations in Dockerfiles.

trivy image --severity HIGH,CRITICAL registry.example.com/shop/api:1.4.2
trivy image --scanners secret registry.example.com/shop/api:1.4.2

Use scan results sensibly. Fail the build on critical, fixable vulnerabilities, but triage the rest using exploitability and whether the vulnerable package is actually reachable. A scanner report with 300 findings that nobody reads protects nothing.

Never bake secrets into images. Use a .dockerignore file to keep .env files, keys and the .git folder out of the build context, use build-time secret mounts (BuildKit --secret) when a build needs credentials, and supply runtime secrets as described in container secrets.

Pinning and rebuilding

Tag versus digestTag (nginx:1.27)Human friendlyCan be movedMay change silentlyHard to auditDigest (sha256:...)Exact contentCannot changeReproducible deploysUpdate deliberately
Figure 2. Tags are labels that can be re-pointed; digests identify the exact bytes you tested.

The tag latest, or even 1.27, can be moved to point at new content. Pinning by digest (image@sha256:...) guarantees you deploy exactly what you tested. Tools such as Renovate or Dependabot can then propose digest updates as pull requests, so you upgrade deliberately rather than by surprise.

Pinning creates its own risk: a pinned image never picks up security fixes on its own. Schedule regular rebuilds (weekly is common) so new base layers reach production, and remove old images from the registry.

Tip: keep a short checklist in code review: minimal base, multi-stage, non-root USER, no secrets, HEALTHCHECK where useful, pinned digest, scan passed.

Practice

Why does a distroless image reduce risk after a compromise?
It has no shell or package manager, so an attacker who gains code execution has far fewer built-in tools to explore or download more malware.
What is the benefit of a multi-stage build?
Build tools, compilers and source stay in the build stage; only the final artefact is copied into a small runtime image.
Your pipeline pins every image by digest. What must you add to stay secure?
A routine to rebuild and update digests regularly, otherwise images never receive security fixes.

Key takeaways

  • Ship only what the application needs: minimal bases and multi-stage builds.
  • Run as a non-root user by default.
  • Scan every build for CVEs and secrets, and triage results sensibly.
  • Keep secrets out of images and build context.
  • Pin by digest and rebuild on a schedule to pick up fixes.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.