volume
Last updated
Last updated
为了持久化由容器产生和使用的数据,优先选择卷来达到这个目的。bind mounts依赖主机操作系统的目录结构,而卷完全由容器进行管理。与bind mounts相比,卷有以下几点优势:
备份或迁移更加方便。
可以通过Docker CLI或Docker API对卷进行管理。
卷可以同时用于Linux容器和Windows容器。
可以在多个容器之间更加安全地共享数据。
卷驱动可以让我们在远端主机或云服务商存储卷,来加密卷中的内容或添加其他的功能。
新的卷中的内容可以被容器预先处理。
在Mac或Windows主机上,Docker Desktop的卷比起bind mounts拥有更高的性能。
对于持久化容器可写层的数据,卷通常是更好的一种方案。它不会增加容器的大小,并且卷中的内容与容器的生命周期是分开的。
如果容器生成是非持久化的数据,我们可以考虑使用tmfs mount
来避免将数据永久性地存储在某个地方,并且通过避免对容器的写入层进行写入而提升容器的性能。
卷使用rprivate
绑定传播(bind propagation)
,并且对于卷,绑定传播(bind propagation)
无法配置。
通常来说,--mount
更加的明确和详细。最大的不同是-v
语法将所有的选项组合在一起放入一个字段,而--mount
语法则是分开的。
如果我们需要指定卷驱动选项,那么必须使用--mount。
-v
或--volume
: 由三个字段组成,通过:分隔开。字段必须按照正确的顺序组合。
如果是指定一个命名卷,第一个字段是卷的名称,并且这个名称在主机上是独一无二的。如果是匿 名卷,则第一个字段可以省略。
第二个字段指定容器上被挂载的文件或路径。
第三个字段是可选的,是一个逗号分隔的选项列表,例如ro
。
--mount
:由多个键值对组成,通过逗号进行分隔,每一个都是一个键值对组合。--mount
语法比-v
或--volume
更详细,但是键的顺序没有那么重要,并且它所对应的值更容易被理解。
挂载的类型(type)
可以是bind
,volume
或者tmpfs
。
挂载的源(source)
。对于命名卷,它是卷的名称。对于匿名卷,这个字段可以被省略。可以通过source
或src
两种形式来指定源。
挂载的目的地(destination)
使用容器中被挂载的文件或目录的路径作为值。可以通过destination
,dst
或target
三种形式来指定目的地。
readonly
选项如果存在,它会将bind mount
以只读的形式挂载到容器中。
volume-opt
选项可以多次使用,使用选项名和值的键值对形式。
与bind mount
相反,卷即可以使用-v
也可以使用--mount
。当使用带有服务的卷时,只支持--mount
。
与bind mount
不同,卷可以在容器外部被创建和管理。
列出卷:
检查一个卷:
移除一个卷:
我们在启动一个带有卷的容器时,如果卷还不存在,Docker会为我们创建一个卷。下面的实例将myvol2
挂载到了容器中的/app/
目录。
使用--mount
的形式:
使用-v
的形式:
使用docker inspect devtest
来检查一个卷是否挂载正确。查看Mounts
部分:
上面的信息显示挂载的是一个卷,显示了正确的源和目的地,并且挂载是read-write
的。
停止一个容器,然后移除卷。这里需要注意移除一个卷的正确步骤!
带有卷的docker-compose
服务看起来应该是下面这样的:
在我们第一次调用docker-compose up
时,卷会被创建。后续的调用会重复使用相同的卷。
一个卷也可以直接在docker-compose
外部通过docker volume create
创建,然后在docker-compose.yml
中引用:
当我们启动一个服务和定义一个卷时,每一个服务容器使用自己的本地卷。如果使用本地(local)
卷驱动, 容器之前无法共享存储,但是有一些的卷驱动支持共享存储。
下面的示例启动一个带有四个副本的nginx
服务,每一个服务都使用名字叫myvol2
的本地卷。
使用docker service ps ps devtest-service
来检查正在运行的服务:
移除服务:
docker service create
命令不支持-v
或--volume
。当挂载一个卷到服务的容器时,必须使用--mount
。
当启动一个使用新创建的卷的容器时,被挂载的目录里面包含了容器的文件和一些目录(例如上面所说的/app/),被挂载目录的内容会被拷贝到卷中。容器会进一步挂载和使用卷,其他使用该卷的容器也可以访问这些预填充的内容。
为了解释上面所说的,下面的示例启动了一个nginx容器,并且使用容器中/usr/share/nginx/html目录中的内容填充了新的nginx-vol卷。该目录默认保存nginx的默认HTML内容。
使用--mount:
使用-v:
运行完上面的示例以后,依然按照正确的步骤删除卷。
对于一些应用开发,容器需要对bind mount进行写入,以便写入以后产生的更改可以传播到容器主机。在其他时候,容器只需要访问这些数据。在同一时间,多个容器可以挂载到相同的卷,对于一些容器可以使用read-write形式挂载而其他的容器使用read-only形式挂载。
下面的示例通过在前面使用过的命令选项列表中添加ro,来使卷作为只读卷挂载到容器中的指定路径。
通过docker inspect nginxtest | jq '.[] | .Mounts[]'
来查看被挂载的卷:
停止和移除容器,然后移除卷。卷删除必须按照单独有序的步骤执行。
当构建零容错的应用时,我们可能需要为服务配置多个副本来访问相同的文件。
当开发应用时,我们有多种方式来实现数据共享。一个是在我们的应用中添加代码逻辑,使文件存储在像AWS S3这样的存储系统中。另外一种方式是通过一个支持将文件写入到外部存储系统(例如NFS或AWS S3)的驱动来创建一个卷。
当我们使用docker volume create或当我们启动一个使用还没有创建的卷的容器时,我们可以指定一个卷驱动。下面的示例使用vieus/sshfs卷驱动。
下面示例假设我们有两个节点,第一个节点可以使用ssh连接到第二个节点。
在docker主机上安装vieux/sshfs插件:
下面示例指定了一个SSH密码,但是如果两个主机共享配置的key,我们可以省略密码。每个卷驱动可以有零个或多个可配置的选项,每一个选项使用-o指定。·
下面示例指定了一个SSH密码,但是如果两个主机共享配置的key,我们可以省略密码。每个卷驱动可以有零个或多个可配置的选项。如果卷驱动需要我们传递选项,我们必须使用--mount
来挂载卷而不是-v
。
下面示例展示了创建一个服务时如何创建一个NFS卷。示例使用10.0.0.10作为NFS服务器地址,而/var/docker-nfs作为被导出的目录。注意这里的卷驱动指定为local。
NFSV3
NFSV4
卷对于备份,恢复和迁移非常有用。使用--volumes-from来创建一个挂载到卷上面的新容器。
例如,创建一个dbstore的容器:
下面的命令中,我们:
启动一个新的容器,然后挂载到dbstore容器的卷上面。
挂载一个本地主机目录/backup。
传递一个命令到容器中将dbdata卷中的内容打包成backup.tar文件并保存在/dbdata中。
通过上面备份的数据,我们可以在相同的容器中或者你在其他地方创建的容器中恢复它。
例如,创建一个名为dbstore2的容器:
然后在新的容器的数据卷中解压备份文件:
一个Docker数据卷在容器被删除以后依然存在。有两种类型的卷需要了解:
命名卷有一个来自容器外部的指定的源,例如awesome:/bar。
匿名卷没有指定的源,因此当容器被删除时,需要通过命令让Docker引擎去移除它们。
如果需要自动删除匿名卷,可以使用-rm选项。例如,下面的命令创建了一个匿名/foo卷,当容器被删除时,Docker引擎会移除/foo卷,但是不会移除awesome卷。
移除所有卷来释放空间,我们可以使用下面的命令: