Docker Rootless Mode: Running Containers Without Root Privileges
Docker runs as root by default, giving containers dangerous host access. Learn how to run Docker in rootless mode, what breaks, and how to fix common compatibility issues.
Docker Rootless Mode: Running Containers Without Root Privileges
By default, the Docker daemon runs as root. Every container it spawns inherits access to the host kernel with root-level capabilities. This means a container escape — through a kernel vulnerability, a misconfigured mount, or a compromised image — gives the attacker root access to your host.
Docker rootless mode eliminates this by running the entire Docker daemon and all containers as an unprivileged user. No root. No sudo. No elevated capabilities.
Why Docker Runs as Root (and Why That Is a Problem)
Docker needs root for three things:
- Network namespace creation — setting up virtual networks requires CAP_NET_ADMIN
- User namespace mapping — mapping container UIDs to host UIDs requires /etc/subuid
- cgroup management — resource limits (CPU, memory) require cgroup access
Historically, these operations required root. Docker chose convenience over security by running the daemon as root.
The consequences:
- A container breakout gives root access to the host
- Any process that can talk to the Docker socket (
/var/run/docker.sock) effectively has root - Mounting the Docker socket into a container (common for CI/CD) gives that container full host control
# This gives the container full root access to the host
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
# The container can now: create privileged containers, read any file, modify the host
Setting Up Docker Rootless Mode
Prerequisites
# Install uidmap (provides newuidmap/newgidmap)
sudo apt-get install -y uidmap dbus-user-session
# Configure subordinate UID/GID ranges
echo "youruser:100000:65536" | sudo tee -a /etc/subuid
echo "youruser:100000:65536" | sudo tee -a /etc/subgid
# Enable lingering (keeps user services running after logout)
sudo loginctl enable-linger youruser
Installation
Get more insights on Security
Join 2,000+ engineers who get our weekly deep-dives. No spam, unsubscribe anytime.
# Install rootless Docker (as your regular user, NOT root)
dockerd-rootless-setuptool.sh install
# Set environment variables (add to ~/.bashrc)
export PATH=/home/youruser/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
# Start the rootless daemon
systemctl --user start docker
systemctl --user enable docker
Verify It Works
# Check Docker is running rootless
docker info 2>/dev/null | grep -i "rootless\|security"
# Security Options: rootless
# Check the daemon process
ps aux | grep dockerd
# youruser 12345 ... dockerd-rootless
# Note: NO root process
# Run a container
docker run --rm alpine id
# uid=0(root) gid=0(root)
# The container THINKS it is root, but on the host it maps to youruser
What User Namespaces Actually Do
The key technology behind rootless Docker is user namespaces. Inside the container, processes see themselves as root (UID 0). On the host, they map to an unprivileged UID (e.g., 100000).
Container view: root (UID 0)
|
User namespace map: UID 0 → UID 100000 on host
|
Host view: youruser:100000 (unprivileged)
This means:
- A container breakout lands you as UID 100000 — an unprivileged user with no special access
- Files created by root inside the container appear as UID 100000 on host volumes
- The container cannot access files owned by actual root (UID 0) on the host
What Breaks in Rootless Mode (and How to Fix It)
Port Binding Below 1024
Rootless containers cannot bind to ports below 1024 (privileged ports):
# This fails in rootless mode
docker run -p 80:80 nginx
# Error: bind: permission denied
# Fix 1: Use a higher port
docker run -p 8080:80 nginx
# Fix 2: Allow unprivileged port binding (Linux kernel 4.11+)
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
# Add to /etc/sysctl.d/rootless.conf for persistence
Volume Permissions
Files written by the container appear as the mapped UID on the host:
docker run -v /home/youruser/data:/data alpine touch /data/test
ls -la /home/youruser/data/test
# -rw-r--r-- 1 100000 100000 0 Mar 23 12:00 test
# Fix: Use --userns-remap or chown inside the container
Overlay2 Storage Driver
Rootless Docker uses fuse-overlayfs instead of the kernel overlay2 driver. Performance is slightly lower for I/O-heavy workloads:
# Check storage driver
docker info | grep "Storage Driver"
# Storage Driver: fuse-overlayfs (rootless)
# vs: overlay2 (rootful)
# For better performance, use overlay2 with idmapped mounts (kernel 5.19+)
Docker Compose
Docker Compose works with rootless Docker, but ensure DOCKER_HOST points to the rootless socket:
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
docker compose up -d # Works normally
Networking Limitations
Rootless containers use slirp4netns or pasta for networking instead of iptables:
- No bridge networking — containers communicate via port mapping, not direct IP
- Slower than rootful networking — slirp4netns adds overhead
- No --net=host — host networking requires root capabilities
# Check which network driver is used
docker info | grep "Network"
# pasta (or slirp4netns)
Rootless Docker in Production
Free Resource
Infrastructure Security Audit Template
The exact audit template we use with clients: 60+ checks across network, identity, secrets management, and compliance.
Docker Compose Example
# docker-compose.yml (runs under rootless Docker)
services:
web:
image: nginx:alpine
ports:
- "8080:80" # Use port above 1024
read_only: true # Extra hardening
tmpfs:
- /tmp
- /var/cache/nginx
api:
image: node:20-slim
ports:
- "3000:3000"
environment:
- NODE_ENV=production
volumes:
- ./app:/app:ro
read_only: true
tmpfs:
- /tmp
db:
image: postgres:16-alpine
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
pgdata:
Systemd Service
# ~/.config/systemd/user/docker-compose-app.service
[Unit]
Description=My App (rootless Docker)
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/youruser/app
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=default.target
Rootless vs Other Hardening Approaches
| Approach | Protects Against | Overhead | Compatibility |
|---|---|---|---|
| Rootless Docker | Container breakout → root access | Low | Some features break |
| Podman (daemonless) | Same as rootless + no daemon socket | Low | Different CLI |
| gVisor (runsc) | Kernel exploits | Medium | Syscall compatibility |
| Kata Containers | Full VM isolation | High | Near-full compatibility |
| Seccomp profiles | Specific syscall attacks | None | Per-container config |
Rootless Docker is the lowest-friction hardening you can apply. It does not replace seccomp or AppArmor — stack them together.
Migration Checklist
Moving from rootful to rootless Docker:
- Audit port usage — identify anything binding below 1024
- Check volume permissions — files will be owned by mapped UIDs
- Test networking — ensure services can communicate via port mapping
- Update CI/CD — runners need DOCKER_HOST pointing to rootless socket
- Benchmark I/O — fuse-overlayfs may be slower for database workloads
- Update monitoring — cAdvisor and Docker metrics need rootless socket path
The Bottom Line
Docker running as root is a design decision from 2013 that prioritized ease of use over security. Rootless mode, available since Docker 20.10, eliminates the most dangerous consequence of container escapes: landing as root on the host.
The compatibility issues are real but manageable. Port binding, volume permissions, and networking all have straightforward fixes. For most workloads, rootless Docker is a drop-in replacement that dramatically reduces your blast radius.
If you are running Docker in production and have not switched to rootless mode, you are one container escape away from full host compromise. The migration takes an afternoon. The security improvement is permanent.
Related Service
Security & Compliance
Zero-trust architecture, compliance automation, and incident response planning.
Need help with security?
TechSaaS provides expert consulting and managed services for cloud infrastructure, DevOps, and AI/ML operations.
We Will Build You a Demo Site — For Free
Like it? Pay us. Do not like it? Walk away, zero complaints. You will spend way less than hiring developers or any agency.
No spam. No contracts. Just a free demo.