← Back to posts
comparison guide self-hosted · · 12 min read

Docker Bench vs Trivy vs Checkov: Self-Hosted Container Security Hardening Guide 2026

Compare Docker Bench for Security, Trivy, and Checkov for self-hosted container hardening, CIS benchmark auditing, and misconfiguration scanning in 2026.

OS
Editorial Team

Running containers in production without security hardening is one of the most common mistakes teams make. A default Docker installation ships with dozens of configuration choices that deviate from security best practices — running as root, sharing the host namespace, exposing privileged ports, and mounting sensitive filesystem paths without restriction.

This guide compares three open-source tools that audit and enforce container security baselines: Docker Bench for Security, Trivy, and Checkov. Each takes a different approach to hardening, from CIS benchmark compliance checks to infrastructure-as-code misconfiguration scanning. We’ll cover installation, configuration, and real-world usage so you can pick the right tool for your self-hosted environment.

Why Harden Your Containers?

Containers share the host kernel, which means a misconfigured container can compromise the entire system. The CIS Docker Benchmark alone lists over 100 security checks covering host configuration, Docker daemon settings, container runtime options, and image build practices.

Hardening your containers addresses three core risks:

  • Privilege escalation — containers running as root or with --privileged flag can escape to the host
  • Data exposure — volumes mounted without :ro (read-only) flags allow write access to sensitive host paths
  • Network exposure — containers binding to 0.0.0.0 without firewall rules are reachable from any network

The tools covered in this guide automate the detection of these misconfigurations, saving hours of manual audit work.

Docker Bench for Security: CIS Benchmark Auditing

Docker Bench for Security is the official Docker Inc. tool that implements the CIS Docker Benchmark as an automated shell script. It runs dozens of checks against your Docker host configuration, daemon settings, and running containers.

AttributeDocker Bench for Security
GitHubdocker/docker-bench-security
Stars9,623
LanguageShell
Last UpdatedOctober 2024
LicenseApache 2.0
FocusCIS Docker Benchmark compliance
DeploymentDocker container or host script

How It Works

The tool connects to your Docker daemon (read-only via the socket) and runs a series of checks organized into categories:

  1. Host configuration — kernel parameters, AppArmor/SELinux status, partitioning
  2. Docker daemon configuration — storage driver, logging, live restore, user namespaces
  3. Daemon configuration files — permissions on /etc/docker/daemon.json
  4. Container images and build filesdocker commit, HEALTHCHECK presence, update policies
  5. Container runtime — privileged mode, PID namespace sharing, network mode, memory limits
  6. Docker security operations — swarm mode, secrets management
  7. Docker swarm configuration — manager/workernode settings (if applicable)

Each check is marked as PASS, WARN, or INFO, making it easy to spot failures at a glance.

Installation via Docker Compose

The easiest way to run Docker Bench is inside a container with access to the host Docker socket and relevant filesystem paths:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  docker-bench-security:
    build: .
    cap_add:
      - audit_control
    labels:
      - docker_bench_security
    pid: host
    stdin_open: true
    tty: true
    volumes:
      - /var/lib:/var/lib:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /usr/lib/systemd:/usr/lib/systemd:ro
      - /etc:/etc:ro

Build and run:

1
2
3
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
docker compose up

Running Specific Tests

You can target specific test categories using the -t flag:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Run only container runtime checks
docker run --rm --net host --pid host --userns host \
  --cap-add audit_control \
  -v /etc:/etc:ro \
  -v /var/lib:/var/lib:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v /usr/lib/systemd:/usr/lib/systemd:ro \
  -l docker_bench_security \
  docker/docker-bench-security \
  -t 5_check_docker_security

Sample Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[INFO] 1 - Host Configuration
[WARN] 1.1  - Ensure a separate partition for containers has been created
[PASS] 1.2  - Ensure the container host has been Hardened
[PASS] 1.3  - Ensure Docker is up to date
[WARN] 1.4  - Ensure only trusted users are allowed to control Docker daemon

[INFO] 5 - Container Runtime Configuration
[WARN] 5.4  - Ensure privileged containers are not running
[WARN] 5.9  - Ensure the host's network namespace is not shared
[PASS] 5.15 - Ensure the host's process namespace is not shared

Trivy: Multi-Purpose Security Scanner

Trivy by Aqua Security is a comprehensive security scanner that goes far beyond container hardening. It scans container images, filesystems, Git repositories, and Kubernetes clusters for vulnerabilities, misconfigurations, secrets, and software bill of materials (SBOM).

AttributeTrivy
GitHubaquasecurity/trivy
Stars34,718
LanguageGo
Last UpdatedApril 2026
LicenseApache 2.0
FocusVulnerabilities, misconfigurations, secrets, SBOM
DeploymentCLI binary or Docker container

Container Misconfiguration Scanning

Trivy’s config scanner supports Docker Compose, Dockerfile, and Kubernetes manifests. It checks against built-in policies derived from CIS benchmarks and best practices:

1
2
3
4
5
6
7
8
# Scan a Dockerfile for misconfigurations
trivy config Dockerfile

# Scan a docker-compose.yml file
trivy config docker-compose.yml

# Scan a directory of IaC files
trivy config ./deploy/

Sample Misconfiguration Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
docker-compose.yml (dockerfile)
=============================
Tests: 7 (SUCCESSES: 5, FAILURES: 2, EXCEPTIONS: 0)
Failures: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 0)

HIGH: Image 'app:latest' uses 'latest' tag
══════════════════════════════════════════
Using 'latest' tag makes builds non-reproducible

MEDIUM: Container runs as root user
═══════════════════════════════════
No user specified in Dockerfile; defaults to root

Installing Trivy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Debian/Ubuntu
sudo apt-get install wget apt-transport-https gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
  sudo gpg --dearmor -o /usr/share/keyrings/trivy.gpg
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] \
  https://aquasecurity.github.io/trivy-repo/deb \
  generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy

# Or via Docker
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  -v $HOME/.cache:/root/.cache/ \
  aquasec/trivy:latest image nginx:latest

Running as a Self-Hosted Scanner

You can run Trivy on a schedule via cron to audit all running images:

1
2
3
4
5
#!/bin/bash
# /usr/local/bin/trivy-audit.sh
trivy image --format table --severity HIGH,CRITICAL \
  $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v '<none>') \
  >> /var/log/trivy-audit.log 2>&1

Add to crontab for daily runs:

1
0 2 * * * /usr/local/bin/trivy-audit.sh

Checkov: Infrastructure-as-Code Security

Checkov by Bridgecrew (now part of Prisma Cloud) is a static analysis tool for infrastructure-as-code. It scans Terraform, CloudFormation, Kubernetes, Dockerfile, and Docker Compose files against hundreds of built-in policies covering security, compliance, and best practices.

AttributeCheckov
GitHubbridgecrewio/checkov
Stars8,670
LanguagePython
Last UpdatedApril 2026
LicenseApache 2.0
FocusIaC misconfiguration scanning across cloud providers
DeploymentPython package or Docker container

Docker and Compose Scanning

Checkov includes policies specifically for Dockerfile and Docker Compose files:

1
2
3
4
5
6
7
8
# Scan a Dockerfile
checkov -f Dockerfile

# Scan a docker-compose file
checkov -f docker-compose.yml

# Scan a directory
checkov -d ./infrastructure/ --framework dockerfile

Sample Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Check: CKV_DOCKER_2: "Ensure that HEALTHCHECK instructions have been added to container images"
        FAILED for resource: /Dockerfile.main
        File: /Dockerfile.main:1-20
        Guide: https://docs.prismacloud.io/en/enterprise-edition/...

Check: CKV_DOCKER_7: "Ensure the base image uses a non latest version"
        PASSED for resource: /Dockerfile.main

Check: CKV2_DOCKERCOMPOSE_1: "Ensure container uses a non-root user"
        FAILED for resource: /docker-compose.yml
        File: /docker-compose.yml:5-15

Installing Checkov

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# Via pip
pip install checkov

# Via Docker
docker run --tty --volume /tmp:/tf \
  bridgecrew/checkov --directory /tf --framework dockerfile

# CI/CD integration (GitHub Actions example)
# .github/workflows/checkov.yml
name: Checkov
on: [push]
jobs:
  checkov:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Checkov
        uses: bridgecrewio/checkov-action@master
        with:
          directory: ./
          framework: dockerfile,dockercompose

Comparison: Docker Bench vs Trivy vs Checkov

FeatureDocker BenchTrivyCheckov
Primary FocusCIS Docker BenchmarkMulti-purpose securityIaC misconfiguration
Dockerfile ScanningPartial (build checks)YesYes (detailed policies)
Docker ComposeNo (runtime only)YesYes
Running Container AuditYes (primary feature)NoNo
Vulnerability ScanningNoYes (CVE database)No
Secret DetectionNoYesNo
Kubernetes ScanningNoYesYes
Custom PoliciesNoYes (Rego/OPA)Yes (Python/YAML)
CI/CD IntegrationManual/scriptedNativeNative (GitHub Actions)
Output FormatsConsole onlyJSON, SARIF, Table, CycloneDXJSON, JUnit, SARIF, CLI
LanguageShellGoPython
Stars9,62334,7188,670
Best ForRuntime compliance checksComprehensive scanningBuild-time IaC checks

When to Use Each Tool

  • Docker Bench — Run periodically on production hosts to verify CIS Docker Benchmark compliance. Best for audit and compliance teams who need documented proof of security posture.
  • Trivy — Use as your all-in-one scanner in CI/CD pipelines. Catches vulnerabilities, misconfigurations, and secrets in a single pass. Ideal for development teams.
  • Checkov — Deploy as a pre-commit or CI gate for infrastructure-as-code files. Its granular policy controls make it the best choice for enforcing standards across Docker Compose and Dockerfile repositories.

For a complete self-hosted container security pipeline, combine all three tools at different stages:

Stage 1: Build-Time Checks (Checkov + Trivy)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# .github/workflows/container-security.yml
name: Container Security
on:
  push:
    paths:
      - 'Dockerfile'
      - 'docker-compose.yml'
jobs:
  checkov:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install checkov
      - run: checkov -f Dockerfile -f docker-compose.yml --framework dockerfile,dockercompose

  trivy-config:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'config'
          scan-ref: '.'
          severity: 'HIGH,CRITICAL'
          exit-code: '1'

Stage 2: Image Scanning (Trivy)

After building your container image, scan for vulnerabilities:

1
2
docker build -t myapp:latest .
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest

Stage 3: Runtime Auditing (Docker Bench)

Schedule Docker Bench to run weekly on production hosts:

1
2
3
4
5
#!/bin/bash
# /opt/scripts/docker-bench-audit.sh
cd /opt/docker-bench-security
docker compose up --exit-code-from docker-bench-security \
  2>&1 | tee /var/log/docker-bench-$(date +%Y%m%d).log
1
0 3 * * 0 /opt/scripts/docker-bench-audit.sh

Hardening Quick-Reference Checklist

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# /etc/docker/daemon.json - Essential security settings
{
  "userns-remap": "default",
  "live-restore": true,
  "no-new-privileges": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  }
}

Hardened Docker Compose Example

Here’s a production-ready compose file that passes most Docker Bench checks:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
services:
  app:
    image: myapp:1.2.3
    user: "1000:1000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    tmpfs:
      - /tmp:size=100M
    volumes:
      - app-data:/data:rw
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - backend

  proxy:
    image: caddy:2-alpine
    user: "1000:1000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    ports:
      - "127.0.0.1:8080:8080"
    networks:
      - backend

volumes:
  app-data:

networks:
  backend:
    driver: bridge
    internal: true

Key hardening principles applied:

  • Non-root user — every container runs as UID 1000
  • Read-only filesystem — mutable state isolated to tmpfs and named volumes
  • Capability dropping — all capabilities dropped, only NET_BIND_SERVICE re-added where needed
  • No new privileges — prevents privilege escalation via setuid binaries
  • Resource limits — memory and CPU caps prevent runaway containers
  • Internal network — backend network not exposed to host
  • Healthchecks — enables automatic restart on failure
  • Pinned image tags — no latest tags for reproducible builds

Additional Hardening Tips

Enable User Namespace Remapping

User namespace remapping maps container root to an unprivileged host user:

1
2
3
4
5
6
7
8
9
# /etc/docker/daemon.json
{
  "userns-remap": "default"
}

# Or map a specific range
{
  "userns-remap": "dockremap:dockremap"
}

Enable AppArmor or SELinux Profiles

1
2
3
4
5
# Apply AppArmor profile to a container
docker run --security-opt apparmor=docker-default nginx:alpine

# Or use SELinux
docker run --security-opt label=type:container_t nginx:alpine

Disable Inter-Container Communication

1
2
3
4
5
# Create an isolated network
docker network create --opt com.docker.network.bridge.enable_icc=false isolated-net

# Run containers on this network
docker run --network isolated-net myapp

Use Content Trust for Image Verification

1
2
3
4
5
# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# Pull only signed images
docker pull nginx:latest

For related reading on container security, see our container image scanning guide and Kubernetes hardening comparison. If you’re also managing IaC security, check our Checkov vs TFsec vs Trivy comparison.

FAQ

What is the CIS Docker Benchmark?

The CIS Docker Benchmark is a set of security configuration guidelines published by the Center for Internet Security. It covers host configuration, Docker daemon settings, container images, and runtime options. Docker Bench for Security automates these checks, making compliance verification a single command.

Can Trivy replace Docker Bench for Security?

Not entirely. Trivy excels at scanning container images and IaC files for misconfigurations and vulnerabilities, but it does not audit running containers or the Docker daemon configuration on the host. Docker Bench fills this gap by checking the live environment. For comprehensive coverage, use both: Trivy at build time and Docker Bench at runtime.

Does Checkov scan running containers?

No. Checkov performs static analysis on infrastructure-as-code files (Dockerfile, docker-compose.yml, Terraform, etc.). It catches misconfigurations before deployment but cannot audit containers already running on a host. Pair it with Docker Bench for full lifecycle coverage.

How often should I run container security audits?

Run Trivy scans on every build in your CI/CD pipeline (zero extra cost). Run Checkov as a pre-commit hook or PR check. Run Docker Bench on production hosts weekly via cron, and immediately after any Docker daemon configuration change or host update.

What is the difference between vulnerability scanning and misconfiguration scanning?

Vulnerability scanning checks for known CVEs in package dependencies (e.g., OpenSSL 1.1.1 has CVE-2023-0464). Misconfiguration scanning checks for insecure settings (e.g., container running as root, privileged mode enabled). Trivy does both; Docker Bench and Checkov focus on misconfigurations only.

Can I write custom policies for these tools?

Trivy supports custom policies via Rego (OPA) language for config scanning. Checkov allows custom policies in Python or YAML format. Docker Bench does not support custom policies — it strictly implements the CIS Docker Benchmark. If you need custom runtime checks, consider combining Docker Bench output with a custom script.

Are these tools suitable for production environments?

Yes. All three tools are read-only by design. Docker Bench connects to the Docker socket in read-only mode. Trivy and Checkov analyze files without modifying them. None of these tools change your system configuration — they only report findings.

Advertise here
Advertise here