CodeOath
← All posts
Docker65 min total · 19 parts

Docker Fundamentals: Images, Containers, and Writing a Good Dockerfile

Contents — Part 16 of 19: Security Basics
Part 16 of 19 · ~1 min

Security Basics

A handful of habits separate a Dockerfile a real production team would accept from one that would get flagged in review:

  • Run as a non-root user. The default user inside a container is root unless the image (or your Dockerfile) says otherwise — root inside a container is still a real privilege, and a container escape as root is strictly worse than one as an unprivileged user.
RUN addgroup -S app && adduser -S app -G app
USER app
  • Pin base image versions, not latestnode:latest today and node:latest in three months can be completely different images, silently changing your build's behavior (and its vulnerabilities) with no code change on your side. Even better, pin by digest (node:20-alpine@sha256:...) for a build that's byte-for-byte reproducible.
  • Scan images for known vulnerabilities — tools like Trivy or Docker Scout check an image's installed packages against CVE databases; this is commonly wired directly into CI so a build fails (or at least warns) on a newly disclosed critical vulnerability in a base image.
  • Never bake secrets into layers — an API key set via ENV or written to a file and later "deleted" is still recoverable from the image's layer history (see the layers section). Use runtime environment injection, a secrets manager, or Docker's --secret build mount instead.
  • Prefer a minimal base image (alpine, slim, or distroless) — fewer installed packages means fewer things that can have a vulnerability in the first place.