本帖最后由 不懂就问 于 2020-4-29 10:20 编辑
一、分享简介
本次主要和大家分享容器的数据是如何存放和管理的,包含:storage driver的类型以及该存储机制的弊端、实现数据持久化和数据共享的两种方式。 二、storage driver 在前面容器镜像分享一节中我们了解到容器的分层机制,最上层是一个可写的容器层,下面是一个个只读的镜像层。分层机制有一个特性:COW(写时拷贝)。 当我们新增数据文件时,新数据会直接存放在最上面的容器层。 修改数据文件时,将根据容器分层结构由上到下依次查找。找到后,将镜像层中的数据复制到容器层进行修改,修改后的数据保存在容器层中,镜像层中的数据保持不变。 删除数据文件时,同样根据容器分层结构由上到下依次查找,找到对应的数据文件后,在容器层中记录该删除操作,但镜像层中并没有真正将该数据文件删除,实际上是由文件系统将该数据遮挡起来而已。 聊了这么多分层结构,那么是谁在管理分层结构呢?正是本次要分享的第一个内容:storage driver。
storage driver的主要作用是管理镜像层和容器层,它实现了多层数据的堆叠并为用户提供了多层数据合并之后的统一视图。 storage driver的类型有很多,常见的有overlay2、AUFS、Device Mapper。我们可以用相关命令查看当前容器引擎的storage driver类型。我们可以看到当前的类型是overlay2,目前所有的linux发行版都支持overlay2,也是默认的一种类型。
那么这种分层机制有没有什么弊端?我们不妨思考几个问题: 1、容器运行时,我们新增与修改了很多数据,当容器被删除时,这部分数据是不是就丢失了? 2、很多个容器同时运行时,如何将一个容器中的数据共享给另一个容器? 3、容器在宿主机上运行时,如何将容器中的数据共享给宿主机?如何将宿主机上的数据共享给容器? 思考完这几个问题,我们可以发现storage driver存在两个弊端:无法实现数据的持久化存储;无法简单快捷的实现容器与容器、容器与宿主机之间的额数据共享。
三、Docker容器数据持久化的两种方式 【volume】 volume是将宿主机上的指定路径下的目录挂载给容器,由Docker管理。当容器被删除时,数据卷仍在存在。 具体挂载:Docker会在宿主机的/var/lib/docker/volumes路径下给每一个volume生成一个目录,作为mount源。 挂载过程中,如果mount point指向容器中的已有目录,则该目录下的数据会被copy到volume中。 如果mount point指向容器中的空目录,则会自动创建所需目录。 volume常用操作命令: 创建卷: 查看卷信息: 删除卷: 我们来实际动手操作体验一下: 创建一个卷,并挂载给一个容器 - docker run -d --name httpd1 -p 8080:80 -v /usr/local/apache2/htdocs httpd
复制代码
我们新建一个httpd容器,命名为httpd1,将宿主机的8080端口映射给这个容器,并新增一个卷挂载给容器的指定路径。 我们可以查看到挂载的类型是volume,挂载源和挂载点的路径,随后我们找到宿主机对应的目录,查看到有一个index.html文件。 进入容器,修改文件内容 - docker exec -it httpd1 /bin/bash
复制代码
我们进入到容器,将静态index.html文件修改为welcome sangfor 由此我们可以发现volume这种方式可以实现数据持久化。
【bind mount】 我们接着来看下bind mount这种方式是如何实现数据持久化存储的。 bind mount 是将 host 上已存在的目录或文件 mount 到容器。 将宿主机的/root/htdocs目录以只读的方式挂载给一个名为httpd1的httpd容器,映射端口8081。 - docker run --name httpd1 -d -p 8081:80 -v /root/htdocs:/usr/local/apache2/htdocs:ro httpd
复制代码
查看容器的挂载信息
我们可以看到Type是bind,挂载源端和挂载路径。 在宿主机上更新index.html文件数据,我们可以发现httpd1容器中的数据也一起更新。 - echo "This is bind mount" > /root/htdocs/index.html
复制代码
此时我们可以发现通过bind mount可以实现容器和主机之间的数据共享。 进入httpd1容器中更新index.html文件数据。 - docker exec -it httpd1 bash
- echo "test read only?" > /usr/local/apache2/htdocs/index.html
复制代码
可以发现此时没有写的权限,提示只读。 将宿主机/root/htdocs挂载给名为httpd2的httpd容器,映射端口8082,不设置只读权限。 - docker run --name httpd2 -d -p 8082:80 -v /root/htdocs/:/usr/local/apache2/htdocs httpd
复制代码
进入容器httpd2中修改index.html文件
分别查看主机、容器httpd1、容器httpd2中的数据。
此时我么可以发现,三者的数据文件是一致的,我们可以利用bind mount实现主机与容器、容器与容器之间的数据共享。
最后我们思考一下:volume和bind mount这两种方式各自有什么优缺点呢? |