Docker Rootless Mode: How and Why to Run Without Root
Published August 2, 2026 · 10 min read
Docker rootless mode runs the entire daemon as an ordinary, unprivileged user. It closes one of the oldest gaps in container security — the fact that the daemon runs as root — so a break-out or a daemon bug no longer means instant host root. Here is how it works, how to set it up, and the tradeoffs you need to know before switching.
The problem rootless mode solves
In a standard install the Docker daemon (dockerd) runs as root. That is convenient — it can manage networks, mount filesystems, and create namespaces freely — but it means two dangerous things. Anyone who can talk to the Docker socket effectively has root on the host, and any container that escapes its namespace while running as root arrives on the host as root. You can mitigate the second with user-namespace remapping, but the daemon itself is still a root-owned process.
Rootless mode removes that last root process. The daemon runs under your user account, and Linux user namespacesmap your single real UID to a range of subordinate UIDs so containers can still have their own “root” and multiple users internally. To the host kernel, though, all of it is just your unprivileged account. Introduced experimentally in Docker 19.03 and supported since 20.10, it is now a mature option rather than an experiment.
Prerequisites
Rootless mode leans on a few kernel and userspace features. On a modern distribution most are already present, but check them before you start:
- The
newuidmapandnewgidmapsetuid helpers, shipped in theuidmappackage. - A range of subordinate UIDs and GIDs assigned to your user in
/etc/subuidand/etc/subgid(at least 65,536 IDs). - cgroup v2 with a systemd user session if you want to enforce CPU, memory, and PID limits per container.
- A kernel new enough (5.11+) for rootless overlay2, or the
fuse-overlayfspackage as a fallback.
# Debian/Ubuntu: install the helpers and confirm your subordinate ID range sudo apt-get install -y uidmap grep "^$(whoami):" /etc/subuid /etc/subgid # e.g. yourname:100000:65536 -> 65536 subordinate IDs starting at 100000
Installing the rootless daemon
If Docker is already installed system-wide, the packaged setup tool provisions a per-user daemon. Run it as your normal user — not with sudo:
# Provision the rootless daemon for the current user dockerd-rootless-setuptool.sh install # Point your client at the per-user socket export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock # Start it as a user service and keep it running after logout systemctl --user enable --now docker sudo loginctl enable-linger "$(whoami)"
On a machine with no Docker at all, the convenience installer does the same in one step:
curl -fsSL https://get.docker.com/rootless | sh
The loginctl enable-linger line matters: without it, your user services (and therefore the daemon) stop when you log out, which is rarely what you want on a server.
Verifying it is really rootless
Confirm the daemon and containers are running under your user, not root:
# The context and security options should report rootless
docker info --format '{{ .SecurityOptions }}'
# expect a line containing: name=rootless
# The daemon process should be owned by your user, not root
ps -o user= -C dockerd
# expect your username
# A container "root" maps to an unprivileged host UID
docker run --rm alpine id
# uid=0 inside, but on the host it is one of your subordinate UIDsThat last point is the whole idea: uid=0 inside the container is a subordinate UID on the host, so “root” in the container owns nothing outside its namespace.
The tradeoffs, honestly
Rootless mode is a genuine security win, but it is not free. Know these before you migrate production workloads:
- Networking. Container traffic runs through a userspace network stack (RootlessKit with slirp4netns or a built-in equivalent), which is slower than the kernel bridge and changes how source IPs appear. High-throughput or latency-sensitive services should benchmark it.
- Privileged ports. Binding ports below 1024 needs an extra step (below), because that is a privileged operation.
- Resource limits.
--memory,--cpus, and--pids-limitonly take effect with cgroup v2 and a systemd user session. - Storage. Rootless overlay2 needs a 5.11+ kernel; otherwise you fall back to fuse-overlayfs, which is slower.
- Not everything works. Host networking, some bind-mount patterns, and a handful of privileged workloads behave differently or not at all.
To allow low ports, either lower the unprivileged threshold or grant the capability to the RootlessKit binary:
# Option A: allow all users to bind low ports (host-wide sysctl) echo 'net.ipv4.ip_unprivileged_port_start=0' | sudo tee /etc/sysctl.d/99-rootless.conf sudo sysctl --system # Option B: grant the bind capability to rootlesskit only, then restart sudo setcap cap_net_bind_service=ep "$(which rootlesskit)" systemctl --user restart docker
Rootless Docker vs Podman
It is worth being honest that Docker is not the only way to get here. Podman was designed rootless and daemonless from the start — there is no long-running root process at all, and it is largely CLI-compatible with Docker. If you are building a host from scratch and rootless operation is a hard requirement, Podman reaches it with fewer moving parts. If you already run Docker and want the same security benefit without changing your tooling, rootless Docker is the incremental path. Both end up in the same place: no root-owned container daemon.
When rootless is the wrong choice
Rootless mode is a security upgrade, but it is not universally the right call, and pretending otherwise leads to painful migrations. Skip it, or plan carefully, when any of these apply:
- You need host networking or raw performance. The userspace network stack adds overhead and changes source-IP behavior; a high-throughput edge proxy on bare metal should benchmark before committing.
- You depend on privileged device access. Some GPU, FUSE, or low-level device workflows expect capabilities that are awkward or unavailable rootless.
- You are already on Kubernetes. Managed clusters usually run containerd or CRI-O, not dockerd, so rootless Docker is mostly a concern for single hosts, CI runners, and developer laptops rather than the cluster itself.
The sweet spot is exactly those single-host and CI cases: a build runner that executes untrusted pull-request code, or a developer machine, gains a real security boundary from rootless mode at almost no cost. A latency-critical production service on dedicated hardware is where you weigh the tradeoffs most carefully — and where user-namespace remapping can be a lighter-touch middle ground that still keeps container root off the host.
Where ScanRook fits
Rootless mode hardens how a container runs. It does nothing about what is inside the image. A rootless container is still running whatever packages you built into it, and if one of them carries a critical CVE, the flaw is exploitable in-process regardless of how unprivileged the daemon is. That is the gap scanning closes: ScanRook reads the package databases inside each image layer and matches every component against OSV, NVD, and vendor advisory data, so you know what you are shipping. Pair rootless mode with a scan in CI and you are covering both halves — the runtime boundary and the software inside it. The full CI workflow is in how to scan a Docker image for vulnerabilities, and broader runtime guidance lives in our container scanning best practices.
Frequently asked questions
What is Docker rootless mode?
Running the Docker daemon and containers as an unprivileged user via user namespaces, so a break-out or daemon bug lands as a normal user rather than host root. Supported since Docker 20.10.
Rootless mode vs userns-remap?
userns-remap keeps the daemon as root and only remaps container users; rootless runs the daemon itself unprivileged. Rootless is the stronger boundary with more tradeoffs.
Can it bind ports under 1024?
Not by default. Lower net.ipv4.ip_unprivileged_port_start or grant CAP_NET_BIND_SERVICE to rootlesskit — or front it with a proxy on a high port.
Does it replace image scanning?
No. Rootless mode limits blast radius on the host but does not remove vulnerable packages inside the image. Scan images as well.
Rootless runtime, scanned images
Rootless mode contains the runtime; scanning cleans up what you ship. Upload an image to ScanRook to see every installed package matched against OSV, NVD, and vendor advisories, each finding tagged with its source and confidence.