Image Security Scanning with Docker Scout and Trivy

Advanced
12 min

Image Security Scanning with Docker Scout and Trivy

An image is a snapshot of an operating system and a dependency tree, and both accumulate known vulnerabilities from the day they are built. This lesson shows how to scan with Docker Scout and Trivy, how to read and prioritise the results, how to fix the findings that matter, and how to lint Dockerfiles and generate a software bill of materials so scanning becomes routine rather than a one-off audit.

What a Scanner Actually Checks

A scanner walks the image's layers and builds an inventory: OS packages (from apk, dpkg or rpm databases), language packages (package-lock.json, requirements.txt metadata, Java jars, Go binaries) and sometimes secrets and misconfigurations. It then matches each package version against vulnerability databases and reports CVEs with a severity, whether a fixed version exists, and which layer introduced the package. That last detail matters: a CVE in the base image is fixed by updating FROM, while one in node_modules is fixed in the lockfile.

Docker Scout

Scout is built into recent Docker CLIs and Docker Desktop. It needs no installation:

bash
docker scout quickview my-api:1.0 # Target │ my-api:1.0 │ 0C 2H 9M 14L # Base │ node:22 │ 0C 1H 7M 12L docker scout cves --only-severity critical,high --only-fixed my-api:1.0 docker scout recommendations my-api:1.0 # suggests newer base tags with fewer CVEs docker scout compare --to my-api:0.9 my-api:1.0

quickview separates findings inherited from the base image from those you introduced. recommendations is often the fastest fix: switching from node:22 to node:22-slim or node:22-alpine removes hundreds of packages you never used. compare is useful in pull requests to show that a change did not add vulnerabilities.

Trivy

Trivy is an open-source scanner that runs anywhere, which makes it the usual choice for CI. It can be installed natively or run as a container that reads the local image store through the Docker socket, as in the sample code.

bash
trivy image my-api:1.0 # full report trivy image --severity HIGH,CRITICAL --ignore-unfixed my-api:1.0 trivy image --exit-code 1 --severity CRITICAL my-api:1.0 # fail a pipeline trivy image --format json -o report.json my-api:1.0 trivy fs --scanners vuln,secret,misconfig . # scan the source tree and Dockerfile trivy config Dockerfile # misconfiguration checks only

--ignore-unfixed hides vulnerabilities that no package update can address yet, which keeps the report actionable. A .trivyignore file lists CVE IDs you have assessed and accepted, ideally with a comment and an expiry date.

Reading and Prioritising Results

Not every finding needs action today. Sort by:

| Factor | Ask | |--------|-----| | Severity | Critical and High first; use the CVSS score, not only the label | | Fix available | Is there a patched version? If not, only mitigation is possible | | Reachability | Is the vulnerable component actually used at run time? A CVE in apt matters little in a container that never runs apt | | Exposure | Is the container internet-facing, or an internal batch job? |

A pipeline that fails on any CVE will be ignored within a week. Fail on Critical and High with a fix available and report the rest.

Fixing What You Find

  • Update the base image: docker pull node:22-alpine and rebuild; most OS-level CVEs are fixed upstream within days.
  • Switch to a smaller base: slim, alpine, or distroless variants carry fewer packages, so fewer CVEs.
  • Update application dependencies: npm audit fix, pip install -U, or a Dependabot-style bot on the lockfile.
  • Remove what you do not need: build tools, curl, package manager caches; multi-stage builds do this naturally.
  • Rebuild regularly: a clean image accumulates CVEs while it sits in the registry; schedule a weekly rebuild and rescan.
  • Pin base images by digest (FROM node:22-alpine@sha256:...) and let a bot bump the digest.

SBOMs and Dockerfile Linting

A software bill of materials lists every component in an image, so you can answer "are we affected?" the day a new CVE appears without rescanning everything:

bash
docker scout sbom --format spdx my-api:1.0 > sbom.spdx.json trivy image --format cyclonedx --output sbom.cdx.json my-api:1.0 docker buildx build --sbom=true --provenance=true -t my-api:1.0 . # attach at build time

Linting catches problems before an image exists. hadolint flags unpinned versions, missing --no-install-recommends, latest tags and shell-form CMD; run it in CI next to the scanner.

Quick Quiz
Question 1 of 3

What does `--ignore-unfixed` do in a Trivy scan?

Key Takeaways

  • Scanners inventory OS and language packages in each layer and match them against CVE databases.
  • docker scout quickview, cves and recommendations are built in; Trivy is the portable choice for CI with --exit-code 1.
  • Prioritise by severity, fix availability, reachability and exposure; fail pipelines only on actionable findings.
  • Fix by updating or shrinking the base image, updating lockfiles, removing unneeded tools and rebuilding regularly.
  • Generate SBOMs and lint Dockerfiles with hadolint so security checks run on every build.

Next lesson: Docker Best Practices and Security — consolidate everything into a checklist for small, safe, maintainable images.

Image Security Scanning with Docker Scout and Trivy - Docker | CodeYourCraft | CodeYourCraft