What Can Go Wrong
Containers Are Not a Security Boundary (By Default)
Back in the very first module you learned that containers share the host kernel with everything else on the machine, unlike a VM's fully separate one. That efficiency has a security cost: the isolation is real but thinner than a VM's, and Docker's defaults were chosen for convenience, not lockdown. A plain docker run gives the app root (the Linux superuser account that can read, write, or delete anything), a fully writable filesystem, and a dozen kernel capabilities (fine-grained permissions like "can change file ownership" or "can configure network interfaces" that root would otherwise have as one big bundle) it almost never actually needs. If the app inside is ever compromised - through a bug, a bad dependency, anything - every one of those unused privileges now belongs to the attacker too.
The two catastrophic anti-patterns:
Danger: --privileged disables essentially every isolation mechanism - all capabilities, all devices, no seccomp. A privileged container is root on the host wearing a thin costume. It exists for tools like Docker-in-Docker, never for apps.
Danger: Mounting/var/run/docker.sockhands the container the Docker API. Whoever holds the socket can start a privileged container with the host's/mounted - i.e., they own the machine. Treat the socket like the root password, because it is one.
# Audit any container in seconds:
$ docker inspect app --format '{{.HostConfig.Privileged}}'
$ docker inspect app --format '{{range .Mounts}}{{.Source}}{{"\n"}}{{end}}' | grep docker.sock
$ docker exec app id # uid=0(root)? that's finding #3
| Risk | Why it matters |
|---|---|
| Runs as root | container escape = root on host; file writes anywhere it can reach |
| Extra capabilities | NET_RAW, SYS_ADMIN etc. are escape toolkits |
| Writable rootfs | attacker persists malware, rewrites the app |
| Secrets in image/env | anyone with the image or inspect rights reads them |