Secure Images with Scanning
Learn how to harden Docker images by integrating vulnerability scanning into your workflow. This lesson covers scanning tools, interpretation of results, and remediation steps to keep your container images safe.
Focus: secure images with vulnerability scanning
You've built a Docker image, pushed it, and maybe even deployed it — but how do you know it's safe to run in production? Vulnerabilities in base images and installed packages are the #1 attack vector in containerized environments. This lesson shows you how to secure images with vulnerability scanning, turning a reactive security posture into a proactive one.
The problem this lesson solves
Container images are like icebergs: what you see (your application code) is tiny compared to what lies beneath (the OS layer, system libraries, runtime dependencies). A simple FROM ubuntu:latest can pull in hundreds of packages, each with its own CVE history. Without scanning, you're shipping unknown risk into production.
Common scenarios this solves: - You inherit a Dockerfile from a team member and have no idea what's inside the base image - A critical CVE drops — e.g., Log4Shell — and you need to find every affected image in seconds - You're preparing for a security audit and must prove your images are hardened - You want to block a build before it reaches production if it contains high-severity vulnerabilities
Pro tip: Vulnerability scanning isn't just for security teams. As a developer, integrating scans into your local workflow catches issues before they ever reach a registry or CI/CD pipeline.
Core concept / mental model
Think of vulnerability scanning as an X-ray for your container image. It unpacks every layer, identifies every package and library, and cross-references each one against public vulnerability databases like the National Vulnerability Database (NVD) and GitHub Advisory Database.
Key definitions
- CVE: Common Vulnerabilities and Exposures — a unique identifier for a known security flaw (e.g., CVE-2023-44487)
- Severity: CVSS score (0–10) that rates impact: Critical (9.0–10.0), High (7.0–8.9), Medium (4.0–6.9), Low (0.1–3.9)
- SBOM: Software Bill of Materials — a full inventory of components in your image, often generated alongside scans
- Vulnerability database: A curated list of known flaws; tools like Grype, Trivy, and Docker Scout each use their own sources
The scanning pipeline
Image → Layer analysis → Package inventory → Database lookup → CVE list + severity → Report / fix suggestions
Each layer is examined independently. If you rebuild with a patched base image, only the changed layers need re-scanning — a huge efficiency gain in CI/CD.
How it works step by step
-
Choose a scanning tool: Docker Desktop includes Docker Scout out of the box. For CI/CD, Trivy (open-source, fast) and Grype (Anchore) are popular. We'll use
docker scoutfirst because it's zero-install. -
Run a scan: Point the scanner at your image tag. It downloads the image (if not cached), extracts metadata, and queries vulnerability databases.
-
Interpret the output: Results group by severity. Each entry shows: - CVE ID — the unique identifier - Package name and installed version - Fixed version — the patched version, if available - Severity score and description
-
Remediate: Common fixes: - Rebase on a smaller, updated base image (e.g., switch
ubuntu:22.04toubuntu:22.04with latest patches) - Upgrade packages inside the image viaapt-get upgradeorpip install --upgrade- Multi-stage builds to exclude build-time tools that carry vulnerabilities - Pin exact versions instead of usinglatesttags -
Automate: Add scanning as a pre-deployment gate in CI/CD. If critical CVEs exceed a threshold, fail the build.
Blockquote: Scanning doesn't fix vulnerabilities — it tells you what's broken. You still need to patch and rebase regularly.
Hands-on walkthrough
Prerequisites
- Docker Desktop 4.17+ (with Docker Scout enabled)
- A sample image to scan — we'll use a deliberately outdated
python:3.8-slimfor demonstration
Step 1: Scan with Docker Scout
# Ensure Docker Scout is enabled
docker scout
# Scan a python:3.8-slim image
docker scout quickview python:3.8-slim
Expected output snippet:
✓ SBOM scanned successfully
✓ No vulnerable packages detected
Target │ python:3.8-slim
digest │ sha256:abcd1234...
base image │ debian:buster-slim
vulnerabilities │ 12C, 34H, 56M, 12L
This tells you: 12 critical, 34 high, 56 medium, 12 low vulnerabilities. The base image debian:buster-slim is outdated (Buster is Debian 10, end-of-life since 2022).
Step 2: Get detailed information
docker scout recommendations python:3.8-slim
This shows the top CVEs and, crucially, suggests a remediation — often a newer base image like debian:bullseye-slim (Debian 11) or debian:bookworm-slim (Debian 12).
Step 3: Fix and rescan
Let's build a safer image using multistage and an updated base.
# Dockerfile
FROM python:3.12-slim-bookworm AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim-bookworm
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY app.py .
CMD ["python", "app.py"]
Build and scan:
docker build -t my-secure-app:latest .
docker scout quickview my-secure-app:latest
Expected outcome: far fewer vulnerabilities — often single digits or zero. You've hardened the image by: - Using the latest Python version (3.12) - Using Debian Bookworm (2023+) instead of Buster - Only copying what's needed from the builder stage
Step 4: Try Trivy (open-source alternative)
# Install Trivy on macOS
echo 'export PATH=$PATH:/usr/local/bin' >> ~/.zshrc
trivy image my-secure-app:latest
Trivy outputs a detailed table. Both tools are valuable — Docker Scout integrates with Docker Hub/Docker Desktop, Trivy is CI-friendly and faster for bulk scans.
Compare options / when to choose what
| Feature | Docker Scout | Trivy | Grype |
|---|---|---|---|
| Install | Built into Docker Desktop | Standalone binary / Docker image | Binary / Docker image |
| Update frequency | Real-time via Docker Hub | Daily database updates | Hourly via syft |
| SBOM generation | Yes (built-in) | Yes (uses Syft) | Yes (built-in) |
| CI integration | GitHub Actions, Jenkins plugins | Native GitHub Action, CLI | GitHub Action, CircleCI orb |
| License | Free for OSS, paid for teams | Open-source (Apache 2.0) | Open-source (Apache 2.0) |
| Speed | Moderate (network-dependent) | Fast (local DB) | Moderate |
When to use each: - Docker Scout: Local development with Docker Desktop; easiest onboarding - Trivy: CI/CD pipelines needing speed; multi-language scans (Python, Go, Java, etc.) - Grype: If you already use Anchore for policy enforcement; deep SBOM analysis
Troubleshooting & edge cases
Docker Scout returns "No SBOM found"
This means the image isn't in Docker Hub or Scout cannot index it. Pull the image first: docker pull my-image. For private registries, enable Scout integration or use --env.
False positives in scan results
Some scanners flag CVEs that don't apply at runtime — e.g., a libssl vulnerability in a Python image that never uses SSL. Context matters: A CVE in a library that isn't loaded at runtime isn't exploitable. Use tools like Snyk or Grype with reachability analysis.
Scan says "0 vulnerabilities" but you know there are issues
You may be scanning a base image that hasn't been updated. Always scan your final image, not the intermediate layers. Also, ensure your scanner has the latest vulnerability database: trivy image --download-db-only.
Remediation breaks the application
Upgrading packages can introduce breaking changes. Example: libc6 upgrade in a system image. Test in a staging environment before updating base images in production. Use docker scout recommendations to see safe upgrade paths.
What you learned & what's next
You now know how to secure images with vulnerability scanning — from basic scans to automated remediation in CI/CD. Let's recap the key skills:
- Scan any Docker image using
docker scoutortrivy - Interpret CVE output and prioritize fixes by severity
- Remediate vulnerabilities by rebasing, upgrading packages, or using multi-stage builds
- Compare scanning tools and choose the right one for your pipeline
- Avoid common pitfalls like false positives or breaking changes from upgrades
Next lesson: [Hardened Dockerfiles with best practices] — you'll learn how to write Dockerfiles that minimize surface area from the start.
Before you go, run one more scan on a base image you use daily. See what's lurking there. Then rebuild with an updated base and compare the vulnerability counts. That's the secure-by-default mindset you're now building.
Practice recap
Mini exercise: Find a Dockerfile you wrote in the last month. Build & scan it with docker scout quickview <image>. Note the top 3 vulnerabilities. Then update the base image (e.g., python:3.9-slim → python:3.12-slim-bookworm), rebuild, rescan, and compare. Write down how many CVEs disappeared. That's your first remediation win.
Common mistakes
- Scanning only production images — development images often have even more packages and vulnerabilities.
- Ignoring medium/low severity CVEs — attackers chain multiple lower-severity issues into exploits.
- Assuming a zero-vuln scan means the image is safe — scanners only know known CVEs; zero-day vulnerabilities can still exist.
- Not pinning base image versions — using
latestmeans your scans are inconsistent and you're shipping unknown content. - Forgetting to rebase regularly — even a patched image collects vulnerabilities over time; scan weekly or per sprint.
Variations
- Use
snyk container testfor reachability analysis — shows only CVEs that affect code paths your app actually takes. - Use
docklefor image security best practices checks beyond CVEs (e.g., running as root, unnecessary packages). - Integrate scanning into pre-commit hooks using
gitleaks+trivyfor a local security check before pushing.
Real-world use cases
- Healthcare SaaS: scan every image build for HIPAA compliance, fail builds with critical CVEs in system libraries.
- E-commerce microservices: schedule weekly Trivy scans on all container images in ECR, auto-file Jira tickets for high-severity vulnerabilities.
- CI/CD pipeline gating: use Docker Scout in a GitHub Action to block deployment if any critical CVE exists in the slimmed-down production image.
Key takeaways
- Vulnerability scanning unpacks every layer of an image, cross-referencing packages against CVE databases.
- Docker Scout is built into Docker Desktop; Trivy is faster and CI-friendly; choose based on your pipeline needs.
- Remediation involves rebasing to updated base images, upgrading packages, and adopting multi-stage builds.
- Always scan your final production image, not intermediate layers, to get an accurate attack surface.
- A zero-vuln scan does not guarantee security — keep tools and databases updated, and test remediations in staging.
- Automate scanning as a pre-deployment gate in CI/CD to prevent vulnerabilities from reaching production.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.