{"id":17382970,"url":"https://github.com/ajgranowski/docker-user-mirror","last_synced_at":"2025-08-03T01:33:02.950Z","repository":{"id":251122409,"uuid":"834413704","full_name":"AJGranowski/docker-user-mirror","owner":"AJGranowski","description":"Mirror host user ownership in and out of rootful Docker containers.","archived":false,"fork":false,"pushed_at":"2024-12-02T05:21:49.000Z","size":215,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-02T06:22:17.417Z","etag":null,"topics":["docker","docker-compose","dockerfile","ownership","permissions","podman","podman-compose","shell","shell-script","shell-scripts"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AJGranowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-27T07:36:27.000Z","updated_at":"2024-12-02T05:21:45.000Z","dependencies_parsed_at":"2024-08-27T18:03:10.012Z","dependency_job_id":"60293f7b-f197-4fce-a510-10eb646dc183","html_url":"https://github.com/AJGranowski/docker-user-mirror","commit_stats":null,"previous_names":["ajgranowski/docker-user-mirror"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AJGranowski%2Fdocker-user-mirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AJGranowski%2Fdocker-user-mirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AJGranowski%2Fdocker-user-mirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AJGranowski%2Fdocker-user-mirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AJGranowski","download_url":"https://codeload.github.com/AJGranowski/docker-user-mirror/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228516438,"owners_count":17932442,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","dockerfile","ownership","permissions","podman","podman-compose","shell","shell-script","shell-scripts"],"created_at":"2024-10-16T07:40:01.916Z","updated_at":"2025-08-03T01:33:02.935Z","avatar_url":"https://github.com/AJGranowski.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Total Downloads][downloads-badge]](#)\n[![CI/CD][cicd-badge]][cicd-link]\n[![OpenSSF Scorecard][scorecard-badge]][scorecard-link]\n[![OpenSSF Best Practices][best-practices-badge]][best-practices-link]\n\n\u003cheader align=\"center\"\u003e\n    \u003ch1 align=\"center\"\u003eDocker User Mirror\u003c/h1\u003e\n    \u003cp align=\"center\"\u003eMirror host user ownership in and out of rootful Docker containers.\u003c/p\u003e\n\u003c/header\u003e\n\n## How It Works\nThis projects uses a pair of scripts to mirror the host user in a container:\n\n```shell\ndocker compose build\n./user-mirror docker compose run --rm {{service}}\n```\n\n1. `entrypoint` (build time): Install `setpriv` or `gosu`.\n2. `user-mirror`: Create mount source items on the host before Docker does (so they're owned by the current host user rather than root).\n3. `user-mirror`: Inject environment variables into the Docker/Podman command and run it.\n4. `entrypoint` (run time): Create a mirrored host user in the container from the injected environment variables.\n5. `entrypoint` (run time): `chown` mount destination items in the container to the mirrored user.\n6. `entrypoint` (run time): Step-down from root to the mirrored user to execute the command.\n\n## Getting Started\n1. Copy the `entrypoint` script to the directory of your Dockerfile.\n2. Copy the `user-mirror` script to the root of your project.\n3. Append `Dockerfile.user-mirror` to your project's Dockerfile.\n4. Add `cap_add`, `cap_drop`, and `environment` from `compose.yml` to your project's compose file.\n5. Prepend your project's compose entrypoint with `[/entrypoint, --,` ...\n\n## Why?\nLets say you want to mount a volume inside a bind mount.\n```\n-v ./:/app -v /app/volume\n      ↑            ↖ volume mount within the exiting bind mount (/app)\n  bind mount\n```\n\nHere's what would happen with rootful Docker on Linux systems:\n```shell\n(IMAGE_ID=\"debian:latest\"; \\\ndocker run --rm -u \"$(id -u):$(id -g)\" -v ./:/app -v /app/volume -w /app \"$IMAGE_ID\" sh -c \\\n'id \u0026\u0026 find volume -printf \"%m %u:%g %f (container)\\n\"' \u0026\u0026 \\\ndocker image rm \"$IMAGE_ID\" \u003e/dev/null) \u0026\u0026 \\\nfind volume -printf \"%m %u:%g %f (host)\\n\" \u0026\u0026 \\\nrm -rf volume\n```\n```\nuid=1000 gid=1000 groups=1000\n755 root:root volume (container) ⇐😭\n755 root:root volume (host)      ⇐😭\n```\n\nEven 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!\n\nThankfully, that's where this project steps in to help:\n```shell\n(IMAGE_ID=\"$(docker build -q image/)\"; \\\n./user-mirror docker run --rm -v ./:/app -v /app/volume -w /app \"$IMAGE_ID\" sh -c \\\n'id \u0026\u0026 find volume -printf \"%m %u:%g %f (container)\\n\"' \u0026\u0026 \\\ndocker image rm \"$IMAGE_ID\" \u003e/dev/null) \u0026\u0026 \\\nfind volume -printf \"%m %u:%g %f (host)\\n\" \u0026\u0026 \\\nrm -rf volume\n```\n```\nuid=1000(user) gid=1000(user) groups=1000(user)\n755 user:user volume (container) ⇐🥳\n755 user:user volume (host)      ⇐🥳\n```\n\nAlso compatible with rootless Docker and Podman!\n```\nuid=0(root) gid=0(root) groups=0(root)\n755 root:root volume (container)\n755 user:user volume (host)\n```\n\nThe big benefit to using this project over [other workarounds](https://github.com/moby/moby/issues/2259) is that it's all automatic. The file ownership fixes are all inferred directly from your command or compose specification.\n\n## Development\nRun `ci` to run the test scripts in `test/` with the images in `images/` using both Docker Compose and Podman Compose (if installed).\n\nThis project is full CI/CD. All changes to `main` that satisfy *all* of the following conditions will automatically get released as a new patch version:\n* Changes that do not have `#skip-auto-release` in the commit body.\n* Changes that could affect release artifacts.\n* Changes that pass all tests on rootful Docker, rootless Docker, and Podman.\n\n----\n\n\u003ch2 align=\"center\"\u003ePartner Projects\u003c/h2\u003e\n\n* [Reddit Expanded Community Filter][reddit-expanded-community-filter-userscript]\n\n[best-practices-badge]: https://www.bestpractices.dev/projects/9502/badge\n[best-practices-link]: https://www.bestpractices.dev/projects/9502\n[cicd-badge]: https://github.com/AJGranowski/docker-user-mirror/actions/workflows/cicd.yml/badge.svg?branch=main\n[cicd-link]: https://github.com/AJGranowski/docker-user-mirror/actions/workflows/cicd.yml\n[downloads-badge]: https://img.shields.io/github/downloads/AJGranowski/docker-user-mirror/user-mirror?logo=github\u0026label=Total%20downloads\u0026labelColor=30373d\u0026color=4078c0\n[reddit-expanded-community-filter-userscript]: https://github.com/AJGranowski/reddit-expanded-community-filter-userscript\n[scorecard-badge]: https://api.securityscorecards.dev/projects/github.com/AJGranowski/docker-user-mirror/badge\n[scorecard-link]: https://securityscorecards.dev/viewer/?uri=github.com/AJGranowski/docker-user-mirror\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajgranowski%2Fdocker-user-mirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fajgranowski%2Fdocker-user-mirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fajgranowski%2Fdocker-user-mirror/lists"}