• docker 数据持久化


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

    • 定制镜像持久化:将这个修改过的容器生成一个新的镜像,让这些修改变为只读的镜像

    • 数据卷持久化:将这些修改通过数据卷同步到宿主机

    定制镜像持久化

    需求

    DockerHub上拉取的centos:7镜像是没有vim工具的,现在将centos:7镜像运行后下载vim工具,再将这个容器打包为一个镜像(centos7:vim)。最后运行这个镜像,可以看到这个镜像里面是有vim工具的。

    实现

    由于之前做过类似的需求,在此我只把使用的命令展示出来。

    # 运行centos:7镜像
    docker run --name centos1 -it centos:7
    
    # 进入到centos7的shell后下载vim
    yum install -y vim
    
    # 下载完成之后输入exit退出centos7容器的shell环境。
    # 并将该容器打包为一个镜像
    docker commit -m="add vim" -a="bing" centos1 centos7:vim
    
    # 打包完成后运行这个新镜像
    docker run --name centos_vim -it centos7:vim
    
    # 查看vim的版本
    vim --version
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    数据卷持久化

    数据卷简介

    数据卷宿主机中的一个特殊的文件/目录,这个文件/目录与容器中的另一个文件/目录进行了直接关联,在任何一端对文件/目录的写操作,在另一端都会同时发生相应变化。在宿主中的这个文件/目录就称为数据卷,而容器中的这个关联文件/目录则称为该数据卷在该容器中的挂载点。数据卷的设计目的就是为了实现数据持久化,其完全独立于容器的生命周期,属于宿主机文件系统,但不属于 UnionFS。因此,容器被删除时,不会删除其挂载的数据卷。

    数据卷的特性

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

    • 数据卷在容器启动时初始化,如果容器启动后容器本身已经包含了数据,那么,这些数据会在容器启动后直接出现在数据卷中,反之亦然。

    • 可以对数据卷或挂载点中的内容直接修改,修改后对方立即可看到。

    • 数据卷会一直存在,即使挂载数据卷的容器已经被删除。

    • 数据卷可以在容器之间共享和重用。

    创建读写数据卷

    数据卷是在使用 docker run 启动容器时指定的,其语法格式为:

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

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

    # 启动容器并创建数据卷
    docker run --name centos1 -it -v /tmp/read_write_sour:/tmp/read_write_dest centos:7
    
    • 1
    • 2

    在容器的/tmp/read_write_dest目录下创建hello.log文件,并写入数据。
    image-20230913123654815

    看宿主机的/tmp/read_write_sour目录下是否有文件和数据,然后向hello.log文件中添加数据。
    image-20230913124045098

    看看容器的/tmp/read_write_dest目录下的hello.log文件是否有宿主机添加的数据。
    image-20230913124217614

    停止容器后的操作

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

    查看数据卷详情

    通过 docker inspect [容器] 命令可以查看到当前容器中挂载点与数据卷的绑定关系,其中Mounts表示挂载的意思。
    image-20230913125316507

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

    创建只写数据卷

    只读数据卷,指的是容器对挂载点的操作权限是只读的宿主机对数据卷的操作权限始终是读写的。有些情况下,为了防止容器在运行过程中对文件产生修改,就需要创建只读数据卷。创建只读数据卷的命令比之前的命令仅多了:ro,具体语法如下:

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

    # 启动容器并创建只读数据卷
    docker run --name centos2 -it -v /tmp/read_only_sour:/tmp/read_only_dest:ro centos:7
    
    • 1
    • 2

    在宿主机中的/tmp/read_only_sour目录下创建一个read-only.log文件,并写入数据。
    image-20230913150455156

    登录到容器中的/tmp/read_only_dest目录下,看看reda-only.log文件的内容,并尝试写入数据。
    image-20230913150939058

    发现在容器中并不能向read-only.log写入数据,说明在该目录下,所有的文件对于容器来说都是只读的。

    查看数据卷详情

    通过 docker inspect centos2 命令可以查看到该数据卷的RW为false,也就是该容器对数据卷有只读属性。
    image-20230913151351735

    创建共享数据卷

    当一个容器与另一个容器使用相同的数据卷时,就称这两个容器实现了“数据卷共享”。而数据卷容器是实现数据卷共享的一种非常有效的方案。当一个容器 C 启动运行时创建并挂载了数据卷,若其它容器也需要共享该容器 C 挂载的数据卷,这些容器只需在 docker run 启动时通过 --volumes-from “容器C” 选项即可实现数据卷共享。此时容器 C 就称为数据卷容器。

    现在搭建如下环境的各种容器以及数据卷。
    image-20230913160517198

    # 首先创建一个使用读写数据卷的centos:3的容器并运行。
    docker run --name centos3 -it -v /tmp/share_sour:/tmp/share_dest centos:7
    
    # 然后创建两个容器分别是tomcat1和tomcat2,注意加上--volumes-from centos3的选项。
    docker run --name tomcat1 --volumes-from centos3 -it tomcat:8.5.32 /bin/bash
    docker run --name tomcat2 --volumes-from centos3 -it tomcat:8.5.32 /bin/bash
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    容器创建完成后,首先宿主机在/tmp/share_sour目录下创建一个share.log的文件,并写入数据。
    image-20230913161915530

    第二步是centos3容器在/tmp/share_dest目录下读取数据并写入数据。
    image-20230913162126945

    第三步是tomcat1容器在/tmp/share_dest目录下读取数据并写入数据。
    image-20230913162300903

    第四步是tomcat2容器在/tmp/share_dest目录下读取数据并写入数据。
    image-20230913162353465

    可以看到这三个容器和宿主机之间实现了数据共享。

    Dockerfile持久化

    Dockerfile 持久化,其实就是通过使用 Dockerfile 的 VOLUME 指令指定数据卷方式实现的持久化。VOLUME 指令可以在容器中创建可以挂载数据卷的挂载点。其参数可以是字符串数组,也可以是使用空格隔开的多个纯字符串。例如,VOLUME [ “/tmp/demo”, “/etc/apache”] 或VOLUME /tmp/demo /etc/apache。

    创建Dockerfile、构建和运行镜像

    首先mkdir 一个目录,例如 volume,然后在其中新建 Dockerfile,内容如下。这里指定/tmp/demo1 与/opt/demo2 为容器端的挂载点。

    FROM centos:7
    VOLUME /tmp/demo1 /opt/demo2
    CMD /bin/bash
    
    • 1
    • 2
    • 3

    然后就是构建和运行镜像,命令如下:

    # 构建镜像
    docker build -t volume .
    
    # 运行镜像
    docker run --name vols -it volume
    
    • 1
    • 2
    • 3
    • 4
    • 5

    查看宿主机端的目录

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

    Source是宿主机的目录,Destination是容器的目录。向/var/lib/docker/volumes/0083b3d0a8c8ea137e2bf43a7e43ad1c68e5155415eb293489041bd6dadd50fc/_data 中写入数据,看看容器的/opt/demo2下是否有数据。
    image-20230913164929604

    这就是使用Dockerfile实现数据持久化的方式,即使删除了容器和镜像,数据也还在宿主机的/var/lib/docker/volumes/······/_data目录下。

  • 相关阅读:
    一行代码禁止用户调试前端代码
    2022年济南12行政区高新技术企业补贴政策及认定条件汇总
    3 Thymeleaf 常用语法
    Go 微服务开发框架 DMicro 的设计思路
    quarkus依赖注入之五:拦截器(Interceptor)
    cap理论、base 定理、分布式事务的理解与相互关系
    ninja构建笔记
    MySQL锁机制详解
    BootLooder引导传参和镜像编译
    vue admin element动态路由刷新后白屏
  • 原文地址:https://blog.csdn.net/qq_54015483/article/details/132910607