pull down to refresh

Running Docker containers with default settings is like leaving your front door unlocked. Here's a practical guide to hardening your containers and reducing your attack surface.

The Core PrinciplesThe Core Principles

Most Docker containers run as root by default and get far more capabilities than they actually need. This creates unnecessary risk if a container is compromised. The solution? Apply the principle of least privilege across every aspect of your container configuration.

Key Hardening TechniquesKey Hardening Techniques

Run as non-root user

user: "99:100"  # nobody:users on Unraid

Drop all capabilities by default

cap_drop:
  - ALL

Only add back specific capabilities if absolutely required.

Enable security restrictions

security_opt:
  - no-new-privileges:true
read_only: true  # if possible
tty: false
stdin_open: false

Harden /tmp to prevent payload execution

tmpfs:
  - /tmp:rw,noexec,nosuid,nodev,size=512m

Set resource limits

pids_limit: 512
mem_limit: 3g
cpus: 3

Mount volumes read-only when possible

volumes:
  - /mnt/data/movies:/movies:ro

Control logging to prevent log bombs

logging:
  driver: json-file
  options:
    max-size: "50m"
    max-file: "5"

Using TemplatesUsing Templates

Save time with compose anchors:

x-lockdown: &lockdown
  read_only: true
  security_opt:
    - "no-new-privileges=true"
  cap_drop:
    - ALL
  tmpfs:
    - /tmp:rw,noexec,nosuid,nodev,size=512m

services:
  myapp:
    <<: *lockdown

Important NotesImportant Notes

Some containers won't work with all restrictions enabled. Use docker logs <container> to troubleshoot and selectively relax constraints as needed. For internet-facing containers, consider running them in a DMZ network or separate VM for additional isolation.

These configurations significantly reduce blast radius without eliminating all risk. Defense in depth is key.


*Credit: Based on excellent advice from the /r/selfhosted community https://www.reddit.com/r/selfhosted/comments/1pr74r4/comment/nv07sp4/ *