User Namespace Remapping, UID/GID Mapping, Non-Root Images, Filesystem Ownership, and Least Privilege: Diagnostics, Failure Modes, Security, and Performance
Diagnose ownership and permission failures by separating image identity, runtime UID/GID, supplementary groups, user-namespace mapping, mount ownership, and daemon mode.
Learning objectives
- Diagnose permission failures by walking image user, runtime user, supplementary groups, namespace mappings, inode ownership/mode, ACL/LSM policy, and daemon mode.
-
Explain why
chmod 777, casual--userns=host, and ad-hoc root execution hide rather than solve identity problems. - Recognize migration risk when enabling userns-remap on a populated daemon and subordinate-range overlap as a host security defect.
- Apply the smallest safe correction while preserving the original evidence.
1. Evidence-first diagnostic sequence for permission and identity failures
- Preserve the exact failing operation and error.
- Confirm client context, Engine version, daemon security options, and rootless/userns mode.
- Confirm image digest and image
Config.User. -
Confirm container runtime
.Config.User,id, supplementary groups, UID/GID maps. - Confirm mount type/source/target and host/volume numeric owner/mode/ACL/LSM labels.
- Confirm whether the path should be mutable at all.
- Apply the narrowest ownership/group/user correction and rerun only the failing operation.
2. Failure: chmod 777 “works” but destroys the security contract
World-write permission can hide a UID/GID mismatch by authorizing almost everyone. It also makes incident analysis harder because the filesystem no longer tells you which principal was intended to own the path.
# Evidence before any fix
id
stat -c '%u:%g %a %n' /path/to/disposable/data 2>/dev/null || true
docker inspect CONTAINER --format 'User={{json .Config.User}} Mounts={{json .Mounts}}' 2>/dev/null || true
The fix should be a precise owner, group, ACL, or application path—not a global mode expansion.
3. Failure: same username, different numeric identity
The host may have app as UID 1005 while the image
defines app as UID 10001. A bind mount checks the
numbers, not the matching text label. Capture id app on
each side and stat on the inode. If portability depends
on host integration, define the numeric contract explicitly.
4. Failure: enabling userns-remap on a populated daemon masks prior state
Docker documents that enabling userns-remap changes the ownership/storage layout under Docker’s data root and effectively masks existing images/containers/objects from the remapped daemon view. That is why Docker recommends enabling it on a new installation. Treat this as a migration project, not a troubleshooting toggle.
Preserve inventory/backups, plan downtime, test storage
drivers/plugins, and define rollback. Do not switch
userns-remap on and off to “see if permissions
improve.”
5. Failure: overlapping subordinate ranges
Subordinate UID/GID ranges must not overlap between identities that need isolation. Overlap is a host identity configuration defect because one namespace could map into IDs assigned to another. Do not hand-edit ranges by guess. Use distribution/user-management tooling or an administrator-approved allocation plan, then record the resulting ranges.
6. Failure: casual --userns=host bypass
When userns-remap is enabled, --userns=host disables
remapping for that container. Docker also documents nuanced
ownership effects because image layers remain shared/remapped. Treat
this as a security-sensitive exception requiring a documented
reason—not a generic permission fix.
7. Intentionally broken example: runtime UID does not match prepared path
docker run --rm --user 20002:20002 da-ch27-app:lab sh -c 'id; echo test > /work/probe.txt' 2>&1 | tee /tmp/da-ch27-user-failure.txt || true
docker image inspect da-ch27-app:lab --format 'ImageUser={{json .Config.User}}'
# Then inspect the actual mount/path ownership before changing anything.
The expected interpretation is “runtime identity and writable-path ownership disagree.” Rebuilding the network, deleting the image cache, or escalating to root would not correct that contract.
8. Performance and operational cost: ownership is also a deployment concern
Recursive chown of large persistent datasets can be
slow, can generate heavy metadata I/O, and can expand maintenance
windows. Repeating it on every startup compounds the cost. Prefer
deterministic image ownership for image content and deliberate
one-time storage provisioning/migration for persistent data.
9. Least-destructive correction matrix
| Evidence | Correction candidate | Avoid |
|---|---|---|
| Wrong image-owned file UID |
Fix Dockerfile COPY --chown/build ownership
|
Runtime root shell hot-fix. |
| Wrong new volume owner | Provision volume once with intended UID/GID | World-write or recursive chown every start. |
| Shared writer group missing | Add precise shared GID / supplementary group | Shared UID or 0777. |
| Host bind owner mismatch | Align mapped numeric owner/group or choose different mount model | Assuming same username means same principal. |
| userns migration conflict | Plan fresh/migrated daemon and storage | Toggling userns-remap on production daemon. |
Knowledge check
Why is chmod 777 a poor default fix?
It broadens authority to everyone and hides the ownership/mapping defect instead of correcting the intended principal.
What is dangerous about overlapping subordinate UID/GID ranges?
Different user namespaces can map into the same host numeric identities, undermining isolation.
Why can enabling userns-remap on a populated daemon surprise operators?
Docker changes the remapped storage ownership/layout and masks previously visible Docker objects; it should be treated as migration.
Why is --userns=host not a routine permission
workaround?
It disables remapping for that container and changes a security boundary; Docker also documents nuanced shared-layer ownership effects.
An app can write /app but not a restored volume. What layer is primary?
Storage/identity: compare runtime UID/GID/groups, namespace mapping, and volume inode ownership before changing the image or network.
Official references and version notes
- User namespace remapping — current prerequisites, mapping behavior, daemon configuration, limitations, and migration cautions.
- Rootless UID/GID mapping — precise difference between userns-remap and rootless host-ID translation.
- Rootless mode — daemon-level non-root execution and subordinate-ID prerequisites.
- Dockerfile reference — USER and COPY --chown semantics, including numeric versus name lookup.
- Compose services reference — service user override and user namespace configuration surface.
- Bind mounts — host-path ownership, read/write authority, and daemon-host path semantics.
- Volumes — Docker-managed persistent storage and container mount behavior.
- Docker Engine 29 release notes — current Engine baseline and user-namespace-related fixes/changes.
Docker Engine 29.8.1 is the current Engine release. ' Docker
documents two different mappings: in userns-remap,
container UID/GID 0 maps to the first subordinate ID and ID
n maps to subordinate-start + n; in rootless mode,
container UID/GID 0 maps to the host user and IDs ≥1 map into the
subordinate range with an offset. ' Docker recommends enabling
userns-remap on a new daemon because existing Docker
objects become masked by the remapped storage layout, and it warns
that host-mounted filesystem ownership must be arranged for the
mapped IDs. ' COPY --chown accepts names or numeric
IDs; names require matching /etc/passwd//etc/group
inside the build rootfs, while numeric IDs do not. ' Compose
user overrides the image-configured user. Every lab
therefore records the actual Engine/context/security mode and
numeric UID/GID evidence instead of assuming usernames imply
equivalent authority.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.