December 9, 2020·6 min read·engineeringdockerrootlesscgroups

Docker Engine 20.10 separates daemon privilege from resource control

Supported rootless operation and cgroup v2 address different parts of container execution. User namespaces limit authority, while delegated resource control determines what a daemon can allocate.

Running a container process as a non-root user does not establish that the daemon managing it also lacks root privileges. Docker's rootless mode addresses the daemon as well. Engine 20.10 promotes that mode from experimental status and adds cgroup v2 support. Docker's 9 December announcement connects the runtime's cgroup work to the move toward fully supported rootless operation. The release notes date the Engine release to 8 December.

These changes address authority and resource allocation, two related concerns that need separate explanations. User namespaces determine how identities and privileges map into the host environment. Control groups organize processes and distribute resources. A daemon can run without host root authority while still needing a supported mechanism to constrain the resources of the containers it manages.

I value Docker's repeatable build and image model, but the privilege of the service executing those images remains a separate design choice. Supported rootless operation makes that choice more practical. It does not make every aspect of host administration disappear, and it does not turn a container's internal root identity into host root.

The daemon also enters the user namespace

Docker's rootless documentation before this release explains the distinction from userns-remap. Both use user namespaces, but userns-remap retains a rootful daemon. Rootless mode runs the daemon and containers without root privileges in the host environment. The document identifies mitigation of vulnerabilities in the daemon and runtime as the purpose.

The same guide describes subordinate user and group identifiers as prerequisites. It requires newuidmap and newgidmap and at least 65,536 subordinate IDs for the user in each relevant mapping file. Those mapping helpers are the stated exception to its avoidance of setuid binaries or file capabilities. Rootless execution therefore has concrete host prerequisites, rather than being an effect of setting a container's application user alone.

This distinction affects how to reason about a compromise. A vulnerability in a service running with the user's authority begins with a different host privilege level from a vulnerability in a daemon running as root. The application still has access to whatever resources that user and its configuration make available. Reducing authority changes the consequences available through the process, without establishing that every possible application behavior is harmless.

The earlier guide also gives separate locations for rootless state, including the user's local share directory for data and the runtime directory for the daemon socket. That separation is consistent with a daemon owned and managed by a user. Connecting to the intended socket remains necessary for the CLI to reach that daemon rather than a different one on the machine.

Resource control needs a hierarchy

The Linux kernel's cgroup v2 documentation defines cgroups as a hierarchy of processes with controllers that distribute resources. Version 2 uses a single hierarchy. Controllers apply restrictions through that hierarchy, and a descendant cannot override restrictions imposed above it. This is the mechanism that makes resource delegation different from granting unrestricted control over the host.

For example, a delegated manager can subdivide the resources it receives among its own descendants. It cannot create more authority over the parent's resources by adding another child. That property is necessary for a user-managed container daemon to organize its workload while the host retains control of the total allocation. The application-level limit is meaningful only within the authority delegated to the manager enforcing it. Delegation also constrains process migration. The kernel documentation requires permission on the destination and on the common ancestor of the source and destination for a less privileged caller to move a process. That prevents a delegated manager from freely importing processes from elsewhere in the hierarchy or exporting them beyond its delegated portion.

The kernel document describes delegation through permissions on the cgroup directory and selected control files, or through a cgroup namespace with the appropriate mount option. It specifically excludes control over the resource-interface files that determine the parent's distribution. That boundary allows useful management below the delegation point without granting control over allocations above it.

The result is a more precise account of rootless resource management. A non-root daemon needs a writable portion of the hierarchy and the relevant controllers. Merely recognizing a memory-limit flag does not give the process authority to configure arbitrary host cgroups. The host's delegation and the runtime's support both contribute to whether the requested resource policy can be implemented.

Engine support reaches the runtime and the manager

Engine 20.10's runtime notes add cgroup v2 support and use the systemd cgroup driver by default when available on cgroup v2. Its rootless notes separately add support for the systemd native cgroup driver option. These entries describe the connection between the container runtime's resource handling and the service manager's organization of the hierarchy.

Docker's announcement says the work follows cgroup v2 support in runc. That dependency matters because the Engine does not implement container execution alone. A feature presented at the Docker CLI requires support through the components that create and manage the process. The Engine release brings those components together in a supported configuration.

The status change should also be read against the previous documentation. That guide still calls rootless experimental and lists cgroups among its unsupported features. It is useful evidence of the earlier limitation, not an installation guide that overrides the new release's support statement. The release changes what is supported, while the earlier description explains why this combination of changes matters.

I find the resource-delegation account useful because it identifies the remaining administrative responsibility. The host determines what the user can control. The user's daemon manages containers within that allocation. That relationship is more informative than assuming that rootless means the daemon no longer depends on host configuration.

The release adds a user-oriented setup tool

The 20.10 setup script is another concrete part of the release. Its initial checks require Linux, refuse installation as root, locate dockerd-rootless.sh and detect whether a systemd user environment is available. It also requires a writable home directory. These checks make the intended owner of the daemon explicit.

The script checks for an accessible rootful Docker socket and normally stops if one is present, with an explicit override available. That helps distinguish creating a user-managed daemon from unknowingly continuing to use the existing privileged service. The distinction is operationally important because a rootless installation has little effect on a command that remains connected to a different daemon.

Its handling of the runtime directory also exposes the importance of the user's session. With a detected systemd environment, a missing or unwritable runtime directory is an error. The script's diagnostic discusses logging in as the intended user and enabling lingering where appropriate. The service's execution environment therefore includes session and service-management state as well as the daemon binary.

These checks do not change the image format. They determine whether the host can establish the intended execution model for those images. That separation lets an application retain its build description while the deployment environment changes how much privilege the manager holds and how it obtains resources.

Isolation and allocation remain separate policies

A user namespace and a cgroup hierarchy answer different questions. Identity mapping concerns authority. Resource controllers concern the organization and limits of resources. The kernel's delegation rules prevent a subordinate manager from exceeding restrictions above its allocation, while Docker's rootless model changes the host identity under which that manager operates.

This means a security assessment should identify both the daemon's host privilege and its resource-management configuration. A statement that an application runs as a particular user does not answer either question completely. Likewise, a memory limit says little about the host privilege of the process that created the container. Engine 20.10 makes supported rootless operation available alongside the runtime support needed for the newer resource hierarchy.

For systems using this configuration, the practical change is the ability to preserve Docker's image and command model while reducing the daemon's host authority. The setup tool establishes a user-managed service, and cgroup integration connects its containers to delegated resource control. The host still owns the allocation above that delegation point, which is the boundary that makes user-managed resource subdivision compatible with host-wide limits.