Losing files when creating volume of parent directory of exposed volume as bind mount

Hello all,

I realize that I’m probably trying to do something inane here, but bear with me as I don’t understand this behavior, and I hope I’m missing something obvious. I didn’t want to submit a bug report until I understand what’s going on here.

First of all, I’m using the kanboard image. As you can see in that Dockerfile, it mounts a volume /etc/nginx/ssl. I would like to actually mount its parent directory /etc/nginx. I am able to do this successfully if I mount it in /var/lib/docker/volumes as a regular named volume:

$ docker run -d -v "nginx:/etc/nginx" kanboard/kanboard

# Look at the mounts
$ docker inspect youthful_vaughan | grep Mounts -A 41
        "Mounts": [
            {
                "Type": "volume",
                "Name": "0cf0a492a0a9bc75edbbfa8d684fac7d35b784e4cc31f121729b4b024c79be58",
                "Source": "/var/lib/docker/volumes/0cf0a492a0a9bc75edbbfa8d684fac7d35b784e4cc31f121729b4b024c79be58/_data",
                "Destination": "/var/www/app/plugins",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "7c8938d0c9aa37193115089da2df346a5ff5f71e149fb28103fbc0234fa233ec",
                "Source": "/var/lib/docker/volumes/7c8938d0c9aa37193115089da2df346a5ff5f71e149fb28103fbc0234fa233ec/_data",
                "Destination": "/etc/nginx/ssl",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "3aa579316b0c841b8f6a71107a9e0037923bc6b22177d926216c7778cf85fd3f",
                "Source": "/var/lib/docker/volumes/3aa579316b0c841b8f6a71107a9e0037923bc6b22177d926216c7778cf85fd3f/_data",
                "Destination": "/var/www/app/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "nginx",
                "Source": "/var/lib/docker/volumes/nginx/_data",
                "Destination": "/etc/nginx",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

# See the files in the directory on the host
$ ls /var/lib/docker/volumes/nginx/_data
conf.d  fastcgi.conf  fastcgi_params  mime.types  modules  nginx.conf  scgi_params  ssl  uwsgi_params

# See the files in the running container
$ docker exec -it youthful_vaughan ls /etc/nginx
conf.d          mime.types      scgi_params
fastcgi.conf    modules         ssl
fastcgi_params  nginx.conf      uwsgi_params

However, when I try to mount that file at another location, those files are absent in that mount and they are absent inside of the container itself:

$ docker run -d -v "/mnt:/etc/nginx" kanboard/kanboard

# Look at the volumes - we can see that it is now a bind mount instead of a regular volume
$ docker inspect pensive_dubinsky | grep Mounts -A 39
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/mnt",
                "Destination": "/etc/nginx",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "3b357047384d6947be1852e93a4576b8d19c49534693b18d0567437fbf8ce3d2",
                "Source": "/var/lib/docker/volumes/3b357047384d6947be1852e93a4576b8d19c49534693b18d0567437fbf8ce3d2/_data",
                "Destination": "/etc/nginx/ssl",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "16ab0b8aa3656f3143901135a0a30fdd97e156dd5cf13d0c3bde77cfafe2f605",
                "Source": "/var/lib/docker/volumes/16ab0b8aa3656f3143901135a0a30fdd97e156dd5cf13d0c3bde77cfafe2f605/_data",
                "Destination": "/var/www/app/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "2c4c6b40185ebbc0543f412f6f35934d37f765367bbc1a1d3b55e6c9f5ccaaaf",
                "Source": "/var/lib/docker/volumes/2c4c6b40185ebbc0543f412f6f35934d37f765367bbc1a1d3b55e6c9f5ccaaaf/_data",
                "Destination": "/var/www/app/plugins",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

# Take a look at the files on the server
$ ls /mnt
ssl

# Take a look at the files inside of the container
docker exec -it pensive_dubinsky ls /etc/nginx
ssl

So when I am running the mount as a bind mount outside of the normal volumes directory, the inheritance doesn’t work for some reason. Or should I say when I am running the mount as a volume inside of the normal volumes directory, for some reason the inheritance works.

Seeing as doing this is probably not the expected utilization in the first place, is there some reason why doing this in the volumes directory is bad? Or on the flip side, should bind mounts outside of that volumes directory get that inheritance as well?

Regards,

Basicly, you are asking why the behavior is different for named volumes and binds :slight_smile:

Here we go:
– named volume: copies files of the target folder into the named volume.
– bind: replace the target folder (its previous content becomes invisible!) with the source folder

Thus said: you can not expect to replace folders with required files in them, with an empty folder and expect it to still work.

So that makes sense except for one thing, why would the named volume exist in the bind mount?

Does it get populated after the bind volumes are created?

I think I am not able to follow you.

Every path declared as a VOLUME in the Dockerfile of the image will end up as a volume on your host when you create a container from it. If you don’t map a bind/named volume, it will be an anonymous named volume. There is no way arround it.

Please use snippets of your docker inspect output to describe what your observation is. Hint: your first example is a named volume, your second is a bind.

Thanks for your answer, I find out what is the problem, but I didn’t find the solution here!