自Docker早期以来bind mounts 一直存在。与volumes相比,绑定挂载具备有限的功能。使用bind mounts时,主机上的文件或目录将装入容器中。文件或目录由其在主机上的完整路径或相对路径引用。相反,当您使用卷时,会在主机上的Docker存储目录中建立一个新目录,Docker会管理该目录的内容。linux
该文件或目录不须要已存在于Docker主机上。若是它尚不存在,则按需建立。绑定挂载很是高效,但它们依赖于具备特定目录结构的主机文件系统。若是您正在开发新的Docker应用程序,请考虑使用命名卷。您没法使用Docker CLI命令直接管理bind mounts。nginx
最初,-v
或者--volume
标志用于独立容器,--mount
标志用于群集服务。可是,从Docker 17.06开始,您还可使用--mount
独立容器。通常来讲, --mount
更明确和冗长。最大的区别在于-v
语法将全部选项组合在一个字段中,而--mount
语法将它们分开。如下是每一个标志的语法比较。docker
具体的用法 和 差别请参看上一节以介绍。
app
考虑具备一个source目录的状况,并在构建源代码时将构建的代码保存到另外一个目录source/target/
中,您但愿这个构建代码可用于容器/app/
,测试
而且您但愿容器在每次构建源时都能访问新构建在开发主机上。使用如下命令将target/
目录绑定到容器中/app/
。从source
目录中运行命令 。spa
该$(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
部分:3d
这代表mount是一个bind
mount,它显示了正确的源和目标,它代表mount是读写的,而且传播设置为rprivate
。code
中止容器删除容器:blog
$ 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
对于某些开发应用程序,容器须要写入绑定装入,所以更改会传播回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:latestecb63dfecfdb2602ee32c6e6a34930f86501a052a58fe0da8aacad1f31ecfdeb[root@benjamincloud ~]# docker run -itd --name devtest2 -v "$(pwd)"/target:/app:z nginx:latest3427fa5a5ff671454a64186d2cb8fda0553e6c7e912559d43265dd8724cbc2db[root@benjamincloud ~]# docker run -itd --name devtest3 -v "$(pwd)"/target:/app:z nginx:latest 78abe5d52173bc7cc327983cbb9dac5bdc9bc3cb164fa4fb6940215299191be5