Docker卷挂载0个大小的文件

时间:2019-11-26 10:11:50

标签: docker

我正在运行一个Docker容器,其卷已安装到/etc

我使用以下命令创建容器:

$ docker container run -dt -v volume01:/etc alpine sh
81cf19f2c9ea23d79b900fe8f195fd333df376627710aa78f38f35cf565bfaf0

现在我看到卷目录中的某些文件的大小为0,例如/etc/hosts文件:

# ls -ltrh /var/lib/docker/volumes/volume01/_data/hosts
-rwxr-xr-x 1 root root 0 26 nov 10:42 /var/lib/docker/volumes/volume01/_data/hosts

此文件实际上不是空的,如果我检查容器中/etc/hosts的大小,则它不是0:

$ docker exec -ti 81cf19f2c9ea ls -lt /etc/hosts
-rw-r--r--    1 root     root           174 Nov 26 09:42 /etc/hosts

知道为什么会这样吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

您观察到的效果非常有趣。为了说明这一点,让我们看一些事实。

第一:Docker以一种非常特殊的方式处理了很少的文件(/etc/hosts/etc/hostname/etc/resolv.conf),因为它们包含与网络相关的设置对于不同的容器应该有所不同。

Docker为每个容器生成这些文件,并将它们保存在主机系统上。容器的文件系统具有以下文件的绑定挂载:

$ docker run alpine /bin/sh -c 'mount | grep etc'
/dev/sda1 on /etc/resolv.conf type ext4 (rw,relatime)
/dev/sda1 on /etc/hostname type ext4 (rw,relatime)
/dev/sda1 on /etc/hosts type ext4 (rw,relatime)

第二:在执行绑定挂载之前,Docker必须确保它们的目标存在(因为内核要求挂载点在挂载时存在)。这种东西在所谓的 init层中进行配置,这是一个只读层,它安装在图像文件系统的顶部并包含所需的文件。实际上,Docker只是删除了文件的原始版本(如果有),并在其位置创建了empty stubs

要对此进行检查,请尝试运行特权容器和umount(8)这些特殊文件中的任何一个:

$ docker run -it --privileged alpine

/ # cd /etc

/etc # ls -li hosts
3156636 -rw-r--r--    1 root     root           174 Nov 27 09:37 hosts

/etc # umount hosts

/etc # ls -li hosts
3156653 -rwxr-xr-x    1 root     root             0 Nov 27 09:37 hosts

第三alpine图像本身具有这些文件,但是它们的内容是中性默认值:

$ docker save alpine | tar xO 51667c1dd92cb4d851a7d6413545f5883b758f87251387e70ba531a4562e389f/layer.tar | tar xO etc/hosts
127.0.0.1 localhost localhost.localdomain
::1   localhost localhost.localdomain

因此,映像文件系统包含这些文件的一个(默认)版本,容器文件系统的最高RO层(映像文件系统+ init层)具有这些文件的第二(空)版本,并且正在运行的容器的文件系统(图像文件系统+初始化层+ RW层+所有安装)具有这些文件的第三版。

现在,这些东西与音量有什么关系?

在创建和使用非绑定卷时,Docker使用位于容器中卷挂载点的文件填充卷_data目录,即在您的示例中,运行时

docker container run -dt -v volume01:/etc alpine sh

Docker将容器的/etc复制到/var/lib/docker/volumes/volume01/_data

问题是:上面讨论的特殊文件的哪个版本被复制?答案是:来自初始化层的存根,因为复制是从最顶层的容器创建之后执行的,而不是在运行时中执行的(安装了这些文件的“实际”版本时)。

因此,您在卷中观察到大小为零的/etc/hosts/etc/hostname/etc/resolv.conf,尽管在运行时它们被这些文件的Docker管理版本的绑定挂载隐藏