Docker 卷可以从设备挂载而不是绑定挂载目录吗?

Docker 卷可以从设备挂载而不是绑定挂载目录吗?

我想在 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

用于dockerdocker-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/

相关内容