Docker数据管理---Volumes数据卷管理

学习目标:掌握Volumes数据卷的使用
1.3.1 Docker数据存储机制
使用Docker时,我们操作的都是镜像和由镜像生成的容器,所以想要更好地了解Docker内部的数据存储机制,就必须从镜像、容器与数据存储的关系出发。
Docker镜像是通过读取Dockerfile文件中的指令构建的,Dockerfile中的每条指令都会创建一个镜像层,并且每层都是只读的,这一系列的镜像层就构成了Docker镜像。接下来以一个Dockerfile文件为例进行说明,
FROM ubuntu:16.04
COPY ./app
RUN make /app
CMD python /app/app.py
这个Dockerfile文件包含了4条指令,每条指令会创建一个镜像层,其中每一层与前一层有所不同,并且是层层叠加的。通过镜像构建容器时,会在镜像层上增加一个容器层(即可写层),所有对容器的更改都会写入容器层,这也是Docker默认的数据存储方式。
由于所有的容器都是通过镜像构建的,所以每个容器有各自的容器层,对于容器数据的更改就会保存在各自的容器层中。也就是说,由同一个镜像构建的多个容器,它们会拥有相同的底部镜像层,而拥有不同的容器层,多个容器可以访问相同的镜像层,并且有自己独立的数据状态。
1.3.2Docker数据存储方式
(1)当容器不再运行时,容器中的数据无法持久化保存,如果另一个进程需要这些数据,那么将很难从容器中获取数据。
(2)容器层与正在运行的主机紧密耦合,不能轻易地移动数据。
(3)容器层需要一个存储驱动程序来管理文件系统,存储驱动程序提供了一个使用Linux内核的联合文件系统,这种额外的抽象化降低了性能。
所以我们使用一种叫做Docker volume数据外部挂载的机制进行数据管理。
下面用一张图来展示数据卷、绑定挂载和tmpfs挂载之间的差异,如下图所示

Docker数据管理---Volumes数据卷管理
—volumes:存储在主机文件系统中(在Linux系统下是存在于/var/lib/Docker/volumes/目录)并由Docker管理,非Docker进程无法修改文件系统的这个部分。
—bind mounts:可以存储在主机系统的任意位置,甚至可能是重要的系统文件或目录,在Docker主机或容器上的非Docker进程可以对他们进行任意修改。
—tmpfs mounts:只存在主机系统的内存中,并没有写入到主机的文件系统中。
1.3.3 Volumes数据卷管理
1.3.3.1 Volumes数据卷的优势
虽然Docker数据外部挂载机制提供了三种数据管理方式,但在实际应用中,用到更多的是Volumes和Bind mounts这两种数据管理方式。这两种数据管理方式中,Volumes完全由Docker管理的,是官方相对推荐的数据管理方式;而Bind mounts则要依赖与主机的目录结构。
与Bind mounts(绑定挂载)相比,Volumes(数据卷)有以下几个优势。
—数据卷比绑定挂载更容易备份和迁移。
—可以使用Docker CLI指令或Docker API来管理数据卷。
—在Linux和Windows容器上都可以使用数据卷
—在多个容器之间可以更安全的共享数据卷
—数据卷驱动器允许在远程主机或云提供商上存储数据卷,并且加密数据卷的内容或添加其他功能。
—个新数据卷的内容可以由一个容器预填充。
此外,在容器的可写层中,数据卷通常是持久化数据更好的选择,因为使用数据卷并不会增加使用容器的大小,而且数据卷的内容存在于给定容器的生命周期之外。如果我们的容器生成了非持久状态的数据,那么可以考虑使用tmpfs mounts(tmpfs挂载),因为它可以避免永久存储数据,以及写入容器的可写层时增加容器的负担。
1.3.3.2 Volumes数据卷使用
下面小编以数据卷为例来演示Docker如何进行数据管理
1.创建并管理数据卷
(1)创建数据卷
在Docker主机终端,通过对docker volume create指令创建一个名为my-vol的数据卷
#docker volume create my-vol
(2)查看数据卷
使用docker vvolume ls指令查看本地数据卷列表。
#docker volume ls
Docker数据管理---Volumes数据卷管理
从上图中可以看出,新创建的my-vol数据卷已经显示在本地Docker机器上,这说明数据卷创建成功。
(3)核查数据卷
使用docker volume inspect指令查看指定数据卷详情。
#docker volume inspect my-vol #显示my-vol的数据卷的详细信息

Docker数据管理---Volumes数据卷管理
(4)删除数据卷
#docker volume rm my-vol

Docker数据管理---Volumes数据卷管理
2.启动容器并加载数据卷
(1)查看本机容器和数据卷
#docker ps -a #查看本地Docker机器上的容器
#docker volume ls #查看本地Docker机器上的数据卷
Docker数据管理---Volumes数据卷管理
从上图中可以看出,目前本地Docker主机上没有任何容器和数据卷。为了避免后续示例演示的干扰,如果机器上已经存在容器和数据卷,最好将已存在的容器和数据卷删除。
(2)确认查看本机Docker文件系统中的容器和数据卷
首先在Docker主机终端中将普通用户切换到root用户,然后进入“/var/lib/docker”目录,即Docker默认在本机上的文件系统目录,查看信息,

Docker数据管理---Volumes数据卷管理
从上图可以看出,本地Docker机器的文件系统中包含了两个重要的文件目录,分别为containers和volumes,这两个文件目录就是用于存放用户创建的容器和数据卷的。因为前面已经确认Docker机器上没有任何容器和数据卷,所以这两个文件目录是空的。
(3)创建容器并挂载数据卷
#docker run -d -it --name devtest --mount source=myvol,target=/app busybox:latest
这条指令用于创建并启动一个容器,同时挂载一个数据卷
也可以使用-v参数挂载数据卷,命令如下
#docker run -d -it --name devtest2 -v myvol:/app busybox:latest

在上述的两种指令中,首先通过docker run指令创建并启动一个容器,并指定创建容器的名称分别为devtest 和devtest2,然后分别通过–mount和-v两种参数来实现数据卷的挂载。这两个容器共享了同一个一个数据卷myvol,并将该数据卷挂载到了各自的容器中的app目录下。
–mount参数说明
-type(挂载的类型):可以是bind、volume或tmpfs.当前使用的是数据卷,因此类型是volume。
-source(挂载源):对于命名的数据卷来说,这就是数据卷的名称,而对于匿名卷,该字段被省略该字段可以用source 或src表示
-destination(挂载点):就是将文件或目录挂载到容器的具体路径,该字段可以用destination、dst或target表示
readonly参数:挂载到容器中的数据为只读。
—v(–volume的缩写参数)说明:
由三个字段组成,分别由冒号(:)分隔,字段必须以正确顺序排列,而且每个字段的含义都特别明确。关于-v参数的属性值的说明具体如下。
-在命名卷的情况下,第一字段是数据卷的名称,在给定的主机上是唯一的;对于匿名卷,将会省略第一个字段
-第二个字段是在容器中挂载数据的的文件或目录的路径
-第三个字段是可选的,是一个逗号分隔的参数列表,如ro(readonly),即只读)。
Docker数据管理---Volumes数据卷管理
(4)再次查看本机容器和数据卷列表
在Docker主机终端分别使用docker ps -a和docker volume ls指令查看本地Docker机器上存在的容器和数据卷。
Docker数据管理---Volumes数据卷管理
从上图可以看出,容器创建成功后自动加载了数据卷。如果在创建容器时数据卷不存在,则Docker会自动创建。
(5)检查容器详情
在Docker主机终端使用docker inspect+容器名称指令查看容器详情(主要查看数据挂载信息),
Docker数据管理---Volumes数据卷管理Docker数据管理---Volumes数据卷管理
从上图可以看出,容器数据挂载了Mounts信息,其中包括挂载类型为volume、数据卷名称为myvol、数据卷在本地Docker机器上的对应存储地址、数据在容器中的对应地址app目录以及容器中的数据是可写的(RW:true)等。
(6)再次确认本机Docker文件系统中的容器和数据卷
首先在Docker主机终端中将普通用户切换到root用户,然后进入/var/lib/docker目录,然后分别进入containers容器文件目录和volumes数据卷文件目录查看内容。
Docker数据管理---Volumes数据卷管理
从上图可以看出,新建的容器和数据卷已自动生成在本地Docker文件目录中。此时,如果我们将两个容器都删除,则在本地Docker文件目录中的容器也会自动消失,但数据卷却可以保留,除非数据卷也被删除。