Mirror host user ownership in and out of rootful Docker containers.
The goal of this project is to unify mount permissions in and out of containers, regardless of the container engine context. Whether you're using rootful Docker, rootless Docker, or Podman, this project will configure your host environment and container to ensure mount items are owned by the host user, not root.
The primary focus of this project is to improve the developer experience of working with containerized toolchains. Rather than requiring a rootless context, you can incorporate Docker User Mirror to become context agnostic!
Lets say you want to mount a volume inside a bind mount.
-v ./:/app -v /app/volume
Here's what would happen with rootful Docker on Linux systems:
(IMAGE_ID="debian:latest"; \
docker run --rm -u "$(id -u):$(id -g)" -v ./:/app -v /app/volume -w /app "$IMAGE_ID" sh -c \
'id && find volume -printf "%m %u:%g %f (container)\n"' && \
docker image rm "$IMAGE_ID" >/dev/null) && \
find volume -printf "%m %u:%g %f (host)\n" && \
rm -rf volume
uid=1000 gid=1000 groups=1000
755 root:root volume (container) ⇐😭
755 root:root volume (host) ⇐😭
Even though we used the -u, --user
option to mirror the host user inside the container, volume
still ends up being owned by root
! What a pain!
Thankfully, that's where this project steps in to help:
(IMAGE_ID="$(docker build -q image/)"; \
./user-mirror docker run --rm -v ./:/app -v /app/volume -w /app "$IMAGE_ID" sh -c \
'id && find volume -printf "%m %u:%g %f (container)\n"' && \
docker image rm "$IMAGE_ID" >/dev/null) && \
find volume -printf "%m %u:%g %f (host)\n" && \
rm -rf volume
uid=1000(user) gid=1000(user) groups=1000(user)
755 user:user volume (container) ⇐🥳
755 user:user volume (host) ⇐🥳
It even works with rootless Docker and Podman!
uid=0(root) gid=0(root) groups=0(root)
755 root:root volume (container)
755 user:user volume (host)
- Copy
entrypoint
to the directory of your Dockerfile. - Copy
user-mirror
to the directory of yourdocker-compose.yml
. - Append
Dockerfile.user-mirror
to your Dockerfile. - Merge
docker-compose.yml
with your existingdocker-compose.yml
(cap_add
,cap_drop
,entrypoint
,environment
).
The user-mirror
script combined with the entrypoint
script mirror the host user inside the container at runtime, and chown
objects created by Docker. This alongside preemptive creation of host bind mount objects before the Docker daemon eliminates ownership mismatches.
docker compose build
./user-mirror docker compose run --rm {service}
podman compose build
./user-mirror podman compose run --rm {service}
Run ci
to run the test scripts in test/
with the images in images/
using both Docker Compose and Podman Compose (if installed).