Chapter 26Lesson 01~120 minutes

Rootless Docker, RootlessKit, User Namespaces, Networking, Storage, Limitations, and Threat Reduction: Concepts, Architecture, and Mental Model

Model Rootless Docker as an unprivileged user-space daemon boundary built from user namespaces, subordinate IDs, RootlessKit networking, storage, cgroup delegation, and explicit limitations.

Rootless DockerRootlessKitUser namespacesSubordinate IDsThreat reduction

Learning objectives

  • Explain how an unprivileged host user, user namespace, RootlessKit, rootless daemon/runtime, container namespaces, and subordinate IDs compose the rootless architecture.
  • Distinguish rootless Docker from docker-group access, userns-remap, and Docker Desktop VM isolation.
  • Read context/socket/data-root/cgroup/storage/network evidence before changing any rootless setting.
  • State precisely which threats rootless mode reduces and which shared-kernel or application risks remain.
Chapter 26 principle. Rootless Docker reduces the daemon/runtime’s starting host authority. It is still a shared-kernel container architecture, so “rootless” must be treated as one defense layer, not a claim that untrusted code is harmless.

1. The practical problem: “docker without sudo” can mean two very different things

On a normal Linux Engine installation, adding a user to the docker group removes the need to type sudo, but the daemon still runs as root and the socket grants root-level control. Rootless Docker changes the architecture instead: both the daemon and its containers run inside a user namespace owned by an ordinary host user.

This matters when a daemon or runtime bug is part of your threat model. Rootless mode can reduce the blast radius of daemon/runtime compromise because the daemon does not begin with host-root authority. It is not a separate kernel, and it does not turn arbitrary hostile code into a safe workload. The host kernel, user-namespace implementation, mounts, credentials, network reachability, and application privileges still matter.

2. Mental model: user identity, user namespace, RootlessKit, daemon, and subordinate IDs

Start at the host login account. The Docker client selects a context whose endpoint is normally a user-owned Unix socket such as /run/user/$UID/docker.sock. RootlessKit creates the user/network namespace environment in which dockerd and its managed runtime execute. The daemon then creates container namespaces inside that rootless environment.

To provide multiple container UIDs/GIDs without obtaining real host IDs, Linux uses subordinate ranges declared in /etc/subuid and /etc/subgid. Docker currently requires at least 65,536 subordinate IDs for the rootless user. “root” inside a container is therefore a namespace identity whose host mapping is constrained by that range rather than host UID 0.

Rootless Docker authority and data path
flowchart TD
  A[Unprivileged host user] --> B[Docker rootless context / user socket]
  B --> C[RootlessKit + user namespace]
  C --> D[rootless dockerd and containerd]
  D --> E[Container user namespace]
  F["/etc/subuid + /etc/subgid"] --> C
  E --> G[Mapped container processes]
  C --> H[User-mode / rootless networking + port forwarding]
  D --> I[User-owned data root / storage driver]
  J[cgroup v2 + systemd delegation] --> D
            

3. State map: prove which daemon and namespace you are actually using

State Evidence Why it matters
Host login identity id -u, id -g, whoami Defines the outer unprivileged principal.
Subordinate ranges /etc/subuid, /etc/subgid Defines the UID/GID space available inside the user namespace.
Client target docker context show, docker context inspect Prevents confusing a rootless daemon with the ordinary rootful daemon.
Daemon security mode docker info → Security Options Should explicitly show rootless for a rootless Engine.
Socket usually $XDG_RUNTIME_DIR/docker.sock Represents authority over that user daemon.
Data root usually ~/.local/share/docker Rootless images/containers are separate from rootful daemon state.
cgroup mode host cgroup v2 + systemd delegation Required for rootless CPU/memory/PID resource controls.
Storage/network docker info, RootlessKit process/env evidence Affects compatibility and performance.

4. Read-only baseline inspection before changing anything

These commands do not install rootless Docker. They establish whether the host is Linux, whether prerequisites exist, which context is selected, and whether a rootless daemon already exists.

uname -a
id
command -v newuidmap || true
command -v newgidmap || true
grep "^$(whoami):" /etc/subuid 2>/dev/null || true
grep "^$(whoami):" /etc/subgid 2>/dev/null || true

docker version
docker context ls
docker context show
docker context inspect "$(docker context show)"
docker info --format '{{json .SecurityOptions}}'
docker info --format 'DockerRootDir={{.DockerRootDir}} Driver={{.Driver}} CgroupVersion={{.CgroupVersion}}' 

On Docker Desktop, the context typically points to the Desktop VM Engine. That is a different boundary from a native Linux rootless daemon. Record it rather than attempting to infer rootless status from the fact that the desktop application runs under a normal desktop user.

5. What RootlessKit changes—and what it does not

RootlessKit provides the outer user/network namespace and rootless port-forwarding machinery. In current packaged Engine 29.5+ installations, gvisor-tap-vsock is the preferred/default network driver when slirp4netns is not separately present. Other supported/experimental combinations include slirp4netns, pasta, and newer port drivers such as pesto.

The user-mode network path can have different throughput, source-IP, loopback, and reachability characteristics from rootful bridge networking. Since Engine 29.5, rootless --net=host can use the real host network namespace; before 29.5 it remained inside RootlessKit. That historical distinction is exactly why a course should capture Engine/RootlessKit versions before diagnosing networking.

6. cgroup and storage constraints are part of the architecture

Rootless CPU, memory, and PID controls depend on cgroup v2 with systemd delegation. If that delegation is absent, a Docker CLI resource flag may be rejected or ineffective even though the same workload works under a rootful daemon.

Rootless storage is also conditional. Current Docker guidance supports overlay2 on kernel 5.11+, fuse-overlayfs on supported older kernels, btrfs under documented conditions, and vfs as a compatibility/testing fallback. The rootless data root must not be assumed interchangeable with a rootful daemon’s storage.

7. Threat reduction: describe the boundary precisely

Rootless mode reduces the daemon/runtime’s starting host privilege. A compromised rootless daemon process does not automatically begin as host root. That is valuable, but the host kernel remains shared. Kernel vulnerabilities reachable through unprivileged user namespaces can still matter; host bind mounts can deliberately expose host data; application credentials can still be stolen; and network-accessible services can still be attacked.

For hostile multi-tenancy or workloads where a shared kernel is outside the acceptable trust model, a VM or stronger sandbox boundary may be the correct layer. Rootless mode is therefore a least-authority improvement, not a universal replacement for isolation architecture.

8. DevOps connection: reproducibility includes the execution authority

An image digest alone cannot reproduce a rootless execution boundary. Record the daemon context, rootless security option, host/kernel, subordinate-ID allocation, data root/storage driver, RootlessKit network behavior, cgroup delegation, port behavior, and mounted host paths. Those facts explain why identical images can behave differently under rootful Engine, rootless Engine, and Docker Desktop.

Knowledge check

How is Rootless Docker different from merely adding a user to the docker group?

Why are /etc/subuid and /etc/subgid required?

Does rootless mode provide a separate kernel?

What evidence proves the CLI is really targeting a rootless daemon?

When do rootless Docker resource limits work?

Next lesson

Next: Rootless Docker, RootlessKit, User Namespaces, Networking, Storage, Limitations, and Threat Reduction: Guided Hands-On Workflow and Core Operations

Continue with the next lesson in the course sequence and carry forward the evidence-first Docker operating model.

Official references and version notes

Version/platform baseline, verified 2026-09-22.

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.