Rootless Docker
Rootless Docker allows running the Docker daemon and containers without root privileges, significantly reducing the impact of container escapes. This guide covers installation, security benefits, limitations, and when to use rootless mode.
Rootless Docker is a mode that allows the Docker daemon and containers to run without root privileges on the host system. In traditional Docker, the daemon runs as root, creating a potential security risk—if a container escapes, the attacker gains root access on the host. Rootless Docker runs the daemon and containers in a user namespace, mapping container root (UID 0) to an unprivileged user on the host.
This significantly reduces the impact of a container escape. Even if an attacker breaks out of a container, they only gain the privileges of the user running Docker, not root. Rootless mode is a major security improvement, especially for multi-tenant environments or untrusted workloads.
Rootless Docker leverages Linux user namespaces, a kernel feature that allows a non-root user to act as root inside a namespace while remaining unprivileged outside. The Docker daemon runs as your user, and containers run inside a user namespace where UID 0 (root) is mapped to your unprivileged host UID.
Additionally, Rootless Docker uses several other technologies: slirp4netns for network connectivity, fuse-overlayfs for storage (or native overlayfs with kernel support), and cgroup v2 for resource limits (optional).
# Check if user namespaces are supported
cat /proc/sys/user/max_user_namespaces
# Check kernel version (needs 4.18+ for full support)
uname -r
# Verify rootless mode is active
docker info | grep -i rootless
# Check mapping of container root to host user
cat /proc/self/uid_map
Installing Rootless Docker is straightforward. You don't need to uninstall regular Docker—rootless can run alongside it.
# Install rootless Docker (Ubuntu/Debian)
curl -fsSL https://get.docker.com/rootless | sh
# Or manually install
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh --dry-run
sh get-docker.sh --disable-rootless=false
# Add to PATH in your shell config (~/.bashrc)
export PATH=/home/$USER/bin:$PATH
export DOCKER_HOST=unix:///run/user/$UID/docker.sock
# Start rootless Docker service
systemctl --user start docker
systemctl --user enable docker
# Verify installation
docker info
# Check that rootless mode is active
docker info | grep -i "rootless"
# Stop rootless Docker
systemctl --user stop docker
| Feature | Rootful Docker | Rootless Docker |
|---|---|---|
| Daemon privileges | Runs as root | Runs as unprivileged user |
| Container escape impact | Root access on host | Unprivileged user access |
| Cgroup support | Full (cgroup v1 and v2) | Limited (cgroup v2 only) |
| Network performance | Native | slirp4netns (overhead) |
| Overlay networks (Swarm) | Supported | Not supported |
| AppArmor/SELinux | Full support | Limited |
| --privileged flag | Works | Not supported (security risk) |
| Host network (--net=host) | Works | Not supported |
- Reduced attack surface - The Docker daemon doesn't run as root, limiting damage from vulnerabilities.
- Container escape mitigation - Even if a container escapes, the attacker only gets your user privileges, not root.
- No privileged containers - The --privileged flag is disabled, preventing containers from gaining host root.
- Better multi-tenant isolation - Different users can run their own Docker daemons without interfering.
- No sudo required - No need to add users to the docker group (which is equivalent to root access).
- No Swarm mode - Overlay networks and Docker Swarm are not supported in rootless mode.
- No host network mode - `--network host` doesn't work because the container can't access the host's network stack.
- No privileged containers - `--privileged` flag is not supported (security feature).
- Cgroup v2 required - For resource limits (CPU, memory), you need cgroup v2 enabled on the host.
- Performance overhead - Network has overhead due to slirp4netns (though usually acceptable).
- No AppArmor/SELinux profiles - These LSM features don't work in rootless mode.
- Storage driver limitations - Overlayfs requires extra configuration; fuse-overlayfs works but has overhead.
- No checkpoint/restore - CRIU doesn't work in rootless mode.
For resource limits (memory, CPU, pids) to work in rootless Docker, your host must use cgroup v2. Most modern Linux distributions now use cgroup v2 by default (Ubuntu 22.04+, Fedora 31+, Debian 11+).
# Check cgroup version
mount | grep cgroup2
# If output shows cgroup2, you're on v2
# Or check
stat -fc %T /sys/fs/cgroup/
# "cgroup2fs" means v2, "tmpfs" means v1
# Enable cgroup v2 (Ubuntu - requires reboot)
# Edit kernel command line in /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=1"
# Update grub
sudo update-grub
sudo reboot
# For rootless Docker, enable delegation
sudo mkdir -p /etc/systemd/system/user@.service.d
cat <
With cgroup v2 enabled, resource limits work the same way as in rootful Docker:
# Run container with memory limit
docker run --memory=512m --memory-swap=1g nginx
# Run with CPU limit
docker run --cpus=0.5 nginx
# Run with PIDs limit
docker run --pids-limit=100 nginx
# Check that limits are applied
docker stats
# Note: Without cgroup v2, these commands will work but limits won't be enforced
Rootless Docker uses slirp4netns to provide network connectivity. This creates a user-mode network stack that forwards traffic to the host. The performance is lower than native networking but sufficient for most workloads.
# Check slirp4netns version
slirp4netns --version
# Port forwarding works as usual
docker run -d -p 8080:80 nginx
# Inter-container communication works on user-defined bridges
docker network create mynet
docker run --network mynet --name app1 nginx
docker run --network mynet alpine ping app1
# Note: --network host is NOT supported
docker run --network host nginx # This will fail
- Multi-tenant environments - Different users can run Docker independently without root access.
- Shared development servers - Developers can run Docker without needing sudo or docker group membership.
- CI/CD runners - Reduce security risk from untrusted code running in pipelines.
- Education and training - Students can learn Docker without root access.
- High-security environments - Where container escape is a major concern.
- Personal workstations - Safer default for everyday Docker usage.
# Check if rootless mode is active
docker info | grep Rootless
# View rootless daemon logs
journalctl --user -u docker
# Check user namespace support
cat /proc/sys/user/max_user_namespaces
# If 0, enable with: sudo sysctl -w user.max_user_namespaces=10000
# Check cgroup support
docker run --rm --memory=256m alpine cat /sys/fs/cgroup/memory/memory.limit_in_bytes
# Reset rootless Docker
systemctl --user stop docker
rm -rf ~/.local/share/docker
systemctl --user start docker
# Check slirp4netns
which slirp4netns
sudo apt install slirp4netns # if missing
Rootless Docker significantly improves container security by eliminating root privileges. While it has limitations, it's an excellent choice for development, CI/CD, and many production workloads.