Rootless Docker, RootlessKit, User Namespaces, Networking, Storage, Limitations, and Threat Reduction: Diagnostics, Failure Modes, Security, and Performance
Diagnose rootless failures by separating context/socket mistakes, subordinate-ID gaps, cgroup delegation, networking, storage, ownership, and outer-host privilege without weakening the host.
Learning objectives
- Apply an evidence-first sequence to rootless context, subordinate-ID, cgroup, storage, networking, and ownership failures.
- Diagnose bind-mount ownership and capability limitations without broad permissions or privilege escalation.
- Interpret current Engine 29.5+ RootlessKit networking behavior when older guidance no longer matches.
- Preserve first-failure evidence and correct only the failing layer.
1. Evidence-first sequence for rootless incidents
Preserve the first error before changing contexts, reinstalling packages, or switching daemons. Then walk the layers in order:
- Host/kernel and Linux distribution.
- Docker client version and selected context.
- Rootless socket and daemon security options.
- Subordinate UID/GID ranges and user namespace mapping.
- cgroup v2/systemd delegation.
- Storage driver/backing filesystem.
- RootlessKit network/port behavior.
- Container image, process, mounts, and ownership.
- External dependency/registry/application evidence.
2. Failure: “rootless” context is actually an ordinary daemon
docker context show
docker context inspect "$(docker context show)"
docker info --format '{{json .SecurityOptions}}'
docker info --format 'Root={{.DockerRootDir}}'
If rootless is absent from Security Options, a context
name alone is not proof of rootless execution. Fix the client target
or daemon setup; do not troubleshoot UID mappings until the daemon
identity is established.
3. Failure: missing or undersized subuid/subgid ranges
Typical symptoms appear during setup or when creating user mappings. Preserve setup-tool output, then inspect the files:
command -v newuidmap
command -v newgidmap
grep "^$(whoami):" /etc/subuid
grep "^$(whoami):" /etc/subgid
The safe correction is an administrator-approved subordinate-ID
allocation. Do not invent overlapping ranges or make
newuidmap/newgidmap broadly writable.
5. Failure: bind-mounted files have surprising ownership
Rootless UID/GID mapping and host bind mounts meet at a real
filesystem. A file written as “root” inside the container may map to
a subordinate host UID rather than the login user. Preserve
stat evidence on both sides:
docker exec <container> sh -c 'id; stat -c "%u:%g %n" /work/example'
stat -c '%u:%g %n' ./example
Correct by designing the runtime user, directory ownership, ACLs, or
volume strategy deliberately. Do not use chmod 777 or
recursively chown an unrelated host tree.
6. Failure: rootless networking is diagnosed as ordinary bridge networking
RootlessKit inserts an outer networking/port-forwarding layer.
Container IPAddress may be meaningful only inside that
namespace, and published-port source-IP behavior depends on
RootlessKit/network-driver configuration. Since Engine 29.5,
--net=host behavior also changed materially.
docker version
docker info --format '{{json .SecurityOptions}}'
docker inspect <container> --format '{{json .NetworkSettings.Networks}}'
docker port <container>
ps -ef | grep -E '[r]ootlesskit|[s]lirp4netns|[g]visor|[p]asta' || true
Do not disable host firewalls or switch to rootful Docker before proving which rootless network/port path is failing.
7. Failure: storage driver or backing filesystem assumption is wrong
docker info --format 'DockerRootDir={{.DockerRootDir}} Driver={{.Driver}}'
findmnt -T "$HOME/.local/share/docker" 2>/dev/null || true
uname -r
Rootless overlay2 depends on a sufficiently new kernel;
other drivers have documented prerequisites. NFS is not a supported
Docker data-root. A storage mismatch is not repaired by deleting the
data root blindly.
8. Failure: “rootless-in-rootful DinD” is treated as non-privileged
Docker’s documented rootless DinD pattern still uses an outer privileged rootful container. The inner daemon runs as a non-root user, but the outer container’s privilege is the controlling host boundary. Treat that as a separate trust decision and record it explicitly.
--privileged as a troubleshooting
shortcut.
If a CI architecture requires privileged DinD, document why, isolate
the runner, and compare safer alternatives such as a dedicated
rootless daemon/builder or an isolated VM.
9. Intentionally broken example: wrong context, not broken container
Create no destructive state. The “failure” is a client pointing at a nonexistent rootless-style Unix socket:
docker context create da-ch26-broken --docker "host=unix:///tmp/da-ch26-no-such.sock"
docker --context da-ch26-broken info || true
docker context inspect da-ch26-broken
docker context rm da-ch26-broken
The connection error proves a client/context/endpoint failure. It says nothing about image correctness, container runtime state, RootlessKit, cgroups, or storage. The repair is to select the correct known context, not restart daemons or delete runtime files.
Knowledge check
A context named “rootless” points to a normal rootful daemon. What is the first correction?
Fix/select the actual client endpoint. Context names are labels; SecurityOptions and endpoint/data-root evidence prove the daemon mode.
Why is chmod 777 the wrong fix for a bind-mount
ownership mismatch?
It broadens host filesystem permissions without correcting the UID/GID mapping, runtime user, or intended ownership model.
Why can a rootless container IP be unreachable directly from the real host namespace?
The IP may exist inside RootlessKit’s network namespace; published ports are the normal host reachability path.
A rootless workload needs an operation requiring a capability
in the initial host user namespace. Will
--cap-add necessarily solve it?
No. Added capabilities are scoped to the container/user namespace and do not grant authority over host-global resources.
What does the intentionally broken context demonstrate?
A Docker connection failure can be purely a client/context/socket problem; changing runtimes, images, storage, or firewalls would hide the cause.
Official references and version notes
- Docker Engine rootless mode — architecture, prerequisites, setup, contexts, and subordinate UID/GID requirements.
- Rootless mode tips — socket/data-root locations, systemd user service, cgroup resource controls, ports, and advanced operation.
- Rootless troubleshooting — supported storage drivers, cgroup requirements, unsupported features, networking drivers, source-IP behavior, and current host-network behavior.
- User namespace remapping — contrast between a rootful daemon with remapped containers and fully rootless daemon execution.
- Storage driver selection — rootless overlay2/fuse-overlayfs guidance and backing-filesystem considerations.
- Docker Engine 29 release notes — Engine 29.5 rootless networking changes and Engine 29.8 RootlessKit updates.
- Docker Desktop for Linux FAQ — why Docker Desktop uses a VM instead of ordinary Rootless Docker.
- Docker Desktop networking — VM/backend networking boundary on Desktop platforms.
- RootlessKit upstream — user-namespace networking and port-forwarding implementation used by Rootless Docker.
Docker Engine 29.8.1 is the current Engine release. Engine 29.5
changed packaged rootless networking so
gvisor-tap-vsock is the preferred/default path when
slirp4netns is not separately installed, and rootless
host networking now reaches the real host network namespace. Engine
29.8 updates RootlessKit to 3.1.0 and adds the optional
pesto port driver when paired with
pasta (IPv4 only). Rootless resource limits require
cgroup v2 plus systemd delegation; rootless storage support is
host/kernel dependent. Docker Desktop uses an Engine inside a
managed Linux VM and must not be described as ordinary Rootless
Docker. Every lab therefore records actual
docker version, context, security options,
cgroup/storage/network state rather than assuming upstream defaults.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.