Use bind mounts
bind mounts
在 docker 早期版本就已经在使用了。bind mounts
较volumes
而言,会有一些功能限制。- 当使用
bind mounts
时, 宿主机中的已存在的文件或目录
被挂载到容器中。 - 在挂载时,使用
绝对路径
或相对路径
指定所挂载的文件或目录。
$ docker run --rm -v python3:/root/python3/ --name nginx_test -d nginx
bfd85451aa6e96e304341c8c80ac16af64482d793a2b00e866f0bae06ec2e83f
- 与
bind mounts
不同,当创建一个volume
时,会在宿主机的Docker’s storage directory
创建一个新文件夹,并有 docker 管理其内容。
- 容器中的挂载点在不需要预先存在。
- 如果挂载点不存在,则会自动创建。
- 如果挂载点存在且不会空,那么挂载点中的内容将被隐藏。(参考 linux mount)
bind mount
在研发阶段非常有效,但它们依赖于具有特定目录结构的主机的文件系统。- 如果要发布一个 docker 应用,应该使用
命名卷
. - docker CLI 命令不能直接作用于
bind mounts
。
用 -v
还是 --mount
- 最开始,
-v
或--volume
用于standalone
容器, 而--mount
用于swarm services
;但从17.06
开始--mount
也可以用于standalone
容器了。 --mount
可读性更高,意义更明确。-v
将所有参数组合成一个;而--mount
将他们分开
建议: 新人用
--mount
;老鸟可能更熟悉-v / --volume
,但建议使用--mount
-v / --volume
: 有三个部分组成,以 冒号:
分隔。-v local_path:mount_point:flag
- local_path :宿主机文件或目录的
绝对路径或相对路径
。 - mount_point : 容器中的挂载点。
- flag: 可选部分。如果有个多,使用 逗号
,
分隔。例如ro
,consistent
,delegated
,cached
,z
,Z
。
- local_path :宿主机文件或目录的
--mount
: 以多个<key>=<value>
对组成,使用 逗号,
分隔。虽然--mount
比-v
更冗长,但是每个字段意义更明确,而且字段之间没有顺序限制。type
: 挂载类型bind
,volume
,tmpfs
, 此处为bind
。source / src
: 宿主机文件或目录的绝对路径
。destination / dst/ target
: 容器中的挂载点readonly
: 只读挂载bind-propagation
: 如果存在,则修改 bind 的传播方式。可选值为rprivate
,private
,rshared
,shared
,rslave
,slave
。consistency
: 如果存在,可选值为consistent
,delegated
,cached
。该选项仅对Docker for Mac
有效,其他平台将会被忽略。--mount
不支持z
或Z
修改 selinux 标签。
--mount
的 src
不支持相对路径:
$ docker run -d --rm --name nginx_test --mount type=bind,src=python3,dst=/root/python3 nginx
docker: Error response from daemon: invalid mount config for type "bind": invalid mount path: 'python3' mount path must be absolute.
See 'docker run --help'.
$ docker run -d --rm --name nginx_test --mount type=bind,src=/home/python3,dst=/root/python3 nginx
880c35d9d2cfb01db921030451ff2a4f0b6da7baf2b1f5b8ce3fe4da2985ed8e
Differences between -v and --mount behavior
Because the -v
and --volume
flags have been a part of Docker for a long time, their behavior cannot be changed. This means that there is one behavior that is different between -v
and --mount
.
- 使用
-v / --volume
挂载时,如果source
不存在,docker 会在指定路径创建一个目录
作为source
。 - 使用
--mount
挂载是,如果source
不存在,docker 不会创建任何东西,并报错。
Start a container with a bind mount
--mount
:
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app \
nginx:latest
-v
:
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app \
nginx:latest
使用命令 docker container inspect devtest
验证挂载是否正确,并查看 Mounts
部分:
"Mounts": [
{
"Type": "bind",
"Source": "/tmp/source/target",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
结果显示, 挂载方式为 bind
, source
和 Destination
位置正确,挂载方式为 read-write
, 传播方式为 rprivate
。
关闭容器:
$ docker container stop devtest
$ docker container rm devtest
Mounting into a non-empty directory on the container
使用 bind mounts
挂载本地目录到容器中的一个非空目录时, 容器中的目录内容将会被隐藏。
这个非常适合用于研发阶段,经常变动。
下例非常极端,把宿主机的中的 /tmp
目录挂载到了容器中的 /usr
目录。
--mount
:
$ docker run -d \
-it \
--name broken-container \
--mount type=bind,source=/tmp,target=/usr \
nginx:latest
docker: Error response from daemon: oci runtime error: container_linux.go:262:
starting container process caused "exec: \"nginx\": executable file not found in $PATH".
-v
:
$ docker run -d \
-it \
--name broken-container \
-v /tmp:/usr \
nginx:latest
docker: Error response from daemon: oci runtime error: container_linux.go:262:
starting container process caused "exec: \"nginx\": executable file not found in $PATH".
上例中,容器创建了,但是没有被启动。使用命令删除
$ docker container rm broken-container
Use a read-only bind mount
当需要被挂在的目录为 只读
时:
-v
:ro
--mount
:readonly
--mount
:
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app,readonly \
nginx:latest
-v
:
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app:ro \
nginx:latest
使用命令 docker container inspect devtest
查看容器信息,并查看 Mounts
部分
"Mounts": [
{
"Type": "bind",
"Source": "/tmp/source/target",
"Destination": "/app",
"Mode": "ro",
"RW": false,
"Propagation": "rprivate"
}
],
关闭容器
$ docker container stop devtest
$ docker container rm devtest
Configure bind propagation
- 在
bind mount
和volumes
中,Bind propagation
默认为rprivate
。 - 只有
linux
上能为bind mounts
配置bind-propagation
的值。 bind propagation
是一个高阶功能,大部分人不会配置到这部分。
更多信息,直接看官方文档 https://docs.docker.com/engine/admin/volumes/bind-mounts/#configure-bind-propagation
Configure the selinux label
如果使用 selinux
, 你可以使用 z
或 Z
来修改 mount 到容器中的主机文件或目录的 selinux 标签。并且可能会在 Docker 的范围之外产生后果。
z
:bind mount
的内容可以在多个容器之间共享Z
:bind mount
的内容是私有的
,不能被共享。
在 极端情况下,如果挂载宿主机的 /home
或 /usr/
到容器中,并使用了 Z
, 那么会导致宿主机无法操作,且你需要手动 relabel
这些宿主机文件。
z
或Z
不能搭配--mount
使用
This example sets the z
option to specify that multiple containers can share the bind mount’s contents:
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app:z \
nginx:latest
Configure mount consistency for macOS
只作用于 MacOS ,自己看官网 https://docs.docker.com/engine/admin/volumes/bind-mounts/#configure-mount-consistency-for-macos