The Hardening Checklist
Least Privilege, Flag by Flag
This single command embodies most of container security:
$ docker run -d --name payments -p 8090:80 \
--cap-drop ALL \
--cap-add CHOWN --cap-add SETGID --cap-add SETUID \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
--read-only \
--tmpfs /var/cache/nginx --tmpfs /var/run \
--memory 256m --pids-limit 100 \
nginx:alpine
| Flag | Defends against |
|---|---|
--cap-drop ALL + selective --cap-add | kernel-capability abuse (start from zero, add only what's needed) |
no-new-privileges | privilege escalation via setuid binaries |
--read-only + --tmpfs for scratch dirs | malware persistence, tampering with the app |
--memory / --pids-limit | resource-exhaustion DoS, fork bombs |
USER app in the Dockerfile | everything root can do that the app shouldn't |
Beyond docker run:
- Pin base images (
nginx:1.27-alpine, notlatest) and rebuild regularly for CVE patches - Scan images in CI:
docker scout cves myapp:v1(or Trivy/Grype) - Secrets via runtime injection (env from a vault, mounted secret files) - never
COPY'd into layers - Minimal bases (alpine/distroless): fewer binaries = fewer CVEs = less for an attacker to live off
Goal: The Harden the Container lab is a security-audit remediation: you inherit a --privileged, socket-mounted nginx and must recreate it with the full checklist above - while keeping the site serving. That's the real job.