绑定坐骑
自 Docker 早期以来,绑定挂载就已经存在。与卷相比,绑定安装的功能有限 。使用绑定挂载时,主机上的文件或目录将挂载到容器中。文件或目录通过其在主机上的绝对路径引用。相比之下,当您使用卷时,会在主机上的 Docker 存储目录中创建一个新目录,并且 Docker 管理该目录的内容。
该文件或目录不需要已存在于 Docker 主机上。如果尚不存在,则会根据需要创建它。绑定挂载的性能非常好,但它们依赖于具有可用的特定目录结构的主机文件系统。如果您正在开发新的 Docker 应用程序,请考虑使用 命名卷。您无法使用 Docker CLI 命令直接管理绑定安装。


提示
使用大型存储库或单一存储库,或者使用不再随代码库扩展的虚拟文件系统?查看 同步文件共享。它通过使用同步文件系统缓存增强绑定安装性能,从而提供快速、灵活的主机到虚拟机文件共享。
选择 -v 或 --mount 标志
一般来说,--mount
更加明确和详细。最大的区别在于-v
语法将所有选项组合在一个字段中,而--mount
语法则将它们分开。以下是每个标志的语法比较。
提示
新用户应该使用该
--mount
语法。有经验的用户可能更熟悉-v
或--volume
语法,但鼓励使用--mount
,因为研究表明它更易于使用。
-v
or--volume
:由三个字段组成,以冒号字符 (:
) 分隔。字段的顺序必须正确,并且每个字段的含义并不是立即显而易见的。- 在绑定安装的情况下,第一个字段是主机上文件或目录的路径。
- 第二个字段是文件或目录在容器中挂载的路径。
- 第三个字段是可选的,是一个以逗号分隔的选项列表,例如
ro
、z
和Z
。下面讨论这些选项。
--mount
:由多个键值对组成,用逗号分隔,每个键值对由一个<key>=<value>
元组组成。语法--mount
比-v
or更详细--volume
,但键的顺序并不重要,并且标志的值更容易理解。- 安装
type
座的 ,可以是bind
、volume
、 或tmpfs
。本主题讨论绑定安装,因此类型始终为bind
。 source
坐骑的。对于绑定安装,这是 Docker 守护进程主机上的文件或目录的路径。可以指定为source
或src
。- 它
destination
的值是文件或目录在容器中安装的路径。可以指定为destination
、dst
、 或target
。 - 该
readonly
选项(如果存在)会导致绑定挂载 以只读方式挂载到容器中。 - 该
bind-propagation
选项(如果存在)会更改 绑定传播。可能是以下之一rprivate
:private
,,,,,, 。rshared
shared
rslave
slave
- 该
--mount
标志不支持z
或Z
修改 selinux 标签的选项。
- 安装
下面的示例尽可能
显示了--mount
和语法,并且首先给出。-v
--mount
-v 和 --mount 行为之间的差异
由于-v
和--volume
标志长期以来一直是 Docker 的一部分,因此它们的行为无法更改。这意味着-v
和之间存在一种不同的行为--mount
。
如果您使用-v
或--volume
绑定挂载 Docker 主机上尚不存在的文件或目录,则会-v
为您创建端点。它始终创建为目录。
如果您使用--mount
绑定挂载 Docker 主机上尚不存在的文件或目录,Docker 不会自动为您创建它,而是会生成错误。
使用绑定挂载启动容器
考虑这样一种情况,您有一个目录source
,并且当您构建源代码时,工件被保存到另一个目录source/target/
.您希望工件可供位于 的容器使用/app/
,并且您希望每次在开发主机上构建源代码时容器都可以访问新的构建。使用以下命令将target/
目录绑定安装到位于 的容器中/app/
。从目录中运行命令
source
。该$(pwd)
子命令扩展到 Linux 或 macOS 主机上的当前工作目录。如果您使用的是 Windows,另请参阅
Windows 上的路径转换。
--mount
下面的示例-v
产生相同的结果。除非devtest
在运行第一个容器后删除容器,否则您无法同时运行它们。
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app \
nginx:latest
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app \
nginx:latest
用于docker inspect devtest
验证绑定安装是否已正确创建。查找以下Mounts
部分:
"Mounts": [
{
"Type": "bind",
"Source": "/tmp/source/target",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
这表明该挂载是一个bind
挂载,它显示了正确的源和目标,它表明该挂载是可读写的,并且传播设置为rprivate
。
停止容器:
$ docker container stop devtest
$ docker container rm devtest
挂载到容器上的非空目录中
如果将目录绑定挂载到容器上的非空目录中,则该目录的现有内容将被绑定挂载遮盖。这可能是有益的,例如当您想要测试应用程序的新版本而不构建新映像时。然而,这也可能令人惊讶,这种行为与 docker Volume的行为不同。
此示例被设计得比较极端,但将容器/usr/
目录的内容替换为/tmp/
主机上的目录。在大多数情况下,这会导致容器无法运行。
--mount
和示例-v
具有相同的最终结果。
$ 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".
$ 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".
容器已创建但未启动。go掉它:
$ docker container rm broken-container
使用只读绑定挂载
对于某些开发应用程序,容器需要写入绑定挂载,因此更改会传播回 Docker 主机。在其他时候,容器只需要读取访问权限。
ro
此示例修改了上面的目录,但通过添加到容器内挂载点之后的选项列表(默认为空),将目录挂载为只读绑定挂载。如果存在多个选项,请用逗号分隔它们。
--mount
和示例-v
具有相同的结果。
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app,readonly \
nginx:latest
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app:ro \
nginx:latest
用于docker 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
递归挂载
当您绑定挂载本身包含挂载的路径时,默认情况下这些子挂载也包含在绑定挂载中。此行为是可配置的,使用bind-recursive
的选项--mount
。此选项仅受标志支持--mount
,不支持-v
或--volume
。
如果绑定挂载是只读的,Docker 引擎会尽力尝试将子挂载设置为只读。这称为递归只读安装。递归只读挂载需要 Linux 内核版本 5.12 或更高版本。如果您运行的是较旧的内核版本,则默认情况下子安装会自动以读写方式安装。尝试使用该选项将 5.12 之前的内核版本上的子挂载设置为只读会
bind-recursive=readonly
导致错误。
该选项支持的值为bind-recursive
:
价值 | 描述 |
---|---|
enabled (默认) | 如果内核是 v5.12 或更高版本,则只读挂载将递归地设置为只读。否则,子安装是可读写的。 |
disabled | 子安装将被忽略(不包括在绑定安装中)。 |
writable | 子安装座是可读写的。 |
readonly | 子安装座是只读的。需要内核 v5.12 或更高版本。 |
配置绑定传播
绑定传播默认rprivate
针对绑定安装和卷。它只能配置为绑定安装,并且只能在 Linux 主机上。绑定传播是一个高级主题,许多用户永远不需要配置它。
绑定传播是指在给定绑定安装中创建的安装是否可以传播到该安装的副本。考虑一个安装点/mnt
,它也安装在/tmp
.传播设置控制 上的安装是否/tmp/a
也可在 上使用/mnt/a
。每个传播设置都有一个递归对位。在递归的情况下,请考虑将/tmp/a
也安装为/foo
。传播设置控制是否存在/mnt/a
和/或/tmp/a
将存在。
警告
挂载传播不适用于 Docker Desktop。
传播设置 | 描述 |
---|---|
shared | 原始挂载的子挂载会暴露给副本挂载,并且副本挂载的子挂载也会传播到原始挂载。 |
slave | 类似于共享安装,但仅在一个方向。如果原始安装公开了子安装,则副本安装可以看到它。但是,如果副本安装公开了子安装,则原始安装将看不到它。 |
private | 该坐骑是私人的。其中的子安装不会暴露给副本安装,并且副本安装的子安装不会暴露给原始安装。 |
rshared | 与共享相同,但传播也会扩展到嵌套在任何原始或副本安装点内的安装点。 |
rslave | 与从属相同,但传播也会扩展到嵌套在任何原始或副本安装点内的安装点。 |
rprivate | 默认。与私有相同,这意味着原始安装点或副本安装点中的任何位置都没有安装点以任一方向传播。 |
在安装点上设置绑定传播之前,主机文件系统需要已经支持绑定传播。
有关绑定传播的更多信息,请参阅 共享子树的 Linux 内核文档。
以下示例将target/
目录两次挂载到容器中,第二次挂载同时设置了该ro
选项和rslave
绑定传播选项。
--mount
和示例-v
具有相同的结果。
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app \
--mount type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave \
nginx:latest
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app \
-v "$(pwd)"/target:/app2:ro,rslave \
nginx:latest
现在,如果您创建/app/foo/
,/app2/foo/
也存在。
配置selinux标签
如果使用,selinux
您可以添加z
或Z
选项来修改要挂载到容器中的主机文件或目录的selinux 标签。这会影响主机本身上的文件或目录,并可能在 Docker 范围之外产生影响。
- 该
z
选项表示绑定挂载内容在多个容器之间共享。 - 该
Z
选项指示绑定挂载内容是私有且不共享的。
使用这些选项时要格外小心。使用/home
或/usr
选项绑定安装系统目录Z
会使您的主机无法操作,并且您可能需要手动重新标记主机文件。
重要的
当将绑定挂载与服务一起使用时,selinux 标签 (
:Z
和:z
) 以及:ro
将被忽略。有关详细信息,请参阅 moby/moby #32579。
此示例设置z
选项以指定多个容器可以共享绑定安装的内容:
无法使用该--mount
标志修改 selinux 标签。
$ docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app:z \
nginx:latest
将绑定安装与 compose 结合使用
具有绑定安装的单个 Docker Compose 服务如下所示:
services:
frontend:
image: node:lts
volumes:
- type: bind
source: ./static
target: /opt/app/static
volumes:
myapp:
有关bind
在 Compose 中使用该类型卷的更多信息,请参阅
有关卷的 Compose 参考。并
撰写有关卷配置的参考。