docker从零开始 存储(三)bind mounts
使用bind mounts
自Docker早期以来bind mounts 一直存在。与volumes相比,绑定挂载具有有限的功能。使用bind mounts时,主机上的文件或目录将装入容器中。文件或目录由其在主机上的完整路径或相对路径引用。相反,当您使用卷时,会在主机上的Docker存储目录中创建一个新目录,Docker会管理该目录的内容。
该文件或目录不需要已存在于Docker主机上。如果它尚不存在,则按需创建。绑定挂载非常高效,但它们依赖于具有特定目录结构的主机文件系统。如果您正在开发新的Docker应用程序,请考虑使用命名卷。您无法使用Docker CLI命令直接管理bind mounts。
选择-v或--mount标志
最初,-v
或者--volume
标志用于独立容器,--mount
标志用于群集服务。但是,从Docker 17.06开始,您还可以使用--mount
独立容器。一般来说, --mount
更明确和冗长。最大的区别在于-v
语法将所有选项组合在一个字段中,而--mount
语法将它们分开。以下是每个标志的语法比较。
具体的用法 和 差异请参看上一节以介绍。
使用绑定装载启动容器
考虑具有一个source目录的情况,并在构建源代码时将构建的代码保存到另一个目录source/target/
中,您希望这个构建代码可用于容器/app/
,
并且您希望容器在每次构建源时都能访问新构建在开发主机上。使用以下命令将target/
目录绑定到容器中/app/
。从source
目录中运行命令 。
该$(pwd)
子命令将扩展到Linux或者MacOS主机的当前工作目录。
[root@benjamincloud ~]# mkdir target [root@benjamincloud ~]# docker run -tid --name devtest --mount type=bind,source="$(pwd)"/target,target=/app nginx:latest bc8d4cb8bdc26bc77ddc64aa810f7868a13e1019072767a024d8f14b2e4f0a8a
使用docker inspect devtest
验证绑定安装正确创建。寻找Mounts
部分:
这表明mount是一个bind
mount,它显示了正确的源和目标,它表明mount是读写的,并且传播设置为rprivate
。
停止容器删除容器:
$ docker container stop devtest $ docker container rm devtest
挂载到容器上的非空目录中
如果将bind-mount绑定到容器上的非空目录中,则bind mounts 会隐藏目录的现有内容。这可能是有益的,例如当您想要测试新版本的应用程序而不构建新镜像时。当然,它也可能令人惊讶,并且此行为与docker volume行为不同。
此示例设计极端,但将容器/usr/
目录的内容替换为主机上的目录/tmp/。在大多数情况下,这会导致容器无法运行。
这些--mount
和-v
示例具有相同的最终结果。
[root@benjamincloud ~]# docker run -dit --name broken-container --mount type=bind,source=/tmp,target=/usr nginx:latest afe70a7698112b93f0d5f200611b80dfe6c4f9e05ad1e8134183975d14428866 docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"nginx\": executable file not found in $PATH": unknown.
容器已创建但无法启动。去掉它:
$ docker container rm broken-container
使用只读bind mounts
对于某些开发应用程序,容器需要写入绑定装入,因此更改会传播回Docker主机。在其他时候,容器只需要读访问权限。
此示例修改上面的示例,但ro
通过在容器中的挂载点之后添加(默认情况下为空)选项列表,将目录挂载为只读绑定挂载。如果存在多个选项,请用逗号分隔。
[root@benjamincloud ~]# docker run -dit --name devtest --mount type=bind,source="$(pwd)"/target,target=/app,readonly nginx:latest c77da99626fd7c8389cc09aee405951f3bd0837a7a78de9d1eb667da2a24cf5f
使用docker inspect devtest
验证绑定安装正确创建。寻找Mounts
部分:
配置绑定传播
绑定传播默认rprivate
为bind mounts和volume。这里只配置 mount binds,并且仅适用于Linux主机。绑定传播是一个高级主题,许多用户永远不需要配置它。
绑定传播是指在给定的bind mounts或命名volume中创建的挂载是否可以传播到该装载的副本。考虑一个挂载点/mnt
,挂载在/tmp
。
传播设置控制是否/tmp/a
也可以使用挂载/mnt/a
。每个传播设置都有一个递归对位。在递归的情况下,请考虑将/tmp/a被
/foo挂载
。传播设置控制/mnt/a
和/或/tmp/a是否
将存在。
传播设置 | 描述 |
---|---|
shared |
原始挂载的子挂载将暴露给副本挂载,副挂载的副挂载也会传播到原始挂载。 |
slave |
类似于共享挂载,但只在一个方向上。如果原始挂载程序公开子挂载,则副本挂载程序可以看到它。但是,如果副本挂载公开子挂载,则原始挂载无法看到它。 |
private |
挂载是私人的。其中的子挂载不会暴露给副本挂载,而子挂载中的副本挂载不会暴露给原始挂载。 |
rshared |
与共享相同,但传播也扩展到嵌套在任何原始挂载点或副本中的挂载点。 |
rslave |
与从属相同,但传播也延伸到嵌套在任何原始挂载点或副本挂载点。 |
rprivate |
默认值。与private相同,意味着原始或副本挂载点中任何位置的挂载点都不会沿任一方向传播。 |
在你挂载点设置绑定传播之前,主机文件系统需要已经支持绑定传播。
有关绑定传播的更多信息,请参阅共享子树的 Linux内核文档。
以下示例将target/
目录挂载到容器两次,第二个挂载同时设置ro
选项和rslave
绑定传播选项。
这些--mount
和-v
示例具有相同的结果。
[root@benjamincloud ~]# docker run -dit --name devtest --mount type=bind,source="$(pwd)"/target,target=/app --mount type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave nginx:latest
现在,如果你创建/app/foo/
,/app2/foo/
也存在
[root@benjamincloud ~]# mkdir target/foo [root@benjamincloud ~]# docker exec devtest ls /app2/ foo [root@benjamincloud ~]# docker exec devtest ls /app/ foo
果使用selinux
,可以添加z
或Z
选项以修改要装入容器的主机文件或目录的selinux标签。这会影响主机本身上的文件或目录,并且可能会产生Docker范围之外的后果。
- 该
z
选项表示绑定装载内容在多个容器之间共享。 - 该
Z
选项表示绑定装载内容是私有且非共享的。
使用极端谨慎使用这些选项。绑定安装系统目录(例如/home
或/usr
使用该Z
选项)会导致主机无法运行,您可能需要手动重新标记主机文件。
重要提示:将bind mounts与服务一起使用时,selinux标签(:Z
和:z
)以及将:ro
被忽略。
此示例设置z
选项以指定多个容器可以共享绑定装载的内容:
无法使用--mount
标志修改selinux标签。
[root@benjamincloud ~]# docker run -itd --name devtest -v "$(pwd)"/target:/app:z nginx:latest
ecb63dfecfdb2602ee32c6e6a34930f86501a052a58fe0da8aacad1f31ecfdeb
[root@benjamincloud ~]# docker run -itd --name devtest2 -v "$(pwd)"/target:/app:z nginx:latest
3427fa5a5ff671454a64186d2cb8fda0553e6c7e912559d43265dd8724cbc2db
[root@benjamincloud ~]# docker run -itd --name devtest3 -v "$(pwd)"/target:/app:z nginx:latest
78abe5d52173bc7cc327983cbb9dac5bdc9bc3cb164fa4fb6940215299191be5