Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How docker handles multiple mount types?

This post is somewhat lenglthy but bear with me for a while...

Suppose you have an app that sits in /app in your local (host) filesystem with the following structure

app
|-- index.php
|-- foo
|   `-- file-h1
`-- bar
    `-- file-h2

Now suppose we have an image (tagged myrepo/app) that exploits the following data structure

opt
|-- app
|   `-- foo
|       `-- file-c1

If we run a container from that image by mounting host's /app to container's /opt/app as follows

docker container run \
-v /app:/opt/app \
myrepo/app

The resulting data structure of the container will be the following

opt
|-- app
|   |-- index.php
|   |-- foo       
|   |   `-- file-h1          
|   `-- bar
|       `-- file-h2 

So far, so good...

Running container with multiple mounts (both bind-mounts and volumes)

Now, lets say that we want to use both a named volume called data to be mounted on /opt/app/foo and a bind-mount for mounting /app to /opt/app

docker container run \
-v /app:/opt/app \
-v data:/opt/app/foo
myrepo/app

The resulting data structure inside the container will be:

opt
|-- app
|   |-- index.php
|   |-- foo       
|   |   `-- file-c1          
|   `-- bar
|       `-- file-h2 

As it is stated in various posts (like this and this) the docker mounts are performed in lexicographic order (i.e shortest path first). According to this, I would expect docker first to execute the bind-mount ( -v /app:/opt/app) and then the volume (-v data:/opt/app/foo).

Hence, I would expect that the contents of host's /app would replace/obscure the contents of container's /opt/app and thus file-h1 to be inside /opt/app/foo. Finally, file-h1 would be copied in the newly created data volume and the volume would be mounted on /opt/app/foo (so file-h1 should be shown instead of file-c1 )

My questions raised when I tried to understand this answer on SO

like image 331
ira Avatar asked Dec 13 '17 14:12

ira


People also ask

What are the two types of mounts in Docker?

Basically, there are 3 types of mounts which you can use in your Docker container viz. Volumes, Bind mount and tmpfs mounts.

Can multiple Docker containers mount same volume?

Multiple containers can run with the same volume when they need access to shared data. Docker creates a local volume by default.

How does Docker bind mount work?

Bind mounts When you use a bind mount, a file or directory on the host machine is mounted into a container. The file or directory is referenced by its full path on the host machine. The file or directory does not need to exist on the Docker host already. It is created on demand if it does not yet exist.

What are two differences between a Docker volume and a bind mount?

The most notable difference between the two options is that --mount is more verbose and explicit, whereas -v is more of a shorthand for --mount . It combines all the options you pass to --mount into one field. On the surface, both commands create a PostgreSQL container and set a volume to persist data.


1 Answers

Finally, and with a lot of help by github user cpuguy83, I figured out what actually docker engine does when we try to run a container that uses multiple mounts of different type (e.g both a bind-mount and a volume) as, for instance:

docker container run \
-v /app:/opt/app \
-v data:/opt/app/foo
myrepo/app

The key point to understand here is that docker executes the process in two steps that are done in the following order:

  1. First, it creates a new storage-space (i.e. volume) in the host filesystem (... data/) for the container to persist files and then (since that newly created volume is empty) it copies the container's files (i.e whatever is inside /opt/app/foo/*) to the volume's storage location (... data/)

  2. Then after that, it performs all mounts (binds, volumes, tmpfs mounts, etc... are all lumped together) in lexicographic order (first mounts /app to /opt/app then ... data/ to /opt/app/foo)

So, because of that, when we run the container with the mounts in our example, the docker first will copy the file-c1 to the ... data/ location in the host filesystem and second it will mount first the contents of host's /app to the container's /opt/app and then the host's ... data/ (which contains file-c1) to container's /opt/app/foo overwriting/obscuring its contents (i.e overwriting file-h1 with file-c1). Therefore, if we take a look inside the running container after the mounts are done, the result will be the following:

opt
|-- app
|   |-- index.php
|   |-- foo       
|   |   `-- file-c1          
|   `-- bar
|       `-- file-h2
like image 146
ira Avatar answered Sep 20 '22 11:09

ira