Docker Security
Comprehensive security practices, vulnerability scanning, and hardening techniques for Docker containers and images.
Image Security
Secure Base Images
# Use official images from trusted sources
FROM node:18-alpine # ✓ Official Node.js image
FROM alpine:3.18 # ✓ Minimal, frequently updated
FROM distroless/java # ✓ Distroless for production
# Avoid unofficial or outdated images
FROM random/node # ✗ Unofficial source
FROM ubuntu:14.04 # ✗ Outdated version
FROM node:latest # ✗ Unpredictable updates
Image Vulnerability Scanning
# Docker Scout (built-in)
docker scout quickview image_name
docker scout cves image_name
docker scout recommendations image_name
# Trivy scanner
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# Snyk scanner
docker run --rm -v $(pwd):/project \
snyk/snyk test --docker myapp:latest
# Clair scanner
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
quay.io/coreos/clair:latest
# Anchore scanner
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
anchore/engine-cli anchore-cli image add myapp:latest
Secure Image Building
# Multi-stage builds to reduce attack surface
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:18-alpine AS runtime
WORKDIR /app
# Copy only necessary files
COPY /app/node_modules ./node_modules
COPY . .
# Remove unnecessary files
RUN rm -rf /tmp/* /var/cache/apk/*
# Use specific versions
FROM node:18.17.0-alpine3.18 # ✓ Specific version
FROM node:18-alpine # ✓ Acceptable
FROM node:latest # ✗ Unpredictable
# Update packages during build
RUN apk update && apk upgrade && apk add --no-cache curl
RUN apt-get update && apt-get upgrade -y && apt-get clean
Container Runtime Security
User Management
# Create and use non-root user
FROM alpine:3.18
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
USER appuser
# Alternative approach
FROM node:18-alpine
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 -G nodejs
COPY . /app
USER nextjs
Container Security Options
# Drop all capabilities and add only necessary ones
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
# Run with read-only filesystem
docker run --read-only --tmpfs /tmp --tmpfs /var/run nginx
# Disable new privileges
docker run --security-opt no-new-privileges nginx
# Set AppArmor profile
docker run --security-opt apparmor:docker-default nginx
# Set SELinux labels
docker run --security-opt label=level:s0:c123,c456 nginx
# Use user namespace remapping
docker run --userns-remap=default nginx
# Limit resources
docker run --memory=512m --cpus=1.0 --pids-limit=100 nginx
Secrets Management
# Use Docker secrets (Swarm mode)
echo "mysecret" | docker secret create db_password -
docker service create --secret db_password myapp
# Use external secret management
docker run -e API_KEY_FILE=/run/secrets/api_key \
-v /path/to/secrets:/run/secrets:ro \
myapp
# Avoid secrets in environment variables
docker run -e DATABASE_URL="postgres://user:password@host/db" myapp # ✗ Bad
# Use secret files instead
docker run -v /secrets/db_creds:/run/secrets/db_creds:ro myapp # ✓ Good
Network Security
Network Isolation
# Create isolated network
docker network create --internal isolated-network
# Disable inter-container communication
docker network create --opt com.docker.network.bridge.enable_icc=false secure-net
# Use custom bridge with specific subnet
docker network create --subnet=172.30.0.0/24 --gateway=172.30.0.1 private-net
# Host network (use carefully)
docker run --network host nginx # Shares host networking stack
Port Security
# Bind to localhost only
docker run -p 127.0.0.1:8080:80 nginx
# Specific interface binding
docker run -p 192.168.1.100:8080:80 nginx
# Avoid binding to all interfaces
docker run -p 8080:80 nginx # ✗ Binds to 0.0.0.0
docker run -p 0.0.0.0:8080:80 nginx # ✗ Explicit all interfaces
# Use random host ports for non-public services
docker run -P nginx # Random host ports
TLS and Encryption
# Enable Docker daemon TLS
dockerd --tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
# Connect with TLS client
docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=tcp://docker-host:2376 version
Docker Daemon Security
Daemon Configuration
{
"live-restore": true,
"userland-proxy": false,
"no-new-privileges": true,
"seccomp-profile": "/etc/docker/seccomp.json",
"apparmor-profile": "docker-default",
"selinux-enabled": true,
"userns-remap": "default",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Access Control
# Create docker group (if not exists)
sudo groupadd docker
# Add user to docker group
sudo usermod -aG docker $USER
# Set proper permissions on docker socket
sudo chmod 660 /var/run/docker.sock
sudo chown root:docker /var/run/docker.sock
# Use rootless Docker
dockerd-rootless-setuptool.sh install
systemctl --user start docker
Audit and Logging
# Enable audit logging
dockerd --log-level=debug
# Configure centralized logging
docker run --log-driver=syslog nginx
docker run --log-driver=fluentd --log-opt fluentd-address=localhost:24224 nginx
# Monitor Docker events
docker events --filter type=container --filter event=start
# Use audit framework
auditctl -w /var/run/docker.sock -p rwxa -k docker
auditctl -w /usr/bin/docker -p rwxa -k docker
Container Hardening
Runtime Security
# Use security profiles
docker run --security-opt seccomp=seccomp-profile.json nginx
docker run --security-opt apparmor=custom-profile nginx
# Limit system calls
docker run --security-opt seccomp=unconfined nginx # ✗ Dangerous
docker run --security-opt seccomp=seccomp-profile.json nginx # ✓ Restricted
# Resource limits
docker run \
--memory=512m \
--memory-swap=512m \
--cpus=1.0 \
--pids-limit=100 \
--ulimit nofile=1024:1024 \
nginx
File System Security
# Use read-only root filesystem
FROM alpine:3.18
RUN mkdir -p /app/tmp /app/logs
VOLUME ["/app/tmp", "/app/logs"]
# Application runs with read-only root filesystem
# Run with read-only filesystem
docker run --read-only \
--tmpfs /tmp \
--tmpfs /var/run \
--tmpfs /var/log \
nginx
Capability Management
# Drop all capabilities
docker run --cap-drop ALL nginx
# Add only required capabilities
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
docker run --cap-drop ALL --cap-add CHOWN --cap-add DAC_OVERRIDE nginx
# Common capability combinations
# Web server
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
# Database
docker run --cap-drop ALL --cap-add CHOWN --cap-add DAC_OVERRIDE postgres
# Monitoring tools
docker run --cap-drop ALL --cap-add SYS_PTRACE monitoring-app
Security Scanning and Compliance
Automated Security Scanning
# CI/CD integration with Trivy
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest
# Docker Bench Security
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /etc:/etc:ro \
--label docker_bench_security \
docker/docker-bench-security
# CIS Docker Benchmark
docker run --rm -it --net host --pid host --cap-add audit_control \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /etc:/etc:ro \
aquasec/docker-bench
Content Trust
# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1
# Pull only signed images
docker pull alpine:latest # Will verify signature
# Push signed images
docker push myregistry/myapp:latest # Will sign image
# Disable for specific command
DOCKER_CONTENT_TRUST=0 docker pull untrusted-image
Image Signing
# Generate signing keys
docker trust key generate mykey
# Add signer to repository
docker trust signer add --key mykey.pub mykey myregistry/myapp
# Sign and push image
docker trust sign myregistry/myapp:latest
# Verify image signature
docker trust inspect myregistry/myapp:latest
Security Best Practices
Development Security
# Secure Dockerfile practices
FROM node:18-alpine
# Don't run as root
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001 -G nodejs
# Install security updates
RUN apk update && apk upgrade
# Copy files with correct ownership
COPY package*.json ./
RUN npm ci --only=production
# Remove unnecessary packages
RUN apk del .build-deps
# Switch to non-root user
USER nextjs
# Use COPY instead of ADD
COPY app.js . # ✓ Secure
ADD app.js . # ✗ Less secure
# Don't store secrets in images
# ENV SECRET_KEY=secret123 # ✗ Bad
# Use runtime secrets instead
Production Security
# docker-compose.yml security configuration
version: '3.8'
services:
web:
image: myapp:latest
read_only: true
tmpfs:
- /tmp
- /var/run
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
- apparmor:docker-default
ulimits:
nofile:
soft: 1024
hard: 1024
mem_limit: 512m
cpus: 1.0
pids_limit: 100
Security Monitoring
# Monitor security events
docker events --filter type=container --filter event=die
# Regular security scans
# Schedule daily scans
0 2 * * * docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image --quiet $(docker images --format "{{.Repository}}:{{.Tag}}")
# Monitor for new vulnerabilities
docker scout watch myapp:latest
Quick Security Checklist
Image Security
- Use official base images
- Keep base images updated
- Scan images for vulnerabilities
- Use specific image tags
- Remove unnecessary packages
- Don't store secrets in images
Runtime Security
- Run as non-root user
- Use read-only filesystems
- Drop unnecessary capabilities
- Set resource limits
- Use security profiles
- Enable content trust
Network Security
- Use custom networks
- Avoid host networking
- Bind ports to specific interfaces
- Enable network encryption
- Implement network segmentation
Operational Security
- Regular security updates
- Audit container configurations
- Monitor security events
- Implement secrets management
- Use least privilege principle
- Regular vulnerability assessments
Security Tools Reference
Vulnerability Scanners
- Trivy - Comprehensive vulnerability scanner
- Docker Scout - Built-in Docker security scanning
- Snyk - Developer-first security scanning
- Anchore - Enterprise container security
- Clair - Open source vulnerability scanner
Security Frameworks
- CIS Docker Benchmark - Security configuration guide
- NIST Container Security - Federal security guidelines
- Docker Bench Security - Automated security checks
Compliance Tools
- Open Policy Agent (OPA) - Policy-based control
- Falco - Runtime security monitoring
- Gatekeeper - Kubernetes policy controller