Container Security
Harden containers by using trusted minimal images, dropping privileges and capabilities, scanning, and limiting resources.
Security is a layered practice. No single setting makes a container safe, but together these habits greatly reduce risk.
Key hardening steps
- Trusted, minimal images — fewer packages means fewer vulnerabilities.
- Run as non-root and drop unneeded Linux capabilities.
- Read-only filesystem — run with
--read-onlywhere possible. - No new privileges — prevent privilege escalation.
- Limit resources — cap memory and CPU so one container cannot starve the host.
- Scan images regularly for known CVEs.
- Keep Docker updated and never expose the daemon socket carelessly.
Example
# Run a hardened container
docker run -d \
--read-only \
--security-opt no-new-privileges \
--cap-drop ALL \
--memory 256m --cpus 0.5 \
--user 10001 \
--name web myapp:1.0When to use it
- A security team drops all Linux capabilities from production containers and adds back only CAP_NET_BIND_SERVICE for a port-80 web server.
- An ops engineer enables seccomp profiles to restrict the syscalls a container can make, reducing the kernel attack surface.
- A compliance team uses --read-only to make container filesystems immutable, preventing malware from writing persistence payloads.
More examples
Drop all Linux capabilities
Drops every Linux capability then adds back only NET_BIND_SERVICE so Nginx can bind to port 80 without root.
docker run -d \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
-p 80:80 \
--name web \
nginx:alpineRun with read-only filesystem
Makes the root filesystem read-only, provides a small tmpfs for /tmp, and prevents privilege escalation via setuid binaries.
docker run -d \
--read-only \
--tmpfs /tmp:size=64m \
--security-opt no-new-privileges \
--name api \
myapp:latestApply a custom seccomp profile
Seccomp profiles restrict which syscalls a container process can make, shrinking the kernel attack surface.
# Use Docker's default restrictive profile
docker run --security-opt seccomp=/etc/docker/seccomp.json myapp
# Or use the built-in default (enabled by default)
docker run --security-opt seccomp=default myapp
Discussion