【云原生 | 18】Docker数据卷及卷的持久化问题

959 阅读5分钟

​携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

作者简介:🏅云计算领域优质创作者🏅新星计划第三季python赛道TOP1🏅 阿里云ACE认证高级工程师🏅
✒️个人主页:小鹏linux
💊个人社区:小鹏linux(个人社区)欢迎您的加入!

1. 数据卷特性

1.1 认识数据卷特性

Docker 镜像由多个只读层叠加而成,启动容器时,Docker 会加载只读镜像层并在镜像栈顶部添加一个读写层> 如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,次即“写时复制”机制

​编辑

1.2 数据卷意义

关闭并重启容器,其数据不受影响;但删除 Docker 容器,则其改变将会全部丢失> 存在的问题>> 存在于联合文件系统中,不易于宿主机访问>> 容器间数据共享不便>> 删除容器其数据会丢失> 解决方案:“卷”>> “卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定”

1.3 数据卷结构

Bind mount volume

Docker-managed volume

Volume可以是物理机上的任何一个目录存储服务方式有很多种,如NFS,MFS等,容器数据共享时需要对接到的文件系统或客户端接口都是不一样的,此时需要CSI容器存储接口将存储服务和容器内部对接。存储服务器对接物理机目录,物理机目录对接容器内目录。

2. docker管理卷(默认挂载)

制作镜像时以volumes关键字会指定一个目录。docker运行时先在镜像内找volumes关键字,然后在物理机的/var/lib/docker/volumes目录下生成一个随机名称的目录,默认将此目录与容器内volumes关键字后面指定的目录挂载起来。

3. 自管理卷(手动挂载)实验

方法1:先在物理机创建一个目录,再将多个容器的目录挂载到物理机目录
[root@localhost ~]# mkdir /data	                    #创建目录
[root@localhost ~]# docker run --name test1 -v /data:/usr/local/nginx/html -d nginx:1.21.4	                                
                                                    #手动挂载
                                                    #-v 物理机目录:容器内目录
[root@localhost ~]# cd /data/		                #进入
[root@localhost data]# ls			                #查看无文件
[root@localhost data]# touch {1..100}	            #创建100个文件
[root@localhost data]# ls			                #查看有1-100个文件
[root@localhost data]# docker exec -it test1 /bin/bash		#进入容器
root@5fdd3cd78396:/# cd /usr/local/nginx/html/		#进入目录
root@5fdd3cd78396:/usr/local/nginx/html# ls			#查看有1-100个文件。挂载成功

此时单容器完成目录共享运行第二个容器,将此容器的/usr/local/nginx/html也与物理机的/data目录挂载:
[root@localhost ~]# docker run --name test2 -v /data:/usr/local/nginx/html -d nginx:1.21.4	    

此时物理机的/data目录分别与test1容器和test2容器的两个目录挂载。这三个目录都可以看到对方创建的文件及内容了。实现了容器与容器的文件共享。且容器删除后,物理机的挂载目录下的文件还存在。
方法2:先运行容器1让它按照默认的方式将容器的目录与物理机随机产生的目录挂载到一起,再查看到物理机上随机产生的这个目录。将其他的所有容器的目录挂载到物理机物理机上随机产生的这个与容器1默认挂载了的目录上。实现多容器数据共享
[root@localhost ~]# docker run --name test1  -d nginx:1.21.4	#运行容器1,会自动默认挂载
[root@localhost ~]# docker inspect test1	                    #查看,找到如下内容就能查找到默认挂载的物理机目录了

​编辑

然后用-v选项可以将其他容器的目录挂载到此目录下了
方法2或者:
[root@localhost ~]# docker run --name test1  -d nginx:1.21.4	#运行容器1,会自动默认挂载
[root@localhost ~]# docker run --name test2 --volumes-from test1 -d nginx:1.21.4
[root@localhost ~]# docker run --name test3 --volumes-from test1 -d nginx:1.21.4

用此命令启动其他容器,并将其他容器的目录自动挂载到容器1的挂载目录下

4. 容器中的数据卷

4.1 数据卷意义

Docker-managed Volume>> docker run -it --name roc -v MOUNTDIR roc/lamp:v1.0>> docker inspect -f {{.Mounts}} roc> Bind-mount Volume>> docker run -it --name roc -v HOSTDIR:VOLUMEDIR roc/lamp:v1.0> Union Volume>> docker run -it --name roc --volumes-from ContainerName roc/lamp:v1.0

4.2 存储驱动

Docker 存储驱动 ( storage driver ) 是 Docker 的核心组件,它是 Docker 实现分层镜像的基础1、device mapper ( DM ):性能和稳定性存在问题,不推荐生产环境使用(centos6及以下的主流)2、btrfs:社区实现了 btrfs driver,稳定性和性能存在问题3、overlayfs:内核 3.18 overlayfs 进入主线,性能和稳定性优异,第一选择

4.3 UFS文件系统-Overlayfs

mount -t overlay overlay -olowerdir=./low,upperdir=./upper,workdir=./work ./merged	
echo "overlay" > /etc/modules-load.d/overlay.conf
cat /proc/modules|grep overlay
reboot  
vim /etc/systemd/system/docker.service 
	--storage-driver=overlay \

5.卷的持久化问题

容器是一个强大的概念,但是有时候并不是所有想访问的事物都能立马被封装成容器。用户可能有一个存储在大的集群上的相关Oracle数据库,想要连接它做一些测试。又或者,用户可能有一台遗留的大型服务器,而它上面现有配置好的二进制程序很难重现。
刚开始使用Docker时,用户想要访问的大部分事物可能会是容器外部的数据和程序。我们将和读者一起从直接在宿主机上挂载文件转到更为复杂的容器模 式:数据容器和开发工具容器。我们还将展示一些实用的技巧,例如,只需要一个SSH连接便能跨网络进行远程挂载,以及通过BitTorrent协议与其他用户分享数据。
卷是Docker的一个核心部分,有关外部数据引用的问题也是Docker生态系统中另一个快速变化的领域。

6.Docker卷的持久化问题

容器的大部分力量源自它们能够尽可能多地封装环境的文件系统的状态,这一点的确很有用处。然而有时候用户并不想把文件放到容器里,而是想要在容器之间共享或者单独管理一些大文件。一个经典的例子便是想要容器访问一个大型的中央式数据 库,但是又希望其他的(也许更传统些的)客户端也能和新容器一样访问它。
解决方案便是卷!一种Docker用来管理容器生命周期外的文件的机制。我们可以使用Docker的卷标志,在容器里访问宿主机上的A文件。如下图则是使用卷标志和和宿主机上的文件系统交互过程

如下命令展示宿主机上的/var/db/tables目录被挂载到了/var/data1:
$ docker run -v /var/db/tables:/var/data1 -it debian bash

-v标志(--volume的简写)表示为容器指定一个外部的卷。随后的参数以冒号分隔两个目录的形式给出了卷的格式,告知Docker将外部 的/var/db/tables目录映射到容器里的/var/data1目录。如果外部目录和容器目录不存在均会被创建。
要注意的是,卷在Dockerfile里被设定为不是持久化的。如果添加了一个卷,然后在一个Dockefile里对该目录做了一些更改,这些变动将不会被持久化到生成的目标镜像.

\

Docker依赖的技术实际上已经以不同形式存在一段时间了,但Docker是那个成功抓住技术行业兴趣点的解决方案。这把Docker推到了一个令人羡慕不已的位置——社区先驱们完成了这一系列工具的开创工作,这些工具又吸引使用者加入社区并不断地回馈社区,形成了一个自行运转的生态系统。
有多种不同的方式来组合编排工具的家族树。图下图展示了我们熟悉的一些工具。树的根节点是docker run命令,这是启动容器最常用的方式。Docker家族的几乎所有工具都衍生于这一命令。树的左侧分支上的工具将一组容器视为单个实体,中间分支的工具借助systemd或服务文件管理容器,右侧分支上的工具将单个容器视为单个实体。沿着这些分支往下,这些工具做的事情越来越多,例如,它可以跨多台宿主机工作,或者让用户远离手动部署容器的繁琐操作。

大家可能会注意到图 9-1 中看似孤立的两个区域——Mesos和 Consul/etcd/Zookeeper组。Mesos是一个有趣的东西,它在Docker之前就已经存在,并且它对Docker的支持是一个附加功能,而不是核心功能。虽然它做得不 错,但是也需要仔细评估,如果仅仅是从功能特性上来看,用户可能在其他工具中也想要有这些。相比之下,Consul、etcd和Zookeeper根本不是编排工具。相反,它们为编排提供了重要的补充功能——服务发现。


\

\