SyntaxStudy
Sign Up
Docker Vulnerability Scanning and Image Security
Docker Beginner 1 min read

Vulnerability Scanning and Image Security

Container images carry the security posture of every package they include. A base image pinned to ubuntu:22.04 may contain hundreds of packages, each a potential vulnerability. Regular scanning with tools like Trivy, Grype, Docker Scout, or Snyk identifies known CVEs in OS packages and language dependencies before images reach production. Minimising the attack surface is the most effective long-term strategy. Distroless images (from Google) contain only the application runtime and its direct dependencies — no shell, no package manager, no other tools. An attacker who compromises the container finds very few tools to work with. The FROM scratch base is even more minimal, suitable for statically compiled binaries. Integrate scanning into CI by failing the pipeline when critical vulnerabilities are found. Gate production pushes behind a clean scan. Set up automated rebuild workflows that are triggered when a new base image patch is published — many registries support event-driven triggers for this. This ensures your images inherit security fixes promptly without manual intervention.
Example
# Trivy - open-source vulnerability scanner
# Scan an image from Docker Hub
trivy image node:20-alpine

# Scan a local image
trivy image myapp:latest

# Fail CI if HIGH or CRITICAL CVEs exist
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest

# Docker Scout (built into Docker CLI)
docker scout cves myapp:latest
docker scout recommendations myapp:latest
docker scout compare myapp:2.1.0 myapp:2.0.0

# Distroless base image (Dockerfile snippet)
# FROM node:20-alpine AS build
# WORKDIR /app
# COPY . .
# RUN npm ci --omit=dev
#
# FROM gcr.io/distroless/nodejs20-debian12
# COPY --from=build /app /app
# CMD ["/app/src/server.js"]

# Scratch base for Go binary
# FROM golang:1.22-alpine AS build
# RUN CGO_ENABLED=0 go build -o /app .
# FROM scratch
# COPY --from=build /app /app
# ENTRYPOINT ["/app"]

# Check image user
docker inspect myapp:latest --format '{{.Config.User}}'