Docker Security Hardening: Production Checklist
•
by Ivan Ivanov
dockersecurityhardeningdevops
Essential security hardening steps for Docker containers and host systems. From user namespaces to read-only filesystems.
Containers are not secure by default. Docker's default settings prioritize convenience over security. Here's my production hardening checklist based on real-world incident response.
Docker Daemon Security
1. Run as Rootless
dockerd-rootless-setuptool.sh install
Rootless Docker removes kernel capabilities and prevents privilege escalation from container to host.
2. Enable User Namespace Remapping
{
"userns-remap": "default"
}
Each container runs with an unprivileged UID/GID range on the host.
3. Restrict Capabilities
Drop all capabilities by default, add only what's needed:
security_opt:
- no-new-privileges:true
- cap-drop=ALL
- cap-add=NET_BIND_SERVICE # only if your app binds to <1024
Container Image Hardening
Use Minimal Base Images
FROM alpine:3.19 # 5MB vs ubuntu:2204's 80MB
Or even better:
FROM scratch # for statically compiled binaries
COPY app /
CMD ["/app"]
Multi-Stage Builds for Smaller Images
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
FROM scratch
COPY --from=builder /app/app /app
CMD ["/app"]
Scan Images for Vulnerabilities
docker scan myapp:latest
# or
trivy image myapp:latest
Integrate scanning into CI:
- name: Scan for vulnerabilities
run: |
trivy image --exit-code 1 --severity HIGH $IMAGE
Runtime Security
Read-Only Filesystem
read_only: true
tmpfs:
- /tmp
- /run
No Root User in Container
RUN addgroup -g 1000 appuser && \
adduser -u 1000 -G appuser -s /bin/sh -D appuser
USER appuser
Seccomp and AppArmor Profiles
security_opt:
- seccomp=./seccomp-profile.json
- apparmor=docker-profile
Network Segmentation
Bridge Network Isolation
docker network create --driver bridge isolated-net
docker run --network isolated-net myapp
Prevent Container-to-Host Communication
iptables -I DOCKER-USER -i br-xxxx -o docker0 -j DROP
Resource Limits
Prevent DoS attacks:
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
Docker Content Trust
export DOCKER_CONTENT_TRUST=1
docker pull myapp:1.0 # only accepts signed images
Host System Hardening
- Keep Docker Engine updated
- Use SELinux/AppArmor on host
- Disable inter-container communication by default:
--icc=false - Audit Docker daemon logs
- Regular security scanning with Lynis or OpenSCAP
Conclusion
Security is defense in depth. Apply these layers systematically. A single missed step could be your next breach.