16.2.3.1 Ownership Mismatch
A focused guide to Ownership Mismatch, connecting core concepts with practical Docker and container operations.
An ownership mismatch is a specific category of permission problem rooted in numeric user and group ID differences between the container's internal user namespace and the host's, or between two different containers sharing the same volume, producing files that appear to have an unexpected, sometimes confusing owner when inspected from the other side of that boundary, even when no actual security policy like SELinux or AppArmor is involved at all.
Why UIDs, not usernames, are what actually matters
Linux permission enforcement operates on numeric user and group IDs, not on usernames; a username is just a label mapped to a UID through /etc/passwd, and that mapping is entirely local to whichever filesystem namespace, the host's or a given container's, is doing the lookup at any moment:
docker exec my-api id
uid=1000(appuser) gid=1000(appuser)
ls -la /srv/app/data
drwxr-xr-x 2 1000 1000 4096 Jun 1 12:00 data
If the host has no user actually mapped to UID 1000, files appear owned by a numeric UID rather than a name when viewed from the host, which is not an error, just a reflection of the fact that ownership is fundamentally numeric and the host simply has no corresponding name mapped to that particular number.
Files created by a container appearing oddly owned on the host
A container writing to a bind-mounted directory creates files with whatever UID the container process runs as, and if that UID does not correspond to any user on the host, those files appear owned by an unfamiliar or even negative-looking numeric ID when inspected with host tools:
docker run -v /srv/app/data:/app/data --user 5000:5000 my-api
ls -la /srv/app/data
-rw-r--r-- 1 5000 5000 1024 Jun 1 12:00 output.txt
This is expected behavior, not a malfunction, but it can be surprising and can cause a host-side process expecting to read or modify that file, running as a different user, to encounter a permission error of its own, since the file's actual ownership genuinely does not match what that host-side process is running as.
Aligning container and host UIDs deliberately
The most direct fix for ownership mismatches affecting bind-mounted directories is deliberately running the container with a UID that matches whatever user on the host needs to interact with the same files, rather than leaving it to whatever default UID the image happens to define:
id -u
docker run -v "$(pwd)/data":/app/data --user "$(id -u):$(id -g)" my-api
Passing the host user's actual UID and GID explicitly at container run time ensures files created inside the container are owned, from the host's perspective, by exactly the user who needs to work with them afterward, removing the mismatch at its source rather than needing to correct ownership after the fact.
Build-time UID configuration for predictable ownership
For images expected to be run consistently with a known, specific UID rather than dynamically passed at run time, defining that UID explicitly during the build, rather than relying on whatever default the base image happens to assign, makes ownership behavior predictable and documented rather than incidental:
RUN groupadd -g 1000 appgroup && useradd -u 1000 -g appgroup appuser
USER appuser
Choosing a specific, documented UID this way, rather than accepting whatever a base image's default non-root user happens to be, makes it straightforward for anyone deploying the image to know in advance what UID will own any files it creates on a mounted volume.
Ownership conflicts between multiple containers sharing a volume
When two different containers, potentially built from different images with different default users, share the same volume, ownership conflicts can arise if each expects to own the files it creates, but the other container's process cannot then read or write those same files due to a UID mismatch between the two:
services:
api:
user: "1000:1000"
volumes:
- shared-data:/data
worker:
user: "1000:1000"
volumes:
- shared-data:/data
Explicitly aligning both services to the same UID and GID, rather than leaving each to its own image's default, resolves this directly for any volume genuinely intended to be shared and written to by more than one service.
Correcting ownership on an existing volume after the fact
For a volume that already has files with mismatched ownership from before the underlying UID configuration was corrected, a one-off container can be used to recursively fix ownership directly:
docker run --rm -v shared-data:/data alpine chown -R 1000:1000 /data
This is a reasonable, direct fix for existing data; going forward, ensuring every container that writes to the volume consistently uses the same UID prevents the mismatch from recurring on newly created files.
User namespace remapping and its effect on apparent ownership
When Docker's user namespace remapping feature is enabled, UIDs inside a container are mapped to a different, typically much higher range of UIDs on the host, which means files created by a container appear owned by these remapped, unfamiliar-looking host UIDs rather than the UID the container's own process believes it is running as:
{
"userns-remap": "default"
}
ls -la /var/lib/docker/<remapped-uid>.<remapped-gid>/volumes/my-volume/_data
This remapping is a deliberate security feature, isolating what a container's root user can actually do against the host even if compromised, and the resulting unfamiliar host-side ownership is an expected, intentional consequence of that isolation rather than a misconfiguration needing to be corrected.
Common mistakes
- Treating an unfamiliar numeric UID shown for a file's ownership as evidence of an error, when it is simply the accurate reflection of a UID with no corresponding name mapped on the host.
- Not explicitly aligning a container's UID with the host user that needs to interact with the same bind-mounted files, leaving ownership mismatched by default.
- Allowing two different containers sharing a volume to each use their own image's default UID rather than deliberately aligning both to the same value.
- Fixing existing ownership on a shared volume without also addressing the underlying configuration that will otherwise cause newly created files to mismatch again.
- Mistaking the unfamiliar, remapped host-side ownership produced by user namespace remapping for a misconfiguration, rather than recognizing it as the intended, security-motivated behavior of that feature.
Ownership mismatches are resolved by remembering that Linux permission enforcement is fundamentally numeric, not name-based, and that aligning the actual UID and GID values, deliberately and explicitly, across every container and host process that needs to interact with the same files is what closes the gap, rather than anything related to usernames, image defaults, or assumptions carried over from non-containerized development.