Docker Bench Security Audit

Docker Bench for Security is an automated tool that audits your Docker infrastructure against the CIS Docker Benchmark, identifying security misconfigurations and compliance violations. This comprehensive guide covers running security audits, understanding CIS benchmarks, interpreting findings, implementing remediation, and automating compliance checks. Regular security audits are essential for maintaining a hardened, production-ready Docker environment.

Table of Contents

Understanding Docker Bench

Docker Bench for Security automates security assessment of Docker hosts and containers against the CIS Docker Community Edition Benchmark. The benchmark provides detailed recommendations for securing Docker deployments.

CIS Benchmark sections:

  • Host Configuration: OS-level security settings
  • Docker Daemon Configuration: API, TLS, logging security
  • Docker Daemon Files/Directories: Permission controls
  • Container Runtime: Runtime security parameters
  • Docker Security Operations: Compliance and monitoring

Scoring levels:

  • PASS: Configuration complies with recommendation
  • WARN: Needs manual review or optional configuration
  • INFO: Informational findings
  • FAIL: Security issue requiring immediate attention

Benefits of auditing:

  • Identify security gaps and misconfigurations
  • Ensure regulatory compliance (CIS, PCI-DSS, etc.)
  • Track security improvements over time
  • Automate security verification
  • Document compliance status

Installation and Setup

Install and configure Docker Bench for Security.

Quick installation:

# Clone repository
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security

# Make executable
chmod +x docker-bench-security.sh

# Run audit
sudo ./docker-bench-security.sh

# Output shows findings with status colors

Docker container installation (recommended):

# Run Docker Bench in container
docker run --rm \
  --net host \
  --userns host \
  --pid host \
  --cap-add audit_read \
  --volume /etc:/etc:ro \
  --volume /lib/systemd/system:/lib/systemd/system:ro \
  --volume /usr/bin/containerd:/usr/bin/containerd:ro \
  --volume /usr/local/bin/docker:/usr/bin/docker:ro \
  --volume /usr/lib/systemd:/usr/lib/systemd:ro \
  --volume /var/lib:/var/lib:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  docker/docker-bench-security

# Container has necessary access to audit host
# Cleaner isolation than host installation

Persistent installation:

# Install as system service
sudo cp docker-bench-security.sh /usr/local/bin/docker-bench-security
sudo chmod +x /usr/local/bin/docker-bench-security

# Verify installation
docker-bench-security --help

# Run from anywhere
docker-bench-security

Running Security Audits

Execute audits and capture results.

Basic audit execution:

# Run complete audit
docker-bench-security.sh

# Audit takes 2-5 minutes
# Output shows real-time progress
# Results organized by category

# Typical output format:
# [PASS] 1.1.1 Ensure a separate partition exists for containers
# [WARN] 1.2.1 Ensure auditing is configured for Docker daemon
# [FAIL] 2.1 Run the Docker daemon as a non-root user

Audit with output file:

# Save results to file
docker run --rm \
  --net host \
  --userns host \
  --pid host \
  --cap-add audit_read \
  --volume /etc:/etc:ro \
  --volume /var/lib:/var/lib:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  --volume $(pwd):/output \
  docker/docker-bench-security > audit_report.txt 2>&1

# Review results offline
cat audit_report.txt | grep FAIL

# Count findings by type
grep -c "^\[PASS\]" audit_report.txt
grep -c "^\[WARN\]" audit_report.txt
grep -c "^\[FAIL\]" audit_report.txt

Selective benchmark sections:

# Run specific section only
# Available sections: host config, docker config, files, runtime, etc.

docker run --rm \
  --net host \
  --userns host \
  --pid host \
  --volume /etc:/etc:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  docker/docker-bench-security \
  --containers

# Run only container runtime checks
# Ignore host configuration checks

# Useful for focused audits or quick verifications

CIS Benchmark Categories

Understand the major benchmark sections and their focus.

Host configuration assessment:

# Section 1: Host Configuration

# Checks include:
# - Separate filesystem for /var/lib/docker
# - SELinux or AppArmor enforcement
# - Audit logging for Docker daemon
# - Kernel security parameters
# - Daemon capabilities

# Example findings:
# [PASS] 1.1.1 Separate partition for containers
# [FAIL] 1.2.1 Auditing configured for daemon
# [WARN] 1.3.1 Only needed capabilities granted

Docker daemon configuration:

# Section 2: Docker Daemon Configuration

# Checks include:
# - Network socket configuration (TCP with TLS)
# - Daemon restart policy
# - Logging configuration
# - Authentication and authorization
# - Container registries and image trust

# Example findings:
# [PASS] 2.1 Restrict network socket to Unix socket
# [FAIL] 2.2 TLS mutual authentication configured
# [WARN] 2.7 Default logging driver configured

File and directory permissions:

# Section 3: Docker Daemon Files and Directories

# Checks include:
# - /var/lib/docker ownership and permissions
# - /var/run/docker.sock permissions
# - Docker configuration files permissions
# - Certificate file permissions

# Example findings:
# [PASS] 3.1 docker.service file ownership (0:0)
# [PASS] 3.6 /etc/docker/daemon.json ownership (0:0)
# [FAIL] 3.22 /var/run/docker.sock permissions

Container runtime security:

# Section 4: Container Runtime

# Checks include:
# - Privileged containers
# - Sensitive host directories mounted
# - SELinux labels on containers
# - Resource limits (memory, CPU, pids)
# - User namespace remapping

# Example findings:
# [WARN] 4.1 Image scanning configured
# [FAIL] 4.3 Privileged containers running
# [WARN] 4.5 PID mode restrictions

Security operations:

# Section 5: Docker Security Operations

# Checks include:
# - Docker secrets configuration
# - Secrets management
# - Host network mode usage
# - Container update policies
# - Compliance monitoring

# Example findings:
# [WARN] 5.1 AppArmor profiles for containers
# [PASS] 5.27 Docker socket mounted in containers
# [INFO] 5.28 Container health checks configured

Understanding Audit Findings

Interpret and categorize audit results.

Severity classification:

# FAIL (Critical):
# - Security vulnerability
# - Immediate remediation required
# - Examples: Running as root, no auth, exposed socket

# WARN (Medium):
# - Best practice not followed
# - Needs manual review
# - May have valid exceptions
# - Examples: Logging not configured, no CPU limits

# INFO (Low):
# - Informational
# - No action required unless needed
# - Examples: Unused features detected

# PASS (Success):
# - Configuration meets security standard
# - Keep current configuration
# - No action needed

Generating audit reports:

# Create detailed report
docker run --rm \
  --net host \
  --userns host \
  --pid host \
  --cap-add audit_read \
  --volume /etc:/etc:ro \
  --volume /var/lib:/var/lib:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  docker/docker-bench-security \
  2>&1 | tee audit_$(date +%Y%m%d).log

# Parse results by type
grep "\[FAIL\]" audit_*.log | wc -l
grep "\[WARN\]" audit_*.log | wc -l
grep "\[PASS\]" audit_*.log | wc -l

# Create summary report
cat > audit_summary.txt <<EOF
Audit Date: $(date)
Docker Version: $(docker --version)

Findings Summary:
- FAIL: $(grep -c "^\[FAIL\]" audit.log)
- WARN: $(grep -c "^\[WARN\]" audit.log)
- PASS: $(grep -c "^\[PASS\]" audit.log)
- INFO: $(grep -c "^\[INFO\]" audit.log)
EOF

Remediation and Hardening

Fix security issues identified in audits.

Common remediation examples:

# FAIL: Daemon not running as non-root
# Fix: Configure Rootless Docker
dockerd-rootless-setuptool.sh install

# FAIL: No TLS authentication
# Fix: Configure TLS certificates
mkdir -p /etc/docker/certs.d
# Add TLS cert and key

# FAIL: Privileged containers
# Fix: Run without --privileged flag
# Before: docker run --privileged myapp
# After: docker run myapp

# FAIL: Sensitive mounts
# Fix: Remove /proc, /sys mounts
# Before: docker run -v /proc:/proc myapp
# After: docker run -v /data:/data myapp (necessary mounts only)

Hardening daemon configuration:

# Configure daemon.json with security settings
cat > /etc/docker/daemon.json <<'EOF'
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "userland-proxy": false,
  "selinux-enabled": true,
  "icc": false,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  }
}
EOF

# Restart daemon to apply
systemctl restart docker

# Re-run audit to verify fixes
docker-bench-security

Filesystem permission hardening:

# Fix /var/lib/docker ownership
sudo chown root:root /var/lib/docker
sudo chmod 700 /var/lib/docker

# Fix /var/run/docker.sock
sudo chown root:docker /var/run/docker.sock
sudo chmod 660 /var/run/docker.sock

# Verify permissions
ls -l /var/lib/docker
ls -l /var/run/docker.sock

# Re-audit to confirm PASS

Automated Compliance Checking

Automate regular security audits.

Scheduled audit execution:

# Create audit script
cat > /usr/local/bin/run-docker-bench.sh <<'EOF'
#!/bin/bash

REPORT_DIR="/var/log/docker-bench"
mkdir -p "$REPORT_DIR"

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
REPORT="$REPORT_DIR/audit_$TIMESTAMP.txt"

docker run --rm \
  --net host \
  --userns host \
  --pid host \
  --cap-add audit_read \
  --volume /etc:/etc:ro \
  --volume /lib/systemd/system:/lib/systemd/system:ro \
  --volume /usr/bin/docker:/usr/bin/docker:ro \
  --volume /var/lib:/var/lib:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  docker/docker-bench-security > "$REPORT" 2>&1

# Count failures
FAIL_COUNT=$(grep -c "^\[FAIL\]" "$REPORT")

# Alert if failures found
if [ $FAIL_COUNT -gt 0 ]; then
    echo "Docker Bench security audit found $FAIL_COUNT failures"
    echo "Report: $REPORT"
    # Send alert (email, Slack, etc.)
fi

# Keep last 30 days of reports
find "$REPORT_DIR" -name "audit_*.txt" -mtime +30 -delete

EOF

chmod +x /usr/local/bin/run-docker-bench.sh

# Schedule daily execution
cat > /etc/cron.d/docker-bench <<'EOF'
# Run Docker Bench daily at 2 AM
0 2 * * * root /usr/local/bin/run-docker-bench.sh
EOF

Continuous integration audit:

# GitLab CI example
cat > .gitlab-ci.yml <<'EOF'
security-audit:
  stage: test
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker run --rm \
        --net host \
        --userns host \
        --pid host \
        --cap-add audit_read \
        --volume /etc:/etc:ro \
        --volume /var/lib:/var/lib:ro \
        --volume /var/run/docker.sock:/var/run/docker.sock:ro \
        docker/docker-bench-security | tee audit.log
    - FAIL_COUNT=$(grep -c "^\[FAIL\]" audit.log || echo 0)
    - |
      if [ $FAIL_COUNT -gt 0 ]; then
        echo "Security audit found $FAIL_COUNT critical issues"
        exit 1
      fi
  artifacts:
    paths:
      - audit.log
    expire_in: 30 days
EOF

Integration with DevOps Workflows

Integrate Docker Bench into deployment pipelines.

Pre-deployment security gate:

# Kubernetes admission controller webhook
# Validates container security on admission

cat > /etc/kubernetes/docker-bench-webhook.yaml <<'EOF'
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: docker-bench
webhooks:
  - name: docker-bench.local
    clientConfig:
      service:
        name: docker-bench
        namespace: kube-system
        path: "/validate"
      caBundle: LS0tLS1CRUdJTi...
    rules:
      - operations: ["CREATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
    failurePolicy: Fail
EOF

Artifact scanning in CI/CD:

# Container image scanning before push
cat > Jenkinsfile <<'EOF'
pipeline {
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:latest .'
            }
        }
        stage('Security Scan') {
            steps {
                sh '''
                    docker run --rm \
                      -v /var/run/docker.sock:/var/run/docker.sock \
                      docker/docker-bench-security \
                      --containers > scan_results.txt
                    
                    FAIL_COUNT=$(grep -c "\\[FAIL\\]" scan_results.txt || echo 0)
                    if [ $FAIL_COUNT -gt 0 ]; then
                        echo "Security scan failed"
                        exit 1
                    fi
                '''
            }
        }
        stage('Push') {
            steps {
                sh 'docker push myregistry.com/myapp:latest'
            }
        }
    }
}
EOF

Continuous Security Monitoring

Monitor and track security compliance over time.

Tracking compliance trends:

# Run weekly audits and track progress
cat > /usr/local/bin/track-compliance.sh <<'EOF'
#!/bin/bash

HISTORY_FILE="/var/log/docker-bench/compliance_history.csv"

# Initialize CSV if not exists
if [ ! -f "$HISTORY_FILE" ]; then
    echo "Date,PASS,WARN,FAIL,INFO" > "$HISTORY_FILE"
fi

# Run audit
REPORT=$(mktemp)
docker run --rm \
  --net host \
  --userns host \
  --pid host \
  --cap-add audit_read \
  --volume /etc:/etc:ro \
  --volume /var/lib:/var/lib:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  docker/docker-bench-security > "$REPORT" 2>&1

# Extract counts
PASS=$(grep -c "^\[PASS\]" "$REPORT")
WARN=$(grep -c "^\[WARN\]" "$REPORT")
FAIL=$(grep -c "^\[FAIL\]" "$REPORT")
INFO=$(grep -c "^\[INFO\]" "$REPORT")

# Append to history
DATE=$(date +%Y-%m-%d)
echo "$DATE,$PASS,$WARN,$FAIL,$INFO" >> "$HISTORY_FILE"

# Show trend
tail -10 "$HISTORY_FILE"

EOF

chmod +x /usr/local/bin/track-compliance.sh

# Schedule weekly
cat > /etc/cron.d/track-compliance <<'EOF'
# Run weekly on Monday at 9 AM
0 9 * * 1 root /usr/local/bin/track-compliance.sh
EOF

Alert on compliance regression:

# Alert if failures increase from previous run
cat > /usr/local/bin/check-compliance-regression.sh <<'EOF'
#!/bin/bash

HISTORY="/var/log/docker-bench/compliance_history.csv"

if [ ! -f "$HISTORY" ]; then
    echo "No history available"
    exit 0
fi

PREVIOUS=$(tail -2 "$HISTORY" | head -1 | cut -d',' -f4)
CURRENT=$(tail -1 "$HISTORY" | cut -d',' -f4)

if [ $CURRENT -gt $PREVIOUS ]; then
    echo "ALERT: Compliance regression detected"
    echo "Previous failures: $PREVIOUS"
    echo "Current failures: $CURRENT"
    # Send alert
fi

EOF

chmod +x /usr/local/bin/check-compliance-regression.sh

Conclusion

Docker Bench for Security provides essential automated auditing capabilities that ensure your Docker infrastructure meets security best practices and compliance standards. By regularly running audits, understanding findings, and implementing remediation, you maintain a hardened, secure container environment. Start with baseline audits to identify critical issues, progressively remediate findings, and eventually integrate automated compliance checking into your deployment pipelines. Regular security audits, combined with proactive hardening and compliance monitoring, create a security-first Docker culture. Make Docker Bench security audits a standard practice in your organization, tracking improvements over time and ensuring continuous security posture enhancement. As container security threats evolve, staying current with security benchmarks and regularly auditing your infrastructure becomes increasingly critical to business security.