Skip to content
intermediate Phase 5 · Docker Security

Security Fundamentals

Understand Docker security model, attack surface, and threat landscape.

45m
0 problems
Topic Progress 0%

Docker Security Model

Docker Security Model

Isolation Layers

Docker provides multiple isolation layers:

┌────────────────────────────┐
│     Application            │
├────────────────────────────┤
│     Container Runtime      │
│  ┌──────────────────────┐  │
│  │ Namespaces           │  │  Process, network, mount isolation
│  │ cgroups              │  │  Resource limits
│  │ seccomp              │  │  System call filtering
│  │ AppArmor/SELinux     │  │  Mandatory access control
│  │ capabilities          │  │  Privilege dropping
│  └──────────────────────┘  │
├────────────────────────────┤
│     Linux Kernel           │
└────────────────────────────┘

Namespaces (Isolation)

Namespace Isolates
PID Process IDs
NET Network interfaces, IPs, routing tables
MNT Filesystem mount points
UTS Hostname and domain name
IPC Inter-process communication
USER User and group IDs

Attack Surface

The primary attack surfaces are:

  1. Container escape: Breaking out of namespace isolation to access the host
  2. Docker daemon: If compromised, full host access
  3. Image supply chain: Malicious base images or dependencies
  4. Resource exhaustion: A container consuming all host resources
  5. Network exposure: Unintended port exposure

Container vs VM Security

# Container: shares kernel with host
# A kernel vulnerability affects ALL containers

# VM: separate kernel per VM
# VM escape + kernel exploit needed

Containers are NOT as secure as VMs for multi-tenant isolation. Use VMs or gVisor/Kata Containers for strong isolation.

Security Checklist

  • Run containers as non-root
  • Use minimal base images
  • Scan images for vulnerabilities
  • Limit container resources
  • Use read-only filesystems where possible
  • Drop unnecessary Linux capabilities
  • Use Docker Bench Security for auditing

Container Hardening

Container Hardening

Run as Non-Root

# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
    adduser -S appuser -u 1001 -G appgroup

# Switch to non-root before CMD
USER appuser

CMD ["node", "server.js"]
# Verify container runs as non-root
docker exec web id
# uid=1001(appuser) gid=1001(appgroup)

# Check in Dockerfile
docker inspect --format '{{.Config.User}}' myapp

Drop Linux Capabilities

# Drop all capabilities and add only needed ones
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx

# Or in docker-compose.yml
services:
  web:
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE  # Bind to ports < 1024

Common capabilities:

Capability Allows
NET_BIND_SERVICE Bind to ports < 1024
CHOWN Change file ownership
SETUID/SETGID Set user/group IDs
SYS_PTRACE Trace processes (debugging)

Read-Only Root Filesystem

docker run --read-only --tmpfs /tmp --tmpfs /var/run myapp

# Or in docker-compose.yml
services:
  web:
    read_only: true
    tmpfs:
      - /tmp
      - /var/run

Seccomp Profiles

Seccomp (Secure Computing) filters system calls:

# Use default seccomp profile (applied automatically)
docker run --security-opt seccomp=default myapp

# Use custom seccomp profile
docker run --security-opt seccomp=profile.json myapp

# Disable seccomp (NOT recommended)
docker run --security-opt seccomp=unconfined myapp

AppArmor / SELinux

# AppArmor (Ubuntu/Debian)
docker run --security-opt apparmor=my-profile myapp

# SELinux (RHEL/Fedora)
docker run --security-opt label=type:svirt_apache_t myapp

Docker Daemon Security

// /etc/docker/daemon.json
{
  "icc": false,           // Disable inter-container communication
  "userns-remap": "default",  // User namespace remapping
  "no-new-privileges": true,   // Prevent privilege escalation
  "live-restore": true,         // Containers survive daemon restart
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Docker Bench Security

Docker Bench Security

What is Docker Bench?

Docker Bench for Security is a script that checks for dozens of common best practices around deploying Docker containers. It implements the CIS Docker Benchmark.

Run Docker Bench

# Run as container (recommended)
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 \
  docker/docker-bench-security

# Output shows PASS, WARN, or INFO for each check

Key Checks

Host Configuration:

  • [PASS] Ensure a separate partition for containers
  • [WARN] Ensure only trusted users are allowed to control Docker
  • [PASS] Ensure auditing is configured

Docker Daemon:

  • [PASS] Ensure TLS is used for Docker daemon
  • [PASS] Ensure default ulimit is configured
  • [WARN] Ensure experimental features are not enabled

Container Images:

  • [WARN] Ensure a user for the container has been created
  • [PASS] Ensure content trust for Docker is enabled
  • [WARN] Ensure minimal base image is used

Container Runtime:

  • [WARN] Ensure privileged containers are not used
  • [PASS] Ensure ports are not mapped to privileged ports
  • [WARN] Ensure memory limit is set

Automated Compliance

# CI/CD integration
docker run --rm docker/docker-bench-security 2>&1 | \
  grep -E "\[WARN\]|\[FAIL\]" | tee security-report.txt

# Fail build on warnings
docker run --rm docker/docker-bench-security 2>&1 | \
  grep -c "\[WARN\]" | xargs -I {} test {} -eq 0

Common Fixes

# Fix: Run as non-root
docker run --user 1000:1000 myapp

# Fix: Drop all capabilities
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp

# Fix: Read-only filesystem
docker run --read-only --tmpfs /tmp myapp

# Fix: Set resource limits
docker run --memory 512m --cpus 1.0 myapp

# Fix: No new privileges
docker run --security-opt no-new-privileges:true myapp