Reputation: 741
Here's a minimal docker-compose.yml
:
version: "3.6"
services:
foo:
user: "${UID}:${GID}"
image: node:latest
container_name: foo
working_dir: /var/www/foo
volumes:
- bar:/var/www/foo/bar
volumes:
bar:
After running docker-compose up
the named volume is created at /var/lib/docker/volumes/project_bar
, and the project_bar
directory is owned by root
- this is fine. Although the _data
directory inside it is also own by root
- I would like it to be own by a specific, non-root user.
For example:
docker-compose run --rm foo sh -c "mkdir bar/foo"
will fail with mkdir: cannot create directory 'bar/foo': Permission denied
.
I was under the impression that specifying user: "${UID}:${GID}"
(note: uid
/gid
are available to docker
, exported in shell they are) will solve this. Obviously, I was wrong.
Is there a way to have /var/lib/docker/volumes/project_bar/_data
being own by specific user? Without chown
'ing anything if possible. And without involving Dockerfile
.
EDIT: To clarify, I would like /var/www/foo/bar
in the container and its equivalent in /var/lib/docker/volumes
to be owned by a specific, not root user.
Upvotes: 2
Views: 1902
Reputation: 263637
You are either involving the Dockerfile, or you need to setup the volume with a separate process. The named volume will be initialized with the contents of the image, including files, directories, owners, and permissions. This happens when the volume is empty or non-existent.
So your options include:
Expanding on the second option, you can create a volume with the desired ownership and content by running a temporary container to do the task:
docker container run --rm -v bar-data:/data busybox /bin/sh -c \
"touch /data/.initialized && chown -R ${UID}:${GID} /data"
Then in your compose file you can declare that volume as external:
version: "3.6"
services:
foo:
user: "${UID}:${GID}"
image: node:latest
container_name: foo
working_dir: /var/www/foo
volumes:
- bar:/var/www/foo/bar
volumes:
bar:
# tell compose this volume is externally created with a different name
external: true
name: bar-data
That will create a volume with a single file, needed to prevent docker from reinitializing an empty volume from the image contents. This also means you need to load any data you want in the volume since it will be otherwise empty. A common method to copy data into a volume involves using tar:
tar -cC source_dir . | \
docker run --rm -i -v foo-data:/target busybox tar -xC /target
Upvotes: 5