no-privileged-service
privileged: true in Docker Compose disables nearly every container isolation mechanism. What it actually grants and the narrower alternatives.
On this page
privileged: true is the biggest hammer in the Compose vocabulary: it gives the container every Linux capability, access to every host device, and turns off the seccomp, AppArmor, and cgroup device protections that make a container a container. It usually enters a file as a workaround, because some device wouldn't open or some syscall was blocked, and then never leaves. This rule flags every service that sets it.
What the rule catches
services:
runner:
image: my-runner:2.1.0
privileged: trueScanning this file reports:
✖ ERROR [docker-doctor/no-privileged-service]
Service 'runner' runs in privileged mode. A privileged container has full access to the host's devices and kernel, so compromising this service compromises the host.Why it matters
A privileged container is not meaningfully contained: it can load kernel modules, talk to raw disks, and remount host filesystems. Root inside is root on the host, so compromise of the service becomes compromise of the machine and every other workload on it. The setting also hides the service's real requirements, so nobody can later reconstruct which capability it actually needed; an explicit cap_add/devices list is both safer and better documentation.
How to fix it
Remove privileged: true and grant only what the service needs: specific capabilities via cap_add, or individual device access via devices.
services:
runner:
image: my-runner:2.1.0
# grant only what the service actually needs
cap_add:
- NET_ADMIN
devices:
- /dev/net/tunAlmost every legitimate use has a narrower replacement:
- Network syscalls (VPN, routing):
cap_add: [NET_ADMIN]. - One device:
devices: [/dev/net/tun](or/dev/dri,/dev/kvm, …). - GPU access for model inference:
deploy.resources.reservations.deviceswith thegpucapability, notprivileged. - Docker-in-Docker for CI: prefer the host's socket via a scoped mechanism (see
no-docker-socket-mount) or a rootless DinD setup.
Start from nothing and add single capabilities until the service works; the final list is rarely more than two entries.
Rule details
- Rule key —
docker-doctor/no-privileged-service - Category — Compose
- Default severity —
error - Applies to — Docker Compose files
Explain this rule from the CLI:
npx @docker-doctor/cli@latest rules explain docker-doctor/no-privileged-serviceChange its severity — or turn it off — in your config file:
// docker-doctor.config.ts
export default {
rules: {
"docker-doctor/no-privileged-service": "off",
},
};Severity affects the health score: error findings cost more points than warning, and info costs the least.