Docker—6章(数据持久化)


第六章 数据持久化

在容器层的 UnionFS(联合文件系统)中对文件/目录的任何修改,无论是手工修改还是容器在运行过程中的修改,在该容器丢失或被删除后这些修改将全部丢失。即这些修改是无法保存下来的。若要保存下来这些修改,通常有两种方式:

  • 定制镜像持久化:将这个修改过的容器生成一个新的镜像,让这些修改变为只读的镜像
  • 数据卷持久化:将这些修改通过数据卷同步到宿主机

1. 定制镜像持久化

1.1 需求

我们这里要实现的功能是,为 tomcat:10.0 镜像修改其 webapps 目录。原本该目录内容是空的,用户访问 tomcat 页面会报 404,而真正的内容是在 webapps.dist 中。现要将原webapps 目录删除,然后重命名 webapps.dist 目录为 webapps,以使用户可以看到 tomcat页面。

1.2 实现

  1. 运行tomcat容器

    首先以分离模式启动 tomcat 容器。

    此时通过浏览器是无法访问到 tomcat 页面的。

  2. 进入容器后删除目录

    通过 docker exec 命令可以进入到容器命令行。可以看到 webapps 目录是空的,而真正需要的内容在 webapps.dist 目录中。

    删除 webapps 目录,然后将 webapps.dist 目录重命名为 webapps

    此时刷新浏览器就可以看到 tomcat 页面了。

  1. 容器生成镜像

    执行 docker commit 命令,以当前运行的容器为范本生成镜像。

    • -m 指定本次提交的日志
    • -a 指定该镜像的作者
    • tomcat10:own 为新镜像的<repository>:<tag>

    此时可以看到已经生成了新的镜像。

  2. 测试新镜像

    启动 tomcat10:own 镜像容器,指定端口号为 9000

2. 数据卷持久化

Docker 提供了三种实时同步(宿主机与容器 FS 间数据的同步)方式:

  • 数据卷
  • Bind mounts(绑定挂载)
  • tmpfs(临时文件系统)

2.1 数据卷概述

2.1.1 数据卷简介

数据卷是宿主机中的一个特殊的文件/目录,这个文件/目录与容器中的另一个文件/目录进行了直接关联,在任何一端对文件/目录的写操作,在另一端都会同时发生相应变化。在宿主中的这个文件/目录就称为数据卷,而容器中的这个关联文件/目录则称为该数据卷在该容器中的挂载点。

数据卷的设计目的就是为了实现数据持久化,其完全独立于容器的生命周期,属于宿主机文件系统,但不属于 UnionFS。因此,容器被删除时,不会删除其挂载的数据卷。

2.1.2 数据卷的特性

数据卷具有如下明显特性:

  • 数据卷在容器启动时初始化,如果容器启动后容器本身已经包含了数据,那么,这些数据会在容器启动后直接出现在数据卷中,反之亦然
  • 可以对数据卷或挂载点中的内容直接修改,修改后对方立即可看到
  • 数据卷会一直存在,即使挂载数据卷的容器已经被删除
  • 数据卷可以在容器之间共享和重用

2.2 创建读写数据卷

读写数据卷指的是容器对挂载点具有读写权限。

2.2.1 命令

数据卷是在使用 docker run 启动容器时指定的,其语法格式为:docker run –it –v /宿主机目录绝对路径:/容器内目录绝对路径 镜像

注:无论是宿主机中的数据卷还是容器中的挂载点,如果指定的目录不存在,那么 docker引擎都会自动创建。即使是多级目录不存在。

2.2.2 需求

在宿主机中的/root/host_mount 目录与 ubuntu 容器的/opt/uc_mount 目录间建立关联,即宿主机中的/root/host_mount 目录作为数据卷,而 ubuntu 容器的/opt/uc_mount 目录作为挂载点。

2.2.3 创建数据卷

以交互方式启动一个 ubuntu 容器,同时指定在启动容器时创建数据卷。容器启动完毕后在容器中查看/opt 目录,可以看到新建了一个 uc_mount 子目录。这个就是容器中的挂载点目录。

再打开一个会话窗口,查看/root 目录,可以看到新建了一个 host_mount 目录。这个就是数据卷目录。

2.2.4 数据卷/挂载点互操作

宿主机数据卷目录与容器挂载点目录中进行文件修改互操作,修改完毕后,对方都可立即看到修改。

在宿主机数据卷目录中创建一个新的文件。

在容器中可以查看到该文件出现了。

在容器中对文件内容进行修改。

在宿主机中可以查看到该修改过的文件内容。

2.2.5 停止容器后的操作

即使容器停止了,在宿主机中只要修改了数据卷目录内容,在重新启动容器后,该修改过的数据仍会出现在容器中。因为容器是一个 UnionFS,是一个存在于宿主机中的文件系统,无论容器是否运行,该 FS 都是存在的。

通过 exit 退出并停止容器。

在宿主机数据卷目录修改文件。

重新启动并进入容器,查看容器中挂载点目录中的文件内容,发现已发生改变。

2.2.6 查看数据卷详情

通过 docker inspect [容器名称] 命令可以查看到当前容器中挂载点与数据卷的绑定关系。

这里给出了数据卷 Source 与挂载点 Destination 的绑定关系,且容器挂载点默认操作权限是 RW 读写的

2.3 创建只读数据卷

只读数据卷,指的是容器对挂载点的操作权限是只读的。宿主机数据卷的操作权限始终是读写的。有些情况下,为了防止容器在运行过程中对文件产生修改,就需要创建只读数据卷。

2.3.1 命令

该命令仅比之前的命令仅多了:ro,具体语法如下:

docker run –it –v /宿主机目录绝对路径:/容器内目录绝对路径:ro 镜像

2.3.2 创建数据卷

以交互方式启动一个 ubuntu 容器,同时指定在启动容器时创建只读数据卷。

2.3.3 数据卷/挂载点互操作

在容器中修改挂载点中的文件,系统会给出只读文件系统的提示。说明容器对数据卷是只读的。

宿主机中对数据卷文件的修改是成功的。

在容器中同样也是可以看到宿主机中的修改的。

2.3.4 查看数据卷详情

通过 docker inspect [容器] 命令可以查看到该数据卷的只读属性。

2.4 数据卷共享

当一个容器与另一个容器使用相同的数据卷时,就称这两个容器实现了“数据卷共享”。

2.4.1 数据卷容器

数据卷容器是实现数据卷共享的一种非常有效的方案。

当一个容器 C 启动运行时创建并挂载了数据卷,若其它容器也需要共享该容器 C 挂载的数据卷,这些容器只需在 docker run 启动时通过--volumes-from[容器 C] 选项即可实现数据卷共享。此时容器 C 就称为数据卷容器

2.4.2 需求

myubuntu2 容器要共享前面的 myubuntu 容器的数据卷,即宿主机中/root/host_mount为数据卷目录,而这两个容器的挂载点目录都是/opt/uc_mount

2.4.3 进入 myubuntu 容器

通过 docker exec 命令进入 myubuntu 容器后,进入挂载点目录/opt/uc_mount

2.4.4 创建并运行 myubuntu2 容器

这里在创建并运行 myubuntu2 容器时,使用--volumes-from 指定该容器要共享 myubuntu的数据卷,即指定 myubuntu 容器为数据卷容器。此时可以发现,myubuntu2 容器中也同样出现了挂载点目录/opt/uc_mount

2.4.5 数据卷共享操作

经过上述操作,myubuntu myubuntu2 这两个容器实现了数据卷共享。此时,无论是在宿主机,还是 myubuntu myubuntu2 任意容器中挂载点目录中的任意写操作,在另外两方均可同步看到该写操作的结果。

下面举例:首先在宿主机数据卷目录中创建一个文件 data.log

myubuntu 容器中可以查看到 data.log 文件。然后,myubuntu 容器也修改该文件。

myubuntu2 容器中可以查看到 data.log 文件。然后,myubuntu2 容器也修改该文件。

myubuntu2 容器对文件的修改,在 myubuntu 容器与宿主机中均可看到。

3. Dockerfile 持久化

Dockerfile 持久化,其实就是通过使用 Dockerfile VOLUME 指令指定数据卷方式实现的持久化。

3.1 VOLUME指令

VOLUME 指令可以在容器中创建可以挂载数据卷的挂载点。其参数可以是字符串数组,也可以是使用空格隔开的多个纯字符串。例如,VOLUME ["/var/www", "/etc/apache"] VOLUME /var/www /etc/apache。

3.2 持久化实现

3.2.1 创建 Dockerfile

/root 目录中 mkdir 一个目录,例如 vols,然后在其中新建 Dockerfile,内容如下。这里指定/opt/xxx/opt/ooo 为容器端的挂载点。

FROM centos:7
VOLUME /opt/xxx /opt/ooo
CMD /bin/bash

3.2.2 构建镜像 build

使用 Dockerfile 构建镜像 volscon:latest

3.2.3 运行新建镜像

以交互方式运行新建镜像。

3.2.4 查看宿主机端目录

Ctrl + P + Q 退出容器后,使用docker inspect查看当前容器中的挂载点目录到底与宿主机中的哪个数据卷对应。

3.2.5 验证

在容器端首先进入/opt/xxx 目录,并在其中新建一个文件 hello.log

在宿主机端,从 docker inspcet 命令中找到/opt/xxx 目录对应的数据卷 Source 目录,首先进入到该目录,然后就可以查看到对应的 hello.log 文件了。说明数据卷设置成功,可以实现从容器到数据卷的持久化了

在宿主机端修改文件内容,在容器端同样也是可以看到的。


文章作者: 念心卓
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 念心卓 !
  目录