Overlapping bind mounts on a linux host seems to create ghost files on the host machine owned by root
. Is this intended? Here's an example:
# Create a file to mount in the container
touch hostfile
# Create a temporary directory to mount in the container
mkdir tempdir
# Run bash in the container and mount the file and directory
docker run --rm --volume=`pwd`/tempdir:/home --volume=`pwd`/hostfile:/home/hostfile ubuntu bash
After running the command, the hostfile
can be found in the tempdir
but is owned by root
.
Note that
hostfile
being owned by the user who started the container,docker run
call does not change anything.Bind mounts have been around since the early days of Docker. Bind mounts have limited functionality compared to volumes. 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 absolute path on the host machine.
Bind mounts in Linux® enable you to mount an already-mounted file system to another location within the file system. Generally, bind mounts are used when restricting the access of specified users to designated parts of a website by replicating the website's directory into a jailed user's home directory.
If you bind mount in a volume - you can simply back up that directory (which is jenkins_home) at any time. This is highly recommended. Treat the jenkins_home directory as you would a database - in Docker you would generally put a database on a volume.
Good use cases for bind mounts Bind mounts are appropriate for the following types of use case: Sharing configuration files from the host machine to containers. This is how Docker provides DNS resolution to containers by default, by mounting /etc/resolv. conf from the host machine into each container.
This behavior is the intended one. Let's try to understand what happens and perform the same mounts manually.
We create the hostfile
, the "host" directory and the target "container" directory at some location (say, it is /home/qazer/dockx
on my machine):
# the host file
$ touch hostfile
# the "host"-side dir
$ mkdir hostdir
# the "container"-side dir
$ mkdir contdir
Then we perform the mounts:
# the first mount: "host" dir to "container" dir
$ sudo mount --bind hostdir contdir
# success!
# the second mount: host file to the container file
$ sudo mount --bind hostfile contdir/hostfile
mount: contdir/hostfile: mount point does not exist.
Yay, the bind mount failed because the target file does not exist! Consulting the manpage for mount(2)
system call reveals that this call would fail if some of the paths provided points to nonexistent file:
ENOENT A pathname was empty or had a nonexistent component.
So, what Docker actually does is the following:
$ sudo strace -f -p $(pidof containerd) \
-e trace=%file,mount -yy |& grep -e hostfile -e home
...
[pid 23945] newfstatat(AT_FDCWD, "/var/lib/docker/overlay2/b2c32423952d49f21e7a9c1addec6201c7f036c8dba1da975bac6a34d5abbe11/merged/home/hostfile", 0xc00016ce08, 0) = -1 ENOENT (No such file or directory)
...
[pid 23945] openat(AT_FDCWD, "/var/lib/docker/overlay2/b2c32423952d49f21e7a9c1addec6201c7f036c8dba1da975bac6a34d5abbe11/merged/home/hostfile", O_RDONLY|O_CREAT|O_CLOEXEC, 0755) = 7</var/lib/docker/overlay2/b2c32423952d49f21e7a9c1addec6201c7f036c8dba1da975bac6a34d5abbe11/merged/home/hostfile>
[pid 23945] mount("/home/qazer/dockx/hostfile", "/var/lib/docker/overlay2/b2c32423952d49f21e7a9c1addec6201c7f036c8dba1da975bac6a34d5abbe11/merged/home/hostfile", 0xc00013bb00, MS_BIND|MS_REC, NULL) = 0
First, the existence of the /home/hostfile
file is checked in the container file system (the newfstat()
call). This file is not present (ENOENT
), so Docker creates it to avoid the error we've seen before (the openat(O_CREAT)
call), and only after this the container engine performs the actual bind mount of hostfile
to the container file system (the mount()
call).
At the time of writing, the /home
directory is already bind-mounted from the host (the first mount), so this write goes to this host directory. Finally, when the container stops, the file written by Docker stays in the host directory, and this is what you see.
As to the file ownership in case of Mac OS host — I think that the reason is the same as in this your question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With