1)为什么/etc/{hosts,hostname,resolv.conf}
文件是从外面安装的?
我至少看到一个原因。
想象一下,如果容器引擎只是将这些文件写入容器的文件系统并且用户决定挂载/etc
为卷(这是完全合法且非常有用的 - 安装/etc
将允许用户为容器提供多个配置文件,会发生什么情况一个-v
论点docker run
):
- 首先,卷安装到容器的
/etc
目录; - 然后它的内容由容器引擎改变(写入特定文件
/etc
)。
启动此容器后,用户尝试使用相同的/etc
卷再启动一个(同样,这是完全合法且有用的 - 例如,用户扩展某些服务并/etc
在实例之间共享配置文件),以及......第二个容器覆盖hostname
,hosts
并resolv.conf
在卷上的文件,影响了第一容器。
现在考虑使用bind-mount而不是直接写入时会发生什么:
- 卷已安装到容器的
/etc
目录中; - 容器引擎
/etc/{hosts,hostname,resolv.conf}
从主机上的某个地方绑定到容器的文件系统; - bind-mounts会隐藏卷上这些文件的原始版本(如果有),因此可以保证在容器设置期间不会修改卷上的文件,也不会将其传播到其他容器。
2)为什么我认为/dev/sda1
这些的来源?
检查findmnt(8)
而不是df(1)
:
$ docker run -it ubuntu root@5a8ab4d6e716:/# findmnt TARGET SOURCE ... |-/etc/resolv.conf /dev/sda1[/var/lib/docker/containers/5a8ab4d6e71691f279cbbcf5a295b5fa90fd138f10418c996ad7ea4440452816/resolv.conf] |-/etc/hostname /dev/sda1[/var/lib/docker/containers/5a8ab4d6e71691f279cbbcf5a295b5fa90fd138f10418c996ad7ea4440452816/hostname] `-/etc/hosts /dev/sda1[/var/lib/docker/containers/5a8ab4d6e71691f279cbbcf5a295b5fa90fd138f10418c996ad7ea4440452816/hosts]
实际上,这里的每行输出显示三个字段(安装目标/etc/hosts
,安装源/dev/sda1
和FS根/var/lib/<...>/hosts
),第三个字段未显示df(1)
。
根据man procfs
关于/proc/PID/mountinfo
文件的段落(这是关于实用程序的安装的信息的来源):
(4) root: the pathname of the directory in the filesystem which forms the root of this mount. (5) mount point: the pathname of the mount point relative to the process's root directory. ... (10) mount source: filesystem-specific information or "none".
对于大多数安装,FS root是/
(因为你挂载了整个文件系统),因此在查看df(1)
输出时不会丢失太多信息。但是,对于特定文件的绑定挂载不是这种情况。