Anthropic-Cybersecurity-Skills hardening-docker-daemon-configuration
Harden the Docker daemon by configuring daemon.json with user namespace remapping, TLS authentication, rootless
install
source · Clone the upstream repo
git clone https://github.com/mukul975/Anthropic-Cybersecurity-Skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/mukul975/Anthropic-Cybersecurity-Skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/hardening-docker-daemon-configuration" ~/.claude/skills/mukul975-anthropic-cybersecurity-skills-hardening-docker-daemon-configuration && rm -rf "$T"
manifest:
skills/hardening-docker-daemon-configuration/SKILL.mdsource content
Hardening Docker Daemon Configuration
Overview
The Docker daemon (
dockerd) runs with root privileges and controls all container operations. Hardening its configuration through /etc/docker/daemon.json, TLS certificates, user namespace remapping, and network restrictions is essential to prevent privilege escalation, lateral movement, and container breakout attacks.
When to Use
- When deploying or configuring hardening docker daemon configuration capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- Docker Engine 24.0+ installed
- Root or sudo access to the Docker host
- OpenSSL for TLS certificate generation
- Understanding of Linux namespaces and cgroups
Core Hardened daemon.json
{ "icc": false, "userns-remap": "default", "no-new-privileges": true, "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "5" }, "storage-driver": "overlay2", "live-restore": true, "userland-proxy": false, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 65536, "Soft": 32768 }, "nproc": { "Name": "nproc", "Hard": 4096, "Soft": 2048 } }, "seccomp-profile": "/etc/docker/seccomp/default.json", "default-address-pools": [ { "base": "172.17.0.0/16", "size": 24 } ], "iptables": true, "ip-forward": true, "ip-masq": true, "experimental": false, "metrics-addr": "127.0.0.1:9323", "max-concurrent-downloads": 3, "max-concurrent-uploads": 5, "default-runtime": "runc", "runtimes": { "runsc": { "path": "/usr/local/bin/runsc", "runtimeArgs": ["--platform=ptrace"] } } }
Setting-by-Setting Explanation
Disable Inter-Container Communication (ICC)
{ "icc": false }
Prevents containers on the default bridge network from communicating. Each container must use explicit
--link or user-defined networks with published ports.
Enable User Namespace Remapping
{ "userns-remap": "default" }
Maps container root (UID 0) to a high unprivileged UID on the host. This prevents a container breakout from gaining root on the host.
# Verify userns-remap is active cat /etc/subuid # Output: dockremap:100000:65536 cat /etc/subgid # Output: dockremap:100000:65536 # Verify container UID mapping docker run --rm alpine id # uid=0(root) gid=0(root) -- but host UID is 100000+
Disable New Privilege Escalation
{ "no-new-privileges": true }
Prevents container processes from gaining additional privileges via setuid/setgid binaries or capability escalation.
Enable Live Restore
{ "live-restore": true }
Keeps containers running during daemon downtime, enabling daemon upgrades without container restart.
Disable Userland Proxy
{ "userland-proxy": false }
Uses iptables rules instead of docker-proxy for port forwarding, reducing attack surface and improving performance.
TLS Configuration for Remote Docker API
Generate CA and Server Certificates
# Create CA openssl genrsa -aes256 -out ca-key.pem 4096 openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem \ -subj "/CN=Docker CA" # Create server key and CSR openssl genrsa -out server-key.pem 4096 openssl req -subj "/CN=docker-host" -sha256 -new -key server-key.pem -out server.csr # Create extfile with SANs echo "subjectAltName = DNS:docker-host,IP:10.0.0.5,IP:127.0.0.1" > extfile.cnf echo "extendedKeyUsage = serverAuth" >> extfile.cnf # Sign server certificate openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \ -CAcreateserial -out server-cert.pem -extfile extfile.cnf # Create client key and certificate openssl genrsa -out key.pem 4096 openssl req -subj "/CN=client" -new -key key.pem -out client.csr echo "extendedKeyUsage = clientAuth" > extfile-client.cnf openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \ -CAcreateserial -out cert.pem -extfile extfile-client.cnf # Set permissions chmod 0400 ca-key.pem key.pem server-key.pem chmod 0444 ca.pem server-cert.pem cert.pem # Move to Docker TLS directory sudo mkdir -p /etc/docker/tls sudo cp ca.pem server-cert.pem server-key.pem /etc/docker/tls/
Configure daemon.json for TLS
{ "tls": true, "tlsverify": true, "tlscacert": "/etc/docker/tls/ca.pem", "tlscert": "/etc/docker/tls/server-cert.pem", "tlskey": "/etc/docker/tls/server-key.pem", "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"] }
Client Connection
docker --tlsverify \ --tlscacert=ca.pem \ --tlscert=cert.pem \ --tlskey=key.pem \ -H=tcp://docker-host:2376 version
Docker Socket Protection
# Restrict socket ownership sudo chown root:docker /var/run/docker.sock sudo chmod 660 /var/run/docker.sock # Audit Docker socket access sudo auditctl -w /var/run/docker.sock -k docker-socket # Never mount Docker socket into containers # BAD: docker run -v /var/run/docker.sock:/var/run/docker.sock ...
Rootless Docker
# Install rootless Docker curl -fsSL https://get.docker.com/rootless | sh # Configure environment export PATH=$HOME/bin:$PATH export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock # Start rootless daemon systemctl --user start docker systemctl --user enable docker # Verify rootless mode docker info | grep -i rootless # Rootless: true
Content Trust (Image Signing)
# Enable Docker Content Trust export DOCKER_CONTENT_TRUST=1 # Pull only signed images docker pull library/alpine:3.18 # Will fail if image is not signed # Sign and push image docker trust sign myregistry/myapp:1.0
Seccomp Profile
# View default seccomp profile docker info --format '{{.SecurityOptions}}' # Use custom seccomp profile docker run --security-opt seccomp=/etc/docker/seccomp/custom.json alpine # Verify seccomp is enabled docker inspect --format='{{.HostConfig.SecurityOpt}}' container_name
AppArmor Profile
# Check AppArmor status sudo aa-status # Use custom AppArmor profile docker run --security-opt apparmor=docker-custom alpine # Load custom profile sudo apparmor_parser -r /etc/apparmor.d/docker-custom
Verification Commands
# Check daemon configuration docker info # Verify userns-remap docker info --format '{{.SecurityOptions}}' # Check ICC setting docker network inspect bridge --format '{{.Options}}' # Audit with Docker Bench docker run --rm --net host --pid host \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /etc:/etc:ro \ docker/docker-bench-security
Best Practices
- Never expose Docker daemon without TLS - Always use
for remote access--tlsverify - Enable user namespace remapping - Map container root to unprivileged host UID
- Disable ICC - Prevent default bridge network container-to-container communication
- Use rootless mode - Run Docker daemon as non-root where possible
- Enable content trust - Only pull signed images
- Configure log rotation - Prevent log files from filling disk
- Use seccomp profiles - Restrict syscalls available to containers
- Audit Docker socket - Monitor access to /var/run/docker.sock
- Run Docker Bench regularly - Automate CIS benchmark checks
- Keep Docker updated - Apply security patches promptly