在昨天的文章里面我们讲了Docker的镜像是一系列的只读层组成的。在启动一个容器的时候,Docker 加载镜像的所有只读层,并在最上层加入一个读写层。这使得Docker可以提高镜像构建、存储和分发的效率,节省了时间和存储空间,同样也存在一些问题:文件在宿主机上形式复杂,不能快速的访问容器中的文件,造成多个容器之间的数据无法共享,如果进行删除容器造作,容器的数据会丢失。数据卷volume机制就可以很好的解决这些问题,究竟什么是Docker数据卷volume呢?

数据卷volume容器中的特殊目录或者特定文件,这个特殊的目录以独立的形式存在宿主机中,为数据的共享与持久化提供以下便利:

  1. a.数据卷volume在容器创建时初始化,容器运行时可直接使用其中的文件,同时能在不同的容器之间进行共享使用。

b.操作数据卷volume中数据就会马上生效,对数据的操作并不会对镜像本身产生影响。

c.数据卷volume有独立生存周期,即使删除容器,数据卷volume仍然会存在,即使容器没有使用过数据卷volume,数据卷volume也不会被容器删除。

为容器添加数据卷volume,类似于Linux的mount操作,用户将一个文件夹作为数据卷volume挂载到容器上,可以很方便地将数据添加到容器中供其中的进程使用。多个容器可以共享同一个数据卷volume,为不同容器之间的数据共享提供了便利。在前面提到,数据卷volume的本质是容器中一个特殊的目录。在容器的创建过程中,Docker会使用绑定挂载(bindmount)的方法将宿主机上的指定目录挂载到容器中,挂载完成后的宿主机目录和容器内的目标目录表现一致。操作步骤如下:

1.创建数据卷volume

目前数据卷volume的来源只有两种:用户通过命令行指定的绑定挂载和从其他容器共享。所以,Docker首先需要根据用户指定的数据卷volume类型,判断并新建对应的挂载点。

Docker在创建数据卷volume的过程中主要进行了如下操作:

a.解析参数并生成参数列表,每一个参数都有一个数据卷volume和容器的对应关系,或者一个容器与其他容器共享数据卷volume。

b.初始化并使用参数列表中的参数生成挂载点列表,这一过程在创建容器时执行,即在宿

主机和容器文件目录下创建上述挂载点中所需的路径。

c.将挂载点列表传递给libcontainer,按照挂载点列表中指定的路径、mount参数、读写标志执行所有的mount操作,完成从宿主机到容器内挂载点的映射,这一过程在容器启动时才会执行。

数据卷volume的创建按照容器启动的过程分为两个阶段。第一阶段为容器创建阶段,Docker根据两种不同的数据卷volume来源组装挂载点列表。第二阶段为容器启动阶段,libcontainer使用组装好的挂载点列表进行mount操作,完成数据卷volume的创建。

2.删除数据卷volume

删除数据卷volume主要有两种方法,第一,使用docker volume rm命令进行删除,第二,使用docker run --rm和docker rm -v在删除容器时删除所关联的数据卷volume。

使用第一种方式删除数据卷volume时,Docker首先会检查是否还有容器在使用这个数据卷volume,如果这个数据卷volume还被其他容器所使用,则返回错误信息,并终止删除。如果没有容器在使用这个数据卷volume,那么Docker会将这个数据卷volume在宿主机上对应的目录删除,并删除其维护的本地数据卷volume列表中的相关信息。

在使用第二种方式进行数据卷volume删除时,其数据卷volume的删除过程与第一种类似,但会过滤掉挂载点中Named字段为true的数据卷volume,也就是说这种方式并不会对命名的数据卷volume进行删除。

3.数据卷volume相关配置文件

Docker的每个容器在/var/lib/docker/containers文件夹下有一个以容器ID命名的子文件夹,这个子文件夹中的config.ison文件是这个容器的配置文件,可以从中看到这个容器所使用的数据卷volume ID以及它们的可写情况。要查看数据卷volume的具体信息,可以在文件夹下找与数据卷volume ID或者数据卷volume名字命名的子文件夹,这个子文件夹中的 data目录存储了该数据卷volume中的所有内容。

数据卷volume是Docker对数据共享的管理机制,它很好的解决了文件形势复杂,访问容器中的文件速度过慢、容器间数据无法共享、如操作失误数据丢失的问题,保证容器之间的配置信息互相传递。