Docker Community Forums

Share and learn in the Docker community.

Create local volume with custom mount options

I would like to create a volume in my docker-compose.yml file with custom mount options (uid set to the host user).

  my_volume:
    driver: local
    driver_opts:
      #type: ""
      #device: ""
      o: "uid=${UID:-1000}"

However, I have no clue what to use for type and device. The only documentation I could find on the topic uses either tmpfs or nfs, but I just want a local volume and it should not get deleted together with the container.

Where can I find documentation on these options or what should I use in this case? Thank you.

If you just need to mount a directory with its own content, you can use a simple bind mount after you set the owner manually:

services:
  yourservice:
    volumes:
      - ./path/to/your/host/dir:/path/inside/the/container
sudo chown -R 1000 ./path/to/your/dir
docker-compose up -d

If you want the content inside the container to be copied back to your host, you can do what you statrted to do except I don’t know a way to set the UID as you tried, But I think you don’t have to, since you can change the owner of the folder inside the Docker image so when you mount the volume, it will change the owner on the host.

volumes:
  my_volume:
    driver: local
    driver_opts:
      type: none
      device: "/path/to/your/host/dir"
      o: bind

I actually learned this way here on the forum not long ago.

Relevant part of the Dockerfile:

FROM yourbaseimage

RUN chown -R 1000 /path/inside/the/container

If you want it to work with any ID, you can you can set the ID as an argument:

FROM yourbaseimage
ARG content_owner=1000
RUN chown -R  $content_owner /path/inside/the/container

build args in docker-compose.yml

services:
  yourservice:
    build:
      context: .
      args:
        content_owner: 1000

You could even use an environment variable instead of 1000

Bind mount is mentioned in the docs but I haven’t met that “named bind mount” version either. That could be my fault or the fault of the documentation. I don’t know.

1 Like

To add some further notes:

A named volume baked by a bind can not mount the filesystem with a different user id, like it possible with a remote share. I am afraid the container process uid/gid will be used to access the local filesystem.

If you desperatly want it, then a feasable workound could be to expose the folder(s) using nfs, and then do what you want with a nfs baked volume.

1 Like

Thank you both! That makes sense.

Creating an empty folder and setting the owner correctly before mounting the volume into the container worked.

But I think you don’t have to, since you can change the owner of the folder inside the Docker image so when you mount the volume, it will change the owner on the host.

This did not work for me. The volume gets mounted when the container starts, not when the image gets built. So in order to change the permissions I would have to create a script specifically to set the permissions of the volume, switch user and then run my app.

Changing the permissions of the empty folder the volume gets mounted into doesn’t have any effect.

To conclude:

  • binding a host directory with either the volume syntax or the driver options creates the directory with root owner on the host (if it doesn’t exist)
  • to avoid having to change the owner to use the volume with a non-root user inside the container, one has to manually create the host directory and set the correct permissions

That’s true but the permissions on the host folder will be set when you start the container. It doesn’t work with the usual bind mount, yes. But it works with the named bind mount when it is initialized. At least with Docker 20.10.10 which almost the latest version but I don’t think that matters. Maybe you misunderstand me so I give you an example to try:

Run on the host

mkdir $HOME/volumes/test

Dockerfile

FROM ubuntu:20.04
RUN mkdir /app && chown -R 33:33 /app

Note: I intentionally used 33 for UID and GID to make the change more noticable

docker-compose.yml

version: "3.7"

volumes:
  test:
    driver: local
    driver_opts:
      type: none
      device: "$HOME/volumes/test"
      o: bind

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - test:/app

Start the project:

docker-compose up -d --build

Check the permissions:

ls -la $HOME/volumes/test