Day 40: Capabilities and the four namespaces
Capabilities: splitting up root's power
Traditionally, a process is either root (can do anything) or not (restricted by permission bits). Capabilities split root's power into ~40 discrete privileges — CAP_NET_BIND_SERVICE (bind to ports below 1024), CAP_SYS_ADMIN (a notoriously broad grab-bag), CAP_CHOWN, and so on. Docker drops most capabilities by default, giving containers a much smaller blast radius than a genuinely root process would have.
# Run with almost nothing
docker run --cap-drop=ALL alpine id
# Add back exactly what's needed to bind port 80 as non-root
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myapiLeast privilege, concretely
This is the practical, hands-on version of the "least privilege" principle you'll see formalized in Phase 26 (OWASP) and enforced automatically by Kubernetes Pod Security Standards in Phase 11.
The four namespaces, revisited
From Day 33: PID (process tree isolation), Network (interfaces/ports), Mount (filesystem view), UTS (hostname). A full container runtime also uses IPC (isolates shared memory/semaphores between containers) and User namespaces (mapping container-root to an unprivileged host UID) — the latter is what lets a process be "root" inside a container without being real root on the host.
Key terms
- Capability
- A discrete slice of root's traditional privileges (e.g. CAP_NET_BIND_SERVICE), grantable independently.
- User namespace
- Maps a UID inside a container (e.g. root, UID 0) to an unprivileged UID on the host.
Why is --cap-drop=ALL --cap-add=NET_BIND_SERVICE better security practice than just running as root?