在 Docker 文档中,绑定挂载和卷之间有非常明显的区别。
然而,我在撰写文件的根级
volumes
元素中偶然发现了这一点。
volumes:
myvolume:
driver: local
driver_opts:
type: 'none'
o: 'bind'
device: '/my/host/folder'
我很确定这是一卷,因为它在
docker volume ls
中可见。
但是
bind
选项表明这也是绑定安装。
我的假设正确吗? IE。这是一种绑定安装,绑定到 docker 卷而不是容器的内部文件夹(因此,事实上,有两个“绑定”)?
从操作系统的角度来看,这是如何工作的?
这仍然可以利用使用 Docker 卷的好处吗?
暂时忽略 Docker,在 Linux 主机上,您可以运行
mount --bind /old/dir /new/dir
来使两个目录具有相同的底层磁盘存储。这与 Docker 绑定挂载具有相同的属性;如果您写入 /new/dir
,它也会在 /old/dir
中可见,并且如果挂载之前的 /new/dir
中有任何内容,它就会被隐藏。我相信也可以将其写为 mount -o bind ...
(尽管 mount(8) 的此副本没有记录它)。
对于命名卷,Docker 内部的默认设置是在 /var/lib/docker/volumes
中创建一个目录,然后将其绑定挂载到容器中。但是您也可以使用挂载选项手动创建卷,记录的用途是将物理磁盘挂载为 Docker 卷或挂载远程网络驱动器。 您显示的此语法结合了这两个选项。您“使用挂载选项手动创建卷”,但这些挂载选项实际上设置了绑定挂载。
这有几个小优点。 Compose 设置的其他部分不需要知道主机路径,只需要知道 Compose 本地卷名称。如果您犯了错误并且主机目录不存在,您将收到错误而不是正在创建的目录。
这也带来了 Docker 将内容复制到新卷中的令人困惑和非标准的行为:如果目录为空,但只有此时,并且仅对于 Docker 命名卷而不是任何其他类型的挂载,图像内容才会被复制。
docker volume rm
实际上不会删除主机目录内容,只会删除 Docker 私有文件系统空间内的挂载点。对于几乎所有用途,我都会在特定容器中使用内联路径语法
volumes: ['./dir:/container/path']
。由于 Compose 可以转换相对路径,因此您可以使用
./dir
来使用项目树中的目录,从而最大限度地减少硬编码主机目录的可移植性问题。