Docker already starts containers with a restricted set of Linux capabilities, using an allowlist. The best practice in Docker's documentation is to go further and remove every capability your process does not explicitly require. In practice that means dropping all and adding back one or two.
What capabilities are
Traditional root has one huge privilege. Linux capabilities split it into separate pieces, such as changing file ownership, binding low ports or loading kernel modules. A container process that runs as root inside the container with a narrow capability set is much less dangerous than one with the full set.
Docker's security page says that by default it drops all capabilities except those needed, an allowlist approach and not a denylist. Its stated best practice is to remove all capabilities except those explicitly required for your processes.
Dropping in Docker
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE myimage:1.2.3
Run it, watch for permission errors, and add back only what the app proves it needs. Many web apps need none, because they can listen on a port above 1024.
Dropping in Kubernetes
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
The Pod Security Standards use the same list. Baseline restricts added capabilities to a short list, including CHOWN, KILL, NET_BIND_SERVICE, SETUID and SETGID. Restricted requires dropping ALL and permits adding back only NET_BIND_SERVICE.
Capabilities to treat as red flags
Without claiming a full list, some stand out. The Kubernetes docs note that allowPrivilegeEscalation false cannot be combined with CAP_SYS_ADMIN, which shows how broad that capability is. If a manifest asks for SYS_ADMIN or similar, ask why, and consider whether the task belongs in a container at all.
Check the Linux capabilities man page for what each name allows before approving an exception.
A review process
- Inventory pods that add capabilities. Admission audit mode will list them.
- For each, record the reason.
- Try removing it in staging.
- Keep an exceptions list with an owner.
See the securityContext checklist for the full set of hardening fields.
A worked example
Suppose a small web service listens on port 8080 and writes logs to stdout. It needs no extra capability at all, so drop ALL and add nothing. If the same service must listen on port 443 directly, add NET_BIND_SERVICE and nothing else. If someone asks for SYS_ADMIN to fix a startup error, treat that as a design question: find the specific operation that failed, and see whether a narrower capability, a volume option or an image change solves it.
Writing the reason next to each added capability in the manifest makes later reviews fast.
Quick check
Does dropping all capabilities break most apps?
Many apps run fine, but test. Common failures involve low ports and file ownership changes.
Is running as non-root a substitute?
No. Do both. They address different parts of the problem.
Sources
- Docker security, Docker documentation
- Pod Security Standards, Kubernetes documentation
- Configure a Security Context
Last reviewed: 19 October 2026.