CIS Docker Benchmark

Secure configuration guidelines for Docker Engine and container workloads

v1.7.0 January 2025

Overview

▶

This CIS Benchmark provides prescriptive guidance for establishing a secure configuration posture for Docker Engine. It covers host configuration, daemon security, container images, runtime security, and operational best practices.

~180Recommendations
5Sections
2Profile Levels
SectionAreaRecommendationsFocus
1Host Configuration~35Filesystem, partitioning, audit daemon
2Docker Daemon Configuration~50Network, security features, runtime options
3Container Images~25Image provenance, Dockerfile hardening
4Container Runtime~45Security config, resource limits, capabilities
5Docker Security Operations~25Secrets management, Swarm security

Profile Definitions

▶
ProfileDescriptionIntended Use
L1Level 1 — Base SecurityEssential security settings for all Docker deployments. Minimal operational impact.
L2Level 2 — Defense in DepthAdvanced hardening for high-security environments. May require changes to workflows.

1 — Host Configuration

▶

Recommendations for securing the Docker host operating system, filesystem layout, and audit configuration.

1.1 Filesystem & Partitioning

▶
1.1.1 Ensure a Separate Partition for /var/lib/docker Exists (Automated)
L1 Auto
Description

Docker stores all images, containers, and local volumes under /var/lib/docker. A dedicated partition prevents container storage from filling the root filesystem.

Rationale

The absence of a Separate Partition for /var/lib/docker leaves the Docker container platform without an important security control. Verifying its presence ensures the system meets the minimum security baseline required by the CIS benchmark.

Audit
mountpoint /var/lib/docker
# Should return: /var/lib/docker is a mountpoint

grep '/var/lib/docker' /etc/fstab
Remediation

Create a dedicated partition or logical volume for /var/lib/docker and add it to /etc/fstab.

1.1.2 Ensure Only Trusted Users Are in the Docker Group (Manual)
L1 Manual
Description

Members of the docker group have root-equivalent privileges on the host via Docker socket access. Limit group membership to trusted users only.

Rationale

Failure to only Trusted Users Are in the Docker Group may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
getent group docker
# Review all listed users
Remediation
# Remove untrusted users:
gpasswd -d <user> docker
1.1.3 Ensure Docker Socket Permissions Are Restrictive (Automated)
L1 Auto
Description

The Docker socket /var/run/docker.sock provides root-level access to the host via Docker API. Restrict its permissions.

Rationale

Incorrect permissions on Docker Socket could allow unauthorized reading, writing, or execution of critical files. Proper file permissions are a foundational control that prevents privilege escalation and data tampering.

Audit
stat -c '%U:%G %a' /var/run/docker.sock
# Should be root:docker 660
Remediation
chown root:docker /var/run/docker.sock
chmod 660 /var/run/docker.sock

1.2 Audit & Logging

▶
1.2.1 Ensure Auditing Is Configured for Docker Files (Automated)
L1 Auto
Description

Configure Linux audit rules for Docker files and directories. Audit events provide traceability for security investigations.

Rationale

Failure to auditing Is Configured for Docker Files may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
auditctl -l | grep docker
# Should include rules for:
# /usr/bin/dockerd, /var/lib/docker, /etc/docker,
# /var/run/docker.sock, /etc/default/docker
Remediation
# Add to /etc/audit/rules.d/docker.rules:
-w /usr/bin/dockerd -k docker
-w /var/lib/docker -k docker
-w /etc/docker -k docker
-w /var/run/docker.sock -k docker
-w /usr/lib/systemd/system/docker.service -k docker
-w /usr/lib/systemd/system/docker.socket -k docker
-w /etc/default/docker -k docker
-w /etc/docker/daemon.json -k docker

# Restart auditd:
systemctl restart auditd
1.2.2 Ensure Docker Daemon Logging Is Configured (Automated)
L1 Auto
Description

Configure a logging driver for the Docker daemon. The default json-file driver stores logs locally. For production, use a centralized logging driver.

Rationale

Misconfiguration of Docker Daemon Logging can lead to security gaps that may be exploited by attackers. A properly configured Docker container platform reduces exposure to both known vulnerabilities and configuration drift.

Audit
docker info --format '{{ .LoggingDriver }}'
# Should return the configured driver

cat /etc/docker/daemon.json | jq '.["log-driver"]'
Remediation
# /etc/docker/daemon.json:
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

2 — Docker Daemon Configuration

▶

Recommendations for securing the Docker daemon including network configuration, security features, and runtime options.

2.1 Network Configuration

▶
2.1.1 Ensure Network Traffic Is Restricted Between Containers (Automated)
L1 Auto
Description

By default, all containers on the same Docker bridge network can communicate. Disable inter-container communication and use explicit links or networks.

Rationale

Failure to network Traffic Is Restricted Between Containers may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker network inspect bridge --format '{{ .Options }}'
# Check com.docker.network.bridge.enable_icc is false

# Or:
ps -ef | grep dockerd | grep -- '--icc'
Remediation
# /etc/docker/daemon.json:
{
  "icc": false
}
2.1.2 Ensure Docker Daemon Does Not Listen on TCP (Automated)
L1 Auto
Description

Do not bind the Docker daemon to a TCP socket. The Docker daemon should only listen on the local Unix socket unless remote access is explicitly required with TLS.

Rationale

Failure to docker Daemon Does Not Listen on TCP may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
ps -ef | grep dockerd | grep -- '-H'
# Should not show tcp:// bindings

cat /etc/docker/daemon.json | jq '.hosts'
Remediation

Remove any -H tcp:// arguments. If remote access is required, use TLS mutual authentication:

{
  "hosts": ["unix:///var/run/docker.sock"],
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "tlsverify": true
}
2.1.3 Ensure iptables Rules Are Not Altered by Docker (Manual)
L2 Manual
Description

Docker modifies iptables rules to provide network isolation. Review changes and consider setting --iptables=false when managing firewall rules externally.

Rationale

Failure to iptables Rules Are Not Altered by Docker may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
iptables -L -n | grep DOCKER
# Review Docker-managed chains
Remediation

If using external firewall management, set "iptables": false in daemon.json and manage rules manually.

2.2 Security Features

▶
2.2.1 Ensure User Namespace Support Is Enabled (Manual)
L2 Manual
Description

Enable user namespace remapping so that root inside the container maps to an unprivileged user on the host, reducing the impact of container breakout.

Rationale

Without User Namespace Support enabled, the Docker container platform may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
docker info --format '{{ .SecurityOptions }}'
# Should include userns

cat /etc/docker/daemon.json | jq '.["userns-remap"]'
Remediation
# /etc/docker/daemon.json:
{
  "userns-remap": "default"
}

# Verify subordinate UID/GID:
cat /etc/subuid
cat /etc/subgid
2.2.2 Ensure Content Trust Is Enabled (Manual)
L2 Manual
Description

Enable Docker Content Trust (DCT) to verify image publisher identity and image integrity using digital signatures.

Rationale

Without Content Trust enabled, the Docker container platform may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
echo $DOCKER_CONTENT_TRUST
# Should be 1
Remediation
export DOCKER_CONTENT_TRUST=1
# Add to /etc/environment or shell profile for persistence
2.2.3 Ensure AppArmor or SELinux Is Enabled (Automated)
L1 Auto
Description

Ensure a MAC (Mandatory Access Control) system like AppArmor or SELinux is active. Docker uses these to confine container processes.

Rationale

Without AppArmor or SELinux enabled, the Docker container platform may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
# AppArmor:
docker info --format '{{ .SecurityOptions }}'
# Should include apparmor

# SELinux:
getenforce
# Should return Enforcing
Remediation
# For SELinux (RHEL/CentOS):
setenforce 1
# In /etc/selinux/config: SELINUX=enforcing

# For AppArmor (Ubuntu/Debian):
systemctl enable apparmor
systemctl start apparmor
2.2.4 Ensure Seccomp Profile Is Applied (Automated)
L1 Auto
Description

Apply seccomp profiles to containers to restrict the system calls available to the container process. Docker applies a default seccomp profile that blocks ~44 syscalls.

Rationale

Failure to seccomp Profile Is Applied may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker inspect --format '{{ .HostConfig.SecurityOpt }}' <container_id>
# Should include seccomp profile or show default is active

docker info --format '{{ .SecurityOptions }}'
# Should include seccomp
Remediation

Do not run containers with --security-opt seccomp=unconfined. Use the default profile or create custom profiles:

docker run --security-opt seccomp=/path/to/custom-profile.json ...

2.3 Runtime Options

▶
2.3.1 Ensure Live Restore Is Enabled (Automated)
L1 Auto
Description

Enable live restore so containers continue running when the Docker daemon is restarted. This reduces downtime during daemon upgrades.

Rationale

Without Live Restore enabled, the Docker container platform may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
docker info --format '{{ .LiveRestoreEnabled }}'
# Should return true
Remediation
# /etc/docker/daemon.json:
{
  "live-restore": true
}
2.3.2 Ensure Default ulimits Are Configured (Manual)
L1 Manual
Description

Set default ulimits for all containers at the daemon level. This prevents resource exhaustion from individual containers.

Rationale

Misconfiguration of Default ulimits can lead to security gaps that may be exploited by attackers. A properly configured Docker container platform reduces exposure to both known vulnerabilities and configuration drift.

Audit
docker info --format '{{ .DefaultUlimits }}'
Remediation
# /etc/docker/daemon.json:
{
  "default-ulimits": {
    "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 65536 },
    "nproc": { "Name": "nproc", "Hard": 4096, "Soft": 4096 }
  }
}

3 — Container Images

▶

Recommendations for securing Docker container images, including provenance verification and Dockerfile hardening.

3.1 Image Provenance

▶
3.1.1 Ensure Images Are Scanned for Vulnerabilities (Manual)
L1 Manual
Description

Scan all container images for known vulnerabilities before use. Integrate scanning into CI/CD pipelines.

Rationale

Failure to images Are Scanned for Vulnerabilities may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Using Trivy:
trivy image <image_name>

# Using Docker Scout:
docker scout cves <image_name>

# Using Grype:
grype <image_name>
Remediation

Integrate image scanning into CI/CD. Block deployments with critical or high CVEs. Rebuild images with updated base images.

3.1.2 Ensure Only Trusted Base Images Are Used (Manual)
L1 Manual
Description

Use official or verified Docker images as base images. Untrusted base images may contain backdoors or unpatched vulnerabilities.

Rationale

Failure to only Trusted Base Images Are Used may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker images --format '{{ .Repository }}:{{ .Tag }}'
# Review base images used in Dockerfiles

grep -r '^FROM' */Dockerfile
Remediation

Use Docker Official Images, Verified Publisher images, or images from your organization's private registry. Pin images to specific digests.

3.2 Image Hardening

▶
3.2.1 Ensure a Non-Root USER Is Specified in Dockerfile (Automated)
L1 Auto
Description

Containers should run as a non-root user. Include a USER directive in Dockerfiles to ensure processes don't run as root.

Rationale

Failure to a Non-Root USER Is Specified in Dockerfile may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check running containers:
docker inspect --format '{{ .Config.User }}' <container_id>
# Should not be empty or root/0

# Check Dockerfile:
grep '^USER' Dockerfile
Remediation
FROM ubuntu:22.04
RUN groupadd -r appuser && useradd -r -g appuser appuser
# ... install dependencies ...
USER appuser
CMD ["app"]
3.2.2 Ensure HEALTHCHECK Is Defined (Automated)
L1 Auto
Description

Include a HEALTHCHECK instruction in Dockerfiles. Health checks enable Docker to detect and restart unhealthy containers.

Rationale

Failure to hEALTHCHECK Is Defined may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker inspect --format '{{ .Config.Healthcheck }}' <container_id>
# Should not be <nil>
Remediation
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1
3.2.3 Ensure COPY Is Used Instead of ADD (Automated)
L1 Auto
Description

Use COPY instead of ADD in Dockerfiles. ADD has extra features (tar extraction, URL fetching) that can introduce unexpected behavior and security risks.

Rationale

Failure to cOPY Is Used Instead of ADD may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
grep '^ADD' Dockerfile
# Should only appear for legitimate tar extraction needs
Remediation

Replace ADD <src> <dest> with COPY <src> <dest> unless tar auto-extraction is explicitly needed.

3.2.4 Ensure No Secrets Are Stored in Images (Manual)
L1 Manual
Description

Do not embed secrets, passwords, keys, or tokens in Docker images. Secrets in images persist in all layers and can be extracted.

Rationale

Failure to no Secrets Are Stored in Images may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check for common secret patterns:
docker history --no-trunc <image_name> | grep -iE 'password|secret|key|token'

# Use tools like TruffleHog or Dockle:
dockle <image_name>
Remediation

Use Docker BuildKit secrets, environment variables at runtime, or a secrets manager. Use multi-stage builds to prevent secrets from leaking to final images.

4 — Container Runtime

▶

Recommendations for securing Docker container runtime configuration including security context, capabilities, and resource limits.

4.1 Security Configuration

▶
4.1.1 Ensure Privileged Mode Is Not Used (Automated)
L1 Auto
Description

Do not run containers in privileged mode. Privileged containers have full access to the host's devices and kernel capabilities.

Rationale

If Privileged Mode remains used, it presents an unnecessary risk vector that attackers could exploit. Removing or disabling unused components is a fundamental principle of secure system hardening.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: Privileged={{ .HostConfig.Privileged }}'
# All should be false
Remediation

Remove the --privileged flag. Grant only needed capabilities using --cap-add.

4.1.2 Ensure No Containers Run with Root User (Automated)
L1 Auto
Description

Run containers as a non-root user. Use --user flag or USER instruction to specify a non-root UID.

Rationale

Failure to no Containers Run with Root User may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: User={{ .Config.User }}'
# Should not be empty or 0/root
Remediation
docker run --user 1000:1000 <image>
4.1.3 Ensure Docker Socket Is Not Mounted Inside Containers (Automated)
L1 Auto
Description

Never mount the Docker socket (/var/run/docker.sock) inside containers. This gives the container full control over the Docker daemon and host.

Rationale

Failure to docker Socket Is Not Mounted Inside Containers may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: {{ range .Mounts }}{{ .Source }} {{ end }}'  | grep docker.sock
# Should return empty
Remediation

Remove Docker socket mounts. For CI/CD, use Docker-in-Docker (DinD) with --privileged in isolated VMs, or use Kaniko/Buildah for image builds.

4.1.4 Ensure Containers Use Read-Only Root Filesystem (Automated)
L2 Auto
Description

Mount the container's root filesystem as read-only. Use volume mounts for directories that require write access.

Rationale

Failure to containers Use Read-Only Root Filesystem may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: ReadOnly={{ .HostConfig.ReadonlyRootfs }}'
# Should be true
Remediation
docker run --read-only --tmpfs /tmp:rw,noexec,nosuid <image>
4.1.5 Ensure All Capabilities Are Dropped (Automated)
L1 Auto
Description

Drop all Linux capabilities and only add those specifically needed. Docker grants a default set of capabilities that is more permissive than necessary.

Rationale

Failure to all Capabilities Are Dropped may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: CapDrop={{ .HostConfig.CapDrop }} CapAdd={{ .HostConfig.CapAdd }}'
Remediation
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE <image>

4.2 Resource Limits

▶
4.2.1 Ensure Memory Limits Are Set (Automated)
L1 Auto
Description

Set memory limits for all containers to prevent a single container from exhausting all host memory.

Rationale

Failure to memory Limits Are Set may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: Memory={{ .HostConfig.Memory }}'
# Should not be 0 (unlimited)
Remediation
docker run --memory=512m --memory-swap=1g <image>
4.2.2 Ensure CPU Limits Are Set (Automated)
L1 Auto
Description

Set CPU limits for all containers to prevent CPU monopolization by a single container.

Rationale

Failure to cPU Limits Are Set may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: CPUs={{ .HostConfig.NanoCpus }} CpuShares={{ .HostConfig.CpuShares }}'
Remediation
docker run --cpus=1.0 --cpu-shares=512 <image>
4.2.3 Ensure Container Restart Policy Is Set Appropriately (Automated)
L1 Auto
Description

Set a restart policy with a maximum retry count. Using always without a limit can mask crashes and consume resources during restart loops.

Rationale

Failure to container Restart Policy Is Set Appropriately may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: RestartPolicy={{ .HostConfig.RestartPolicy.Name }} MaxRetry={{ .HostConfig.RestartPolicy.MaximumRetryCount }}'
Remediation
docker run --restart=on-failure:5 <image>

5 — Docker Security Operations

▶

Recommendations for operational security including secrets management and Docker Swarm mode security.

5.1 Secrets & Credentials

▶
5.1.1 Ensure Secrets Are Managed Using Docker Secrets or External Tools (Manual)
L1 Manual
Description

Use Docker secrets (Swarm mode), Docker BuildKit secrets, or external secrets managers (Vault, AWS Secrets Manager) instead of environment variables for sensitive data.

Rationale

Failure to secrets Are Managed Using Docker Secrets or External Tools may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check for secrets in environment variables:
docker ps -q | xargs docker inspect --format \
  '{{ .Name }}: {{ .Config.Env }}' | grep -iE 'password|secret|key|token'

# List Docker secrets (Swarm mode):
docker secret ls
Remediation
# Docker Swarm secrets:
echo "my-secret-value" | docker secret create db_password -

# Docker BuildKit secrets:
docker build --secret id=mysecret,src=./secret.txt .

# In Dockerfile:
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
5.1.2 Ensure No Hardcoded Credentials in Docker Compose Files (Manual)
L1 Manual
Description

Do not hardcode passwords, API keys, or other credentials in docker-compose.yml files. Use environment variable substitution or Docker secrets.

Rationale

Failure to no Hardcoded Credentials in Docker Compose Files may leave the Docker container platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
grep -rn 'password\|secret\|api_key\|token' docker-compose*.yml
# Should not contain literal values
Remediation
# Use .env file or environment variable substitution:
environment:
  - DB_PASSWORD=${DB_PASSWORD}

# Or Docker secrets:
secrets:
  db_password:
    external: true

5.2 Swarm Mode Security

▶
5.2.1 Ensure Swarm Auto-Lock Is Enabled (Automated)
L1 Auto
Description

Enable Swarm autolock to encrypt the TLS key and Raft logs at rest. When autolock is enabled, a manager must provide the unlock key when restarting.

Rationale

Without Swarm Auto-Lock enabled, the Docker container platform may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
docker info | grep 'Is Manager'
# If manager:
docker swarm unlock-key
# Should not return "no unlock key is set"
Remediation
# Enable autolock:
docker swarm update --autolock=true

# Store the unlock key securely
5.2.2 Ensure Swarm Manager Nodes Are Limited (Manual)
L1 Manual
Description

Limit the number of Swarm manager nodes. Use an odd number (3 or 5) for fault tolerance while limiting the attack surface of manager-level access.

Rationale

Unrestricted Swarm Manager Nodes could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the Docker container platform is essential for defense in depth.

Audit
docker node ls --filter role=manager
# Should be 3 or 5 (odd number for Raft consensus)
Remediation

Demote excess managers: docker node demote <node-id>. Use 3 managers for small clusters, 5 for large ones.

5.2.3 Ensure Certificate Rotation Is Configured (Automated)
L1 Auto
Description

Configure certificate rotation for Swarm node certificates. Short certificate lifetimes reduce the window for compromised certificates.

Rationale

Misconfiguration of Certificate Rotation can lead to security gaps that may be exploited by attackers. A properly configured Docker container platform reduces exposure to both known vulnerabilities and configuration drift.

Audit
docker info | grep 'Expiry Duration'
# Should be 90 days or less
Remediation
docker swarm update --cert-expiry 720h