Container Image Scanning

Container image scanning is essential for detecting vulnerabilities before they reach production. This guide covers Trivy, Clair, Docker Scout, Grype, Snyk, and integrating vulnerability scanning into your CI/CD pipeline.

Trivy Clair Docker Scout Grype CI/CD
Why Container Image Scanning Matters

Containers are built from images that often contain hundreds of packages and libraries. Many of these packages have known vulnerabilities (CVEs) that attackers can exploit. Image scanning tools analyze container images and compare installed packages against vulnerability databases (NVD, Alpine SecDB, Debian Security Tracker, etc.).

Without scanning, you're shipping code with known, exploitable vulnerabilities. Image scanning should be integrated into your CI/CD pipeline to block vulnerable images before they reach production. Most container registries (Docker Hub, AWS ECR, Azure ACR, Google GCR) offer built-in or integrated scanning.

According to Snyk's research, 70% of container images have high-severity vulnerabilities. Regular scanning is essential for maintaining security.
Image Scanning Tools Comparison
ToolLanguageDatabase UpdatesCI/CD IntegrationBest For
TrivyGoFast (auto-updates)ExcellentAll-round, fastest, easiest
Docker ScoutBuilt-inReal-timeExcellent (GitHub Actions)Docker users
ClairGoManual/periodicGoodLarge-scale registries
GrypeGoFastGoodAnchore ecosystem
SnykNode.jsReal-timeExcellentDeveloper-first security
DagdaPythonGoodFairLightweight scanning
Trivy: Comprehensive, Fast Vulnerability Scanner

Trivy is the most popular open-source container vulnerability scanner. It's fast, easy to use, and covers OS packages (Alpine, Debian, Ubuntu, CentOS, etc.) and language-specific packages (npm, pip, gem, cargo, go). Trivy also scans misconfigurations, secrets, and SBOMs.

# Install Trivy - macOS brew install aquasecurity/trivy/trivy # Install Trivy - Linux sudo apt-get install wget apt-transport-https gnupg lsb-release wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list sudo apt-get update sudo apt-get install trivy # Scan image for vulnerabilities trivy image nginx:latest # Scan with severity filter trivy image --severity CRITICAL,HIGH nginx:latest # Scan with JSON output trivy image --format json --output results.json nginx:latest # Scan Dockerfile misconfigurations trivy config ./Dockerfile # Scan filesystem trivy fs --security-checks vuln,config . # Ignore unfixed vulnerabilities (for faster results) trivy image --ignore-unfixed nginx:latest
Docker Scout: Built-in Vulnerability Scanning

Docker Scout is Docker's native vulnerability scanning tool. It's built into Docker Desktop and Docker Hub, and integrates with GitHub Actions. Docker Scout provides policy evaluation, base image upgrade recommendations, and SBOM generation.

# Docker Scout CLI (Docker Desktop) docker scout quickview nginx:latest docker scout cves nginx:latest docker scout recommendations nginx:latest # Compare two images docker scout compare nginx:1.20 nginx:1.25 # Generate SBOM docker scout sbom nginx:latest --format cyclonedx # Policy evaluation (create policy file) docker scout policy evaluate nginx:latest --policy policy.yml # GitHub Actions integration - name: Run Docker Scout uses: docker/scout-action@v1 with: command: cves image: ${{ github.repository }}:latest
Clair: Static Analysis for Container Images

Clair is an open-source project from CoreOS (now Red Hat) for static analysis of container vulnerabilities. It's often used with registry integrations (Quay.io, Harbor) rather than as a CLI tool. Clair has a client-server architecture and is best for large-scale deployments.

# Run Clair with Docker Compose version: '3.8' services: postgres: image: postgres:15 environment: POSTGRES_PASSWORD: clairpass clair: image: quay.io/projectquay/clair:latest depends_on: - postgres ports: - "8080:8080" # Analyze image using clairctl clairctl analyze -i nginx:latest # Harbor integration (Harbor uses Clair for scanning) # Built into Harbor registry
Grype: Fast Vulnerability Scanner from Anchore

Grype is a powerful vulnerability scanner from the creators of Syft (SBOM tool). It's fast, accurate, and integrates well with the Anchore ecosystem. Grype can scan images, directories, and SBOM files.

# Install Grype - macOS brew install anchore/grype/grype # Install Grype - Linux curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin # Scan image grype nginx:latest # Scan with severity filter grype nginx:latest --fail-on high # Output in different formats grype nginx:latest -o json grype nginx:latest -o template -t custom.template # Scan SBOM file (generated with Syft) syft nginx:latest -o cyclonedx-json > sbom.json grype sbom.json
Snyk Container: Developer-First Security

Snyk offers container scanning with deep integration into developer workflows. It includes IDE plugins, GitHub integrations, and detailed remediation advice. Snyk's base image suggestions help you upgrade to secure base images.

# Install Snyk CLI npm install -g snyk snyk auth # Test container image snyk container test nginx:latest # Test with severity threshold snyk container test nginx:latest --severity-threshold=high # Monitor image for ongoing alerts snyk container monitor nginx:latest # Get base image upgrade recommendation snyk container test nginx:latest --file=Dockerfile # GitHub Actions integration - name: Run Snyk Container uses: snyk/actions/docker@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: image: nginx:latest args: --severity-threshold=high
CI/CD Integration: Automate Vulnerability Scanning

Integrate scanning into your CI/CD pipeline to block vulnerable images from being deployed. Here's how to integrate Trivy with GitHub Actions:

# .github/workflows/container-scan.yml name: Container Security Scan on: push: branches: [ main ] pull_request: branches: [ main ] jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t myapp:latest . - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: 'myapp:latest' format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Upload Trivy results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif' - name: Fail if critical vulnerabilities found run: | trivy image --exit-code 1 --severity CRITICAL myapp:latest
For production, set the exit code to fail builds when critical or high severity vulnerabilities are found. This prevents vulnerable images from being deployed.
Registry Integration: AWS ECR, Azure ACR, Google GCR, Docker Hub

Most container registries have built-in or integrated vulnerability scanning:

# AWS ECR scanning # Enabled in ECR settings (Basic or Enhanced scanning) aws ecr describe-image-scan-findings --repository-name myapp --image-id imageTag=latest # Azure ACR scanning az acr scan --name myregistry --image myapp:latest az acr check-health --name myregistry # Google GCR / Artifact Registry scanning (uses On-Demand scanning) gcloud artifacts docker images scan myrepo/myapp:latest # Docker Hub scanning (uses Docker Scout) # Automatic for official images and subscribed repositories
SBOM Generation: Software Bill of Materials

SBOMs (Software Bill of Materials) are machine-readable inventories of all components in a software artifact. Many regulations now require SBOMs. Tools like Syft, Trivy, and Docker Scout can generate SBOMs.

# Syft (SBOM generator) syft nginx:latest -o json > sbom.json syft nginx:latest -o cyclonedx-json > sbom.cyclonedx.json syft nginx:latest -o spdx-json > sbom.spdx.json # Trivy SBOM trivy image --format cyclonedx --output sbom.json nginx:latest # Docker Scout SBOM docker scout sbom nginx:latest --format cyclonedx # GitHub Actions SBOM upload - name: Generate SBOM run: syft nginx:latest -o cyclonedx-json > sbom.json - name: Upload SBOM uses: actions/upload-artifact@v4 with: name: sbom path: sbom.json
Policy as Code: Enforce Security Gates

Define policies to block images based on vulnerability severity, number of vulnerabilities, or specific CVEs. Use rego (Open Policy Agent) or simpler YAML-based policies.

# Trivy policy (YAML) # policy.yaml - name: "Block critical vulnerabilities" description: "Images with critical CVEs are not allowed" type: "Vulnerability" condition: | any(data.vulnerabilities, severity == "CRITICAL") - name: "Block images with known exploits" description: "CVEs with known exploits are blocked" type: "Vulnerability" condition: | any(data.vulnerabilities, exploited == true) # Run with policy trivy image --ignore-policy policy.yaml nginx:latest
Remediation: Fixing Vulnerabilities
  • Update base image - Use the latest patched version of your base image.
  • Switch to minimal base image - Alpine or Distroless have smaller attack surfaces.
  • Remove unnecessary packages - Use multi-stage builds to exclude build tools.
  • Pin dependencies - Use version pinning to avoid unexpected updates.
  • Apply security patches - Run `apt-get upgrade` or `apk upgrade` in Dockerfile.
  • Use distroless images - Eliminates entire package categories (no shell, no package manager).
Image Scanning Best Practices
  • Scan every image before deployment - Never skip scanning in CI/CD.
  • Scan base images first - Scan the base images you use; they may have vulnerabilities.
  • Set severity thresholds - Fail builds on CRITICAL and HIGH severity.
  • Automate daily scans - Vulnerabilities are discovered daily; re-scan regularly.
  • Generate SBOMs - For compliance and vulnerability tracking.
  • Use policy as code - Enforce consistent security gates across teams.
  • Integrate with registry scanning - Use built-in registry scanning for ongoing monitoring.
  • Train developers - Ensure developers know how to interpret and fix vulnerabilities.
Frequently Asked Questions
What's the difference between vulnerability scanning and compliance scanning?
Vulnerability scanning checks for known CVEs in packages. Compliance scanning checks against security benchmarks (CIS Docker Benchmark). Both are important for a complete security program.
How often should I scan images?
Scan on every build (CI/CD), plus daily or weekly for base images. Vulnerability databases update frequently, so re-scan regularly.
What are false positives in container scanning?
False positives occur when a tool reports a vulnerability that doesn't affect your application (e.g., vulnerable package present but not used). Use tools that support reachability analysis (Snyk).
Should I ignore unfixed vulnerabilities?
Unfixed vulnerabilities have no patch available. For critical unfixed vulnerabilities, consider switching to a different base image or applying workarounds. Don't ignore them without justification.
Does scanning impact build time?
Trivy scans in seconds; Grype and others in under a minute. The impact is minimal compared to the security benefit. Run scans in parallel with other CI steps.
What is a zero-day vulnerability?
A zero-day is a vulnerability with no patch available. Scanning tools can't detect unknown zero-days, but they help reduce the attack surface by minimizing packages.
Can I scan images without pulling them?
Some tools support registry scanning without pulling (e.g., AWS ECR scanning, Harbor, Clair). Most CLI tools require pulling the image first.
Which scanning tool should I use?
Start with Trivy (fast, easy, comprehensive). If you're already using Docker, try Docker Scout. For enterprise registries, use Clair or registry-integrated scanning. Snyk is excellent for developer-first workflows.
Previous: Docker Security Best Practices Next: Docker Secrets Management

Container image scanning is a critical part of DevSecOps. Integrate scanning into your CI/CD pipeline to catch vulnerabilities before they reach production.