Docker Security and Optimization: Introduction and Setup
Docker security and performance optimization are critical for production deployments. This guide covers comprehensive security hardening, performance tuning, and operational best practices for containerized environments.
Docker Security Fundamentals
Security Model Overview
┌─────────────────────────────────────────────────────────┐
│ Host Operating System │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Kernel │ │ Namespaces │ │ cgroups │ │
│ │ Capabilities│ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ SELinux/ │ │ AppArmor │ │ seccomp │ │
│ │ AppArmor │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Docker Engine │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Container 1 │ │ Container 2 │ │ Container 3 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
Basic Security Commands
# Run container with security options
docker run --security-opt no-new-privileges:true \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
nginx
# Run as non-root user
docker run --user 1000:1000 \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
alpine id
# Limit resources
docker run --memory=512m \
--cpus="1.5" \
--pids-limit=100 \
--ulimit nofile=1024:1024 \
myapp
# Network security
docker run --network none alpine
docker run --network custom-network \
--ip 172.20.0.10 \
myapp
Container Hardening Basics
Secure Dockerfile Practices
# Use specific versions, not latest
FROM node:16.17.0-alpine3.16
# Create non-root user early
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 -G nodejs
# Set working directory
WORKDIR /app
# Copy package files first for better caching
COPY package*.json ./
# Install dependencies as root, then switch
RUN npm ci --only=production && \
npm cache clean --force && \
chown -R nextjs:nodejs /app
# Copy application files
COPY --chown=nextjs:nodejs . .
# Switch to non-root user
USER nextjs
# Remove unnecessary packages
RUN apk del --purge \
&& rm -rf /var/cache/apk/* \
&& rm -rf /tmp/*
# Set secure permissions
RUN chmod -R 755 /app && \
chmod 644 /app/package.json
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Expose port
EXPOSE 3000
# Use exec form for CMD
CMD ["node", "server.js"]
Runtime Security Configuration
# Comprehensive security flags
docker run -d \
--name secure-app \
--user 1000:1000 \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--tmpfs /var/run:rw,noexec,nosuid,size=50m \
--cap-drop ALL \
--cap-add CHOWN \
--cap-add SETGID \
--cap-add SETUID \
--security-opt no-new-privileges:true \
--security-opt apparmor:docker-default \
--security-opt seccomp:default \
--memory=512m \
--memory-swap=512m \
--cpu-shares=512 \
--pids-limit=100 \
--ulimit nofile=1024:1024 \
--ulimit nproc=64:64 \
--restart=unless-stopped \
myapp:latest
Performance Optimization Basics
Resource Management
# CPU optimization
docker run -d \
--cpus="2.5" \
--cpu-shares=1024 \
--cpuset-cpus="0,1" \
--cpu-quota=50000 \
--cpu-period=100000 \
myapp
# Memory optimization
docker run -d \
--memory=2g \
--memory-swap=2g \
--memory-reservation=1g \
--oom-kill-disable=false \
--kernel-memory=500m \
myapp
# I/O optimization
docker run -d \
--device-read-bps /dev/sda:50mb \
--device-write-bps /dev/sda:50mb \
--device-read-iops /dev/sda:1000 \
--device-write-iops /dev/sda:1000 \
myapp
# Network optimization
docker run -d \
--sysctl net.core.somaxconn=65535 \
--sysctl net.ipv4.tcp_max_syn_backlog=65535 \
--sysctl net.core.rmem_max=134217728 \
--sysctl net.core.wmem_max=134217728 \
myapp
Docker Daemon Optimization
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
},
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 5,
"default-shm-size": "128M",
"userland-proxy": false,
"experimental": false,
"metrics-addr": "127.0.0.1:9323",
"live-restore": true
}
Security Scanning and Assessment
Image Vulnerability Scanning
# Install and use Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# Scan image for vulnerabilities
trivy image nginx:latest
# Scan with specific severity
trivy image --severity HIGH,CRITICAL nginx:latest
# Scan and output to file
trivy image --format json --output results.json nginx:latest
# Scan filesystem
trivy fs .
# Scan with ignore file
trivy image --ignorefile .trivyignore nginx:latest
.trivyignore example:
# Ignore specific CVEs
CVE-2021-12345
CVE-2021-67890
# Ignore by package
pkg:npm/[email protected]
# Ignore by severity
MEDIUM
LOW
Container Runtime Security
# Use Docker Bench Security
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sudo ./docker-bench-security.sh
# Use Falco for runtime security
docker run -i -t \
--name falco \
--privileged \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
falcosecurity/falco:latest
# Use Sysdig for monitoring
docker run -d --name sysdig-agent \
--restart always \
--privileged \
--net host \
--pid host \
-e ACCESS_KEY=your-access-key \
-e SECURE=true \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /dev:/host/dev \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
sysdig/agent
Secrets Management
Docker Secrets (Swarm Mode)
# Create secret from file
echo "mypassword" | docker secret create db_password -
# Create secret from stdin
docker secret create ssl_cert cert.pem
# List secrets
docker secret ls
# Use secret in service
docker service create \
--name myapp \
--secret db_password \
--secret ssl_cert \
myapp:latest
# Access secret in container (available at /run/secrets/secret_name)
docker exec container cat /run/secrets/db_password
External Secrets Management
# docker-compose.yml with external secrets
version: '3.8'
services:
app:
image: myapp
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
- API_KEY_FILE=/run/secrets/api_key
secrets:
- db_password
- api_key
volumes:
- app_data:/data
vault:
image: vault:latest
cap_add:
- IPC_LOCK
environment:
- VAULT_DEV_ROOT_TOKEN_ID=myroot
- VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200
ports:
- "8200:8200"
secrets:
db_password:
external: true
api_key:
external: true
volumes:
app_data:
Monitoring and Logging Setup
Security Monitoring
# docker-compose.security-monitoring.yml
version: '3.8'
services:
# Security event collector
falco:
image: falcosecurity/falco:latest
privileged: true
volumes:
- /var/run/docker.sock:/host/var/run/docker.sock
- /dev:/host/dev
- /proc:/host/proc:ro
- /boot:/host/boot:ro
- /lib/modules:/host/lib/modules:ro
- /usr:/host/usr:ro
- ./falco/falco.yaml:/etc/falco/falco.yaml:ro
environment:
- FALCO_GRPC_ENABLED=true
- FALCO_GRPC_BIND_ADDRESS=0.0.0.0:5060
# Log aggregation
fluentd:
image: fluent/fluentd:latest
volumes:
- ./fluentd/fluent.conf:/fluentd/etc/fluent.conf:ro
- /var/log:/var/log:ro
ports:
- "24224:24224"
# Metrics collection
node-exporter:
image: prom/node-exporter:latest
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
# Container metrics
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
Performance Monitoring
# Monitor container performance
docker stats
# Detailed container inspection
docker exec container top
docker exec container ps aux
docker exec container netstat -tlnp
docker exec container iostat -x 1
# System-wide monitoring
htop
iotop
nethogs
iftop
# Docker system information
docker system df
docker system events
docker system info
Compliance and Governance
CIS Docker Benchmark
Key security controls:
-
Host Configuration
- Keep Docker up to date
- Use trusted users only
- Audit Docker daemon and files
- Set up proper logging
-
Docker Daemon Configuration
- Restrict network traffic between containers
- Set logging level to ‘info’
- Allow Docker to make changes to iptables
- Do not use insecure registries
-
Docker Daemon Configuration Files
- Verify ownership and permissions
- Secure Docker socket
- Protect Docker daemon configuration
-
Container Images and Build Files
- Create user for containers
- Use trusted base images
- Do not install unnecessary packages
- Scan images for vulnerabilities
-
Container Runtime
- Do not share host’s network namespace
- Limit memory usage
- Set container CPU priority appropriately
- Mount container’s root filesystem as read-only
Automated Compliance Checking
#!/bin/bash
# docker-security-audit.sh
echo "Docker Security Audit Report"
echo "============================"
echo "Date: $(date)"
echo
# Check Docker version
echo "1. Docker Version Check"
docker --version
echo
# Check running containers security
echo "2. Container Security Analysis"
for container in $(docker ps -q); do
echo "Container: $container"
# Check if running as root
user=$(docker inspect --format='{{.Config.User}}' $container)
if [ -z "$user" ]; then
echo " WARNING: Container running as root"
else
echo " OK: Running as user $user"
fi
# Check privileged mode
privileged=$(docker inspect --format='{{.HostConfig.Privileged}}' $container)
if [ "$privileged" = "true" ]; then
echo " WARNING: Container running in privileged mode"
else
echo " OK: Not running in privileged mode"
fi
# Check read-only root filesystem
readonly=$(docker inspect --format='{{.HostConfig.ReadonlyRootfs}}' $container)
if [ "$readonly" = "false" ]; then
echo " WARNING: Root filesystem is writable"
else
echo " OK: Root filesystem is read-only"
fi
echo
done
# Check image vulnerabilities
echo "3. Image Vulnerability Scan"
for image in $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>"); do
echo "Scanning $image..."
trivy image --severity HIGH,CRITICAL --quiet $image
done
echo "Audit completed."
Summary
In this introduction, you’ve learned:
Security Fundamentals
- Security Model: Understanding Docker’s security architecture and isolation mechanisms
- Container Hardening: Secure Dockerfile practices and runtime security configuration
- Vulnerability Scanning: Using Trivy and other tools for security assessment
- Secrets Management: Proper handling of sensitive data in containers
Performance Basics
- Resource Management: CPU, memory, and I/O optimization techniques
- Docker Daemon Tuning: Configuration for optimal performance
- Monitoring Setup: Tools and techniques for performance monitoring
Operational Security
- Compliance: CIS Docker Benchmark and security controls
- Monitoring: Security event collection and analysis
- Governance: Automated compliance checking and reporting
Key Concepts Mastered
- Defense in Depth: Multiple layers of security controls
- Least Privilege: Running containers with minimal permissions
- Resource Limits: Preventing resource exhaustion attacks
- Continuous Monitoring: Real-time security and performance monitoring
Next Steps: Part 2 explores core security concepts including advanced hardening techniques, performance optimization strategies, and comprehensive monitoring solutions that form the foundation of production-ready Docker deployments.