Q: Your enterprise hosts legacy microservices that cannot easily be rewritten to run as unprivileged users (`USER nonroot`) due to third-party dependencies requiring `chown` or package installation on startup. Running these containers as root (`UID 0`) means any container breakout vulnerability (such as CVE-2024-21626) grants instant root access to the host node. You must implement host-wide user namespace remapping in `/etc/docker/daemon.json`, configure `/etc/subuid` ranges, and solve file ownership permission conflicts on persistent volume mounts.
Configure daemon-wide user namespace remapping (`userns-remap`) in Docker. Protect multi-tenant hosts by automatically mapping container root (UID 0) to unprivileged host UIDs without breaking volume mounts.
Want to master this scenario in a live sandbox? KodeKloud's Docker Certified Associate (DCA) Hands-On Lab Course covers this exact problem with hands-on terminal drills.
🛠️ Production Runbook & Step-by-Step Resolution
Understand the Mechanics of User Namespace Remapping
User namespaces map a range of UIDs and GIDs inside the container to a distinct, unprivileged range on the host. When a container runs a process as UID 0 (root), the host kernel sees that process as UID 100000. Any attempt to write to host `/etc` or access host devices is blocked by the kernel.
<!-- UID Mapping Scheme -->
Container View (Inside):
UID 0 (root) ───> Can manage container files, bind ports (inside netns)
UID 1000 ───> Regular container user
Host Kernel View (Outside):
Host PID UID: 100000 (Unprivileged SubUID! Zero host permissions)
Host PID UID: 101000
Allocate Subordinate UIDs and GIDs
Create dedicated system user `dockremap` and assign an isolated 65,536 UID/GID range in `/etc/subuid` and `/etc/subgid`.
# Add dockremap user and allocation
sudo useradd -r -s /bin/false dockremap
echo "dockremap:100000:65536" | sudo tee -a /etc/subuid
echo "dockremap:100000:65536" | sudo tee -a /etc/subgid
Enable userns-remap in daemon.json
Configure Docker daemon to use the `dockremap` subordinate namespace and restart the Docker service. Notice that Docker re-initializes its graph driver directory under `/var/lib/docker/100000.100000/`.
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"userns-remap": "dockremap"
}
EOF
sudo systemctl restart docker
# Verify mapped storage directory created
ls -ld /var/lib/docker/100000.100000
Solve Volume Mount Permission Denied Conflicts
When mounting host directories (`-v /opt/data:/data`), host files owned by root (`UID 0`) will be read-only or inaccessible to the container process (`UID 100000`). Chown the host directory to the remapped UID range.
# Chown host directory to mapped subordinate UID
sudo chown -R 100000:100000 /opt/data
# Run container and verify root mapping
docker run --rm -v /opt/data:/data alpine touch /data/test.txt
ls -l /opt/data/test.txt
# Host view shows: -rw-r--r-- 1 100000 100000 ... test.txt
- T
- o
- s
- e
- c
- u
- r
- e
- l
- e
- g
- a
- c
- y
- w
- o
- r
- k
- l
- o
- a
- d
- s
- t
- h
- a
- t
- s
- t
- u
- b
- b
- o
- r
- n
- l
- y
- r
- e
- q
- u
- i
- r
- e
- r
- o
- o
- t
- e
- x
- e
- c
- u
- t
- i
- o
- n
- i
- n
- s
- i
- d
- e
- c
- o
- n
- t
- a
- i
- n
- e
- r
- s
- ,
- w
- e
- i
- m
- p
- l
- e
- m
- e
- n
- t
- e
- d
- D
- o
- c
- k
- e
- r
- u
- s
- e
- r
- n
- a
- m
- e
- s
- p
- a
- c
- e
- r
- e
- m
- a
- p
- p
- i
- n
- g
- (
- `
- u
- s
- e
- r
- n
- s
- -
- r
- e
- m
- a
- p
- `
- )
- .
- C
- o
- n
- t
- a
- i
- n
- e
- r
- r
- o
- o
- t
- (
- U
- I
- D
- 0
- )
- m
- a
- p
- s
- t
- o
- h
- o
- s
- t
- U
- I
- D
- 1
- 0
- 0
- 0
- 0
- 0
- .
- I
- f
- a
- n
- a
- t
- t
- a
- c
- k
- e
- r
- e
- x
- p
- l
- o
- i
- t
- s
- a
- r
- u
- n
- t
- i
- m
- e
- b
- r
- e
- a
- k
- o
- u
- t
- ,
- t
- h
- e
- y
- a
- r
- r
- i
- v
- e
- o
- n
- t
- h
- e
- h
- o
- s
- t
- f
- i
- l
- e
- s
- y
- s
- t
- e
- m
- a
- s
- a
- n
- u
- n
- p
- r
- i
- v
- i
- l
- e
- g
- e
- d
- n
- o
- b
- o
- d
- y
- u
- s
- e
- r
- w
- i
- t
- h
- z
- e
- r
- o
- h
- o
- s
- t
- a
- c
- c
- e
- s
- s
- .