Running containers in production without security hardening is like leaving your front door open. This guide covers the full container security lifecycle — from building secure images to runtime protection.
Image Scanning
# Trivy (most popular, free)
trivy image myapp:latest
trivy image --severity HIGH,CRITICAL myapp:latest
trivy image --exit-code 1 myapp:latest # Fail CI on vulnerabilities
# Docker Scout (built-in)
docker scout cves myapp:latest
docker scout quickview myapp:latest
# Snyk
snyk container test myapp:latest
Dockerfile Hardening
# Use minimal base image
FROM node:20-alpine # NOT node:20 (500MB smaller)
# Pin versions
FROM node:20.11.1-alpine3.19
# Non-root user
RUN addgroup -S app && adduser -S app -G app
USER app
# Read-only filesystem
# Run with: docker run --read-only --tmpfs /tmp myapp
# No new privileges
# Run with: docker run --security-opt=no-new-privileges myapp
# Drop capabilities
# Run with: docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp
# Health check
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:3000/health || exit 1
Runtime Security Flags
# Production-secure container run
docker run -d \
--name myapp \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid \
--security-opt=no-new-privileges:true \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--memory 512m \
--cpus 1.0 \
--pids-limit 100 \
--restart unless-stopped \
--user 1000:1000 \
myapp:latest
Docker Compose Security
services:
app:
image: myapp:latest
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
user: "1000:1000"
📘 Docker Security Deep Dive
Our cybersecurity eBooks cover container security, image hardening, and Kubernetes security in depth.
Browse Security Books →Security Checklist
- Scan images in CI/CD pipeline (fail on CRITICAL)
- Use minimal base images (alpine, distroless, scratch)
- Run as non-root user
- Drop all capabilities, add only what's needed
- Use read-only root filesystem
- Set resource limits (memory, CPU, PIDs)
- Never store secrets in images (use Docker secrets or env)
- Keep images updated (rebuild weekly)
- Use multi-stage builds to minimize attack surface
- Enable Docker Content Trust for image signing