Docker volume default "device" of local driver?

Hi,

when I create a volume (docker volume create test) and inspect it, it has an “Options” field of “null”. Which actual (default) options are used there? With other words, is there an equivalent “verbose” commandline like so:

docker volume create --driver local \
    --opt type=??? \
    --opt o=??? \
    --opt device=??? \
    test

I’d like to know, which type/device-specific options there are, to create a volume as similar as possible to the default.
Thanks,
Jeff

Go to " How mounting block devices works".

I quote

Under the hood, the --mount flag using the local storage driver invokes the Linux mount syscall and forwards the options you pass to it unaltered. Docker doesn’t implement any additional functionality on top of the native mount features supported by the Linux kernel.

If you’re familiar with the Linux mount command, you can think of the --mount options as forwarded to the mount command in the following manner:

If you want to know the default options you can run the following command:

docker run --rm -it -v $VOLUME_NAME:/volumetest  bash mount | grep volumetest

Replace $VOLUME_NAME with the name of your test volume.
My output is:

/dev/sda1 on /volumetest type ext4 (rw,relatime,discard,errors=remount-ro)

Actually, I would expect the options to be the ones from the mount on the host, as the “volume” will be ultimately bind mounted from a host folder in /var/lib/docker/volumes/${volume name}/_data to a target folder inside the container.

After all isn’t a bind mount just mounting a folder from the file system to another folder of the file system? It doesn’t make sense if a bind actually allows any options at all.

I am glad you mentioned that, because it is an interesting point.Yes, when I think of a volume my first thought is that the system would mount the /var/lib/docker/${volume_name}/_data folder to the containers filesystem which would be used as root for the container, but this is not exactly what is happening.

If you check the container’s “merged” dir, you will see it empty

sudo ls -la $(docker inspect test --format '{{ .GraphDriver.Data.MergedDir }}')/volumetest

The content is mounted only inside the container’s mount namespace. I don’t exactly know how, but I will find out some day.

You can for example make a folder read-only.

mkdir "./testmount"
sudo mount --bind -o ro "$PWD" "./testmount/"

It could be useful sometimes (to be honest I have never actually needed it) for example if you have a script that needs an otherwise writable folder but you don’t want the script to be able to write it if you are not sure whether it would change files or not. So you can bind mount it as read only and work on that folder.

For a named volume with parameters, the volume parameters control the mount from the source into /var/lib/docker/${volume_name}/_data. A named volume without parameters on the other hand mounts nothing, the data directly “lives” in that folder.

The volume does not control the final bind mount from `/var/lib/docker/${volume_name}/_data to the container path.

Of course one could create a named volume and parameterize it to create a bind with option :slight_smile: Though, the OP was about how does the full syntax look like. I’d say there is none, as all variants with parameters actually mount something.

I am sorry everyone if I misunderstood something :slight_smile:

The question in the title is about the “device” in case of a local driver. The following command would show an existing volume’s options:

docker volume inspect test

In case of a simple local volume created without parameters, there is no device. At least not shown in the output. The device would be the first argument of the mount command:

mount <device> <mountpoint>

If we put aside Docker for a moment, a device would be a hard drive for example:

mkdir /mnt/movies
mount /dev/sda1 /mnt/movies

In case of a bind mount, a device is another folder

mkdir /mnt/userhome
mount --bind /home/user /mnt/userhome

If we create a volume without parameters using

docker volume create test

It will create an empty folder at

/var/lib/docker/volumes/test/_data

If I mount it into a non-existent folder inside a container, it remains empty

docker run --rm -it -v test:/app -w /app bash ls -la

If I mount it into an existing folder, the content from the container will be copied to the host

docker run --rm -it -v test:/etc -w /etc bash ls -la
ls -la /var/lib/docker/volumes/test/_data/

Now if I run the mount command instead of “ls”, I can see the mount options and by changing the --opt o= values I can change those values.

I can also use a simple bind mount without creating a volume and let’s not add any extra like “ro”.

docker volume create readwrite --driver local --opt type=none --opt device=$PWD --opt o=bind

Now I run the following commands and get the same result:

docker run --rm -it -v readwrite:/app -w /app bash mount | grep app
# /dev/sda1 on /app type ext4 (rw,relatime,discard,errors=remount-ro)
docker run --rm -it -v $PWD:/app -w /app bash mount | grep app
# /dev/sda1 on /app type ext4 (rw,relatime,discard,errors=remount-ro)

Running the following commands I also get the same content. The content of the folder that $PWD refered to when I created to volume.

docker run --rm -it -v readwrite:/app -w /app bash ls -la
docker run --rm -it -v $PWD:/app -w /app bash ls -la

The difference is that the _data folder is empty. Only a json file is there next to _data

ls -la /var/lib/docker/volumes/readwrite/_data/
# empty folder
cat /var/lib/docker/volumes/readwrite/opts.json
{"MountType":"ext4","MountOpts":"bind","MountDevice":"/home/ubuntu/projects/volumes","Quota":{"Size":0}}

If I want to make the mount readonly, I can

docker volume create readwrite_ro \
  --driver local \
  --opt type=none \
  --opt device=$PWD \
  --opt o=bind,ro

docker run --rm -it -v readwrite_remount:/app -w /app bash mount | grep app
/dev/sda1 on /app type ext4 (ro,relatime,discard,errors=remount-ro)

But you are right, I can’t change other options. I guess because the readonly option is supported using the other syntax as well

docker run --rm -it -v $PWD:/app:ro -w /app bash mount | grep app
# dev/sda1 on /app type ext4 (ro,relatime,discard,errors=remount-ro)

In the original question:

I thought the point was to find out how the volume is mounted using which options. I did not consider whether it can be change or not but I indeed assumed that I could change more parameters. In my first post I did not answer the “device” part either which I completely missed.

In my examples it only mounts when I use it as a volume in a container with or without parameters.

Thank you for your detailed answers!

Of course I had read the docs, and understood in general. But a certain question remains. My final goal was to supply local device options, like this

volumes:
  ipc:
    driver: local
    driver_opts:
      type: tmpfs
      device: tmpfs
      o: size=10m,uid=1000,gid=1000,mode=755

I wanted to do this with default device, not tmpfs. First, because I wasn’t sure what it means to mount as “tmpfs” from the container if it will be restarted (explicitely or after reboot). Second, I’d like to understand any difference.

Thanks again for you detailed answers. I’ll see how I can use it. For the time being I use tmpfs and it seems to work so far.

Thanks

tmpfs is memory, so no, it won’t be available after restarting the container, but it is not mounting 'from" the container but mounting “to” the container from the memory…