![Docker 卷可以从设备挂载而不是绑定挂载目录吗?](https://linux22.com/image/763580/Docker%20%E5%8D%B7%E5%8F%AF%E4%BB%A5%E4%BB%8E%E8%AE%BE%E5%A4%87%E6%8C%82%E8%BD%BD%E8%80%8C%E4%B8%8D%E6%98%AF%E7%BB%91%E5%AE%9A%E6%8C%82%E8%BD%BD%E7%9B%AE%E5%BD%95%E5%90%97%EF%BC%9F.png)
我想在 Linux 主机上设置一个 docker 服务(docker-compose),并使用容器将整个[可移动] 物理硬盘安装为 docker 卷。
我知道在 docker-compose 中设置绑定挂载很简单,我可以在主机上手动挂载驱动器。这种方法确实工作,但它涉及手动步骤,因此容易出现人为错误。当此服务以主机驱动器根分区上的空白目录启动时,会发生糟糕的事情。如果驱动器在仍处于安装状态时拔下,则会发生更糟糕的事情。
我想做的是让 docker 直接将设备挂载为卷。这样做的优点是手动步骤更少/更简单,并且如果驱动器丢失,服务将无法启动,从而提供故障保护。这还可以确保在服务停止时卸载驱动器。
鉴于卷基本上只是操作系统挂载,感觉这应该很简单,但是通过文档进行多次搜索,我仍然没有取得任何进展。
答案1
在 Linux docker 主机上,可以通过首先使用local
驱动程序创建命名卷来实现。
命名卷只是容器启动时要挂载的内容的规范,因此创建卷时无需插入设备。
首先从 docker 创建一个命名卷。假设我要挂载的设备是 ext4 驱动器,并且将始终显示为/dev/disk/by-uuid/d28c6d3a-461e-4d7d-8737-40e56e8f384a
:
# Create "my-volume"
docker volume create --driver=local --opt type=ext4 --opt device=/dev/disk/by-uuid/d28c6d3a-461e-4d7d-8737-40e56e8f384a my-volume
# Run a container with it mounted to a path.
docker run -v my-volume:/my-volume --rm -it alpine sh
笔记:在 Linux 下,设备名称经常会发生变化。因此,使用类似 的名称并不是一个好主意,/dev/sdb1
因为您无法保证它始终被命名为sdb1
。在上面的示例中,我使用了 uuid 来确保始终安装正确的设备。
答案2
用于docker
将docker-compose
设备安装到容器中仅有的不是一个受支持的用例,因此没有直接的方法来做到这一点(至少据我所知)。
更新:实际上这是由local
卷驱动程序支持的,请参阅接受的答案。这个答案只是一种可能的解决方法。
但是你可以使用以下命令将块设备传递到容器中--device
旗帜docker run
(或者devices
属性分别为docker-compose
)并手动将设备安装到容器中 - 例如使用适当的入口点脚本。
请注意,安装块设备需要增强的功能,而这些功能通常会在新容器中删除,因此您还需要添加该CAP_SYS_ADMIN
功能,如下所示:
docker run --device /dev/sdd1 --cap-add CAP_SYS_ADMIN my_image
(docker-compose
参见cap_add
属性)
然后,您可以 - 手动或者在脚本/自定义入口点中 - 在容器内挂载磁盘:
# within the running container
mount /dev/sdd1 /mnt
这种方法只需要您将设备的安装添加到容器中,然后就可以满足您的所有其他要求:
- 在启动容器之前,不需要在主机上手动安装设备
- 当设备不可用时,它将拒绝启动容器(但请确保在失败时手动中止
mount
!) - 因为容器有自己的挂载命名空间已安装的卷仅在容器内可用,当容器停止时,设备将自动卸载
- 可以设置为
docker-compose
/dev/disk/by-label/
为了避免在拔出/插入设备时更改设备名称出现问题,您可以使用为其创建的符号链接之一/dev/disk/by-uuid/
。