WHCSRL 技术网

Docker:逻辑卷详细解释

目录

 什么是数据卷?

 扩展

 为什么要使用逻辑卷?

 卷

 卷的种类

创建逻辑卷

Docker-managed volume创建

 Bind mount volume 创建

使用go模板过滤insepct中的信息

 2个容器共享容器卷

创建共享存储卷并加入基础镜像的网络


Docke 作为容器运行底层引擎,在组织和运行时候每个程序只运行一个程序及子程序,对于启动这个容器它底层可能不止一层的镜像联合挂载的启动而成

最上层时可写层【读写层】,对于容器的所有的操作包括数据,对内容的修改都是在最上层;对下层的操作比如:删除的操作,是通过写时复制的操作来实现

 什么是数据卷?

Docker 镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层

如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本任然存在,只是已经被读写层中该文件的副本所隐藏,此即 " 写时复制(COW)"机制

如图Layer0上的文件A,在Layer1上修改为C,在Layer2标记为删除D,对于最上层用户来说一定是不可见的;如图Layer0上的文件A,在Layer1上标记为删除D,在Layer2创建了一模一样同名文件/修改C,用户是可见的

 对于这种层级关系,修改、删除的操作效率一般会非常的低,比较存在这么多层,还有哪些隐藏还不是真正的删除的一类的操作,对于哪些IO要求非常高的应用:redies,mysql,在实现持久化存储的时候,就会对IO性能要求很高

当我们运行了Mysql容器,如果写的数据在容器中,容器删除后数据也会删除,为了绕过这种使用的机制我们可以建立数据卷来解决,我们可以理解为在物理机之上找一个文件目录,于容器上的某一个访问目录建立关联关系,进行有效数据【临时文件】同步即使删除了容器,只要重新关联了物理的数据目录,还是可以正常访问数据的;但是容器重新关连了别的物理机相同的目录是没有数据

这样我们就可以把容器当作有生命的动态容器对象来使用,容器关闭就是容器删除的时候,但是底层镜像还在,我么们还可以重新启动;假设我们在重新的启动的时候忘记掉了那个容器管理的是物理机的那个逻辑卷,怎么办?可以的话我们可以用文件来保存那个容器对应的物理机的目录,这大多数是容器编排工具使用的,我们大部分只是通过命令行来启动进行关联,如果通过配置文件的启动,容器就会不限于启动在特定的物理机上

如图容器其A与物理机A的/data/data目录关联,物理机的/data/data/在与文件文件系统NFS的/data/data目录关联做到数据持久化存储;这样就不害怕容器A删除后没有数据,也不会局限于特定主机,可以多集群部署

 扩展

 我们的容器是需要持久化存储的,如果使用Nginx方向代理去做,有必要去做持久化存储的吗?应用大致分为有状态【当前的请求处理与此前请求是由关联关系】和无状态【前后的请求是没有关联关系的】两种,大部分有状态的都需要做持久化存储:Mysql,redies

 为什么要使用逻辑卷?

关闭并重启容器,其数据不受影响;但是删除Docker容器,则其更改将会全部丢失

存在的问题:存储于联合文件系统中,不易于宿主机访问;容器间数据共享不便;删除容器其数据会丢书;

解决方案:卷(volume);"卷" 是容器上的一个或多个【一个目录一个卷】" 目录",此目录可绕过联合文件系统,于宿主机上的某目录"绑定(关联)"

 卷

卷(Volume)于容器初始化之时即会创建,由base image提供的卷中的数据会于此期间完成复制
卷的初衷是独立于容器的生命周期实现数据持久化,因此删除容器之时即不会删除卷,也不会对哪怕未被应用的卷做垃圾回收操作【但是删除的容器的时候使用了特殊命令也可以把数据卷删除掉】

卷为Docker提供了独立于容器的管理机制

1、可以把”镜像“ 想象成静态文件,例如程序;把卷类比为动态内容,例如:数据;于是,镜像可以重用,而卷可以共享;

2、卷实现了"程序(镜像)"和"数据(卷)"分离,以及"程序(镜像)"和"制作镜像的主机"分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机的环境

如图:容器内部的程序如果写在根目录,会写到容器的可写层当中;写道挂载到的卷的目录,就会写到卷中;我们知道程序在运行的中,会生成许多的临时数据,会保存在tmp文件中,这部分也是存在容器的可写存中,随着容器的删除它也会被删除

 卷的种类

Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同

1、Bind mount volume【绑定挂载卷】: 容器的挂载目录与宿主机的目录建立关联关系,绑定的卷

2、Docker -- managed volume【Docker 管理的卷】: 容器的挂载目录被绑定的宿主机的那个目录无需关心,由容器Docker引擎Dockers damon自行创建/或使用一个已经存在的目录,与容器挂载的目录建立关联关系【如果容器删除的话,需要收到进行绑定,不然它又会自动给你初始化一个目录卷】

创建逻辑卷

Docker-managed volume创建

[root@localhost ~]# docker run --name b2 -v /data -it 16ea53ea7c65 【会生成data目录】

 [root@localhost ~]# docker inspect b2   【查看逻辑卷】

[root@localhost ~]#  cd  /var/lib/docker/volumes/4bb95bfdbf1325787214043b24f31d7e09ada491e58ca7123cba93598f5d7d5c/_data/    【切换到宿主机的目录中】

[root@localhost _data]# touch a.txt   【船舰目录】

查看容器的data目录

 Bind mount volume 创建

[root@localhost data]# docker run -it --name b2 -v /data/volumes/b2:/data --rm busybox 【创建命令】
[root@localhost _data]# cd /data/volumes/b2/
[root@localhost b2]# touch b.txt
登录容器查看

使用go模板过滤insepct中的信息

[root@localhost b2]# docker inspect -f {{.Mounts}} b2 

 2个容器共享容器卷

既然一个容器使用宿主机上的逻辑卷,那另外的容器也可以使用挂载这一个容器,也就可以是想共享数据卷,直接让他们共享文件系统还是有难度的

既然可以2个容器共享存储卷,那个多个容器也就可以共享存储卷,多个容器共享存储卷,如果记不住需要共享的逻辑卷地址?实际也可以给我提供了,可以直接复制对应的容器的存储卷路径【该容器只要存在即可】

这样我们就可以搭建起来简单的架构,Nginx,Tomcat,Mysql都共享同一个宿主机的物理卷;Nginx对外提供服务【反代理到Tomcat】,Tomcat只服务【只需要监听在LO上】于Nginx,Mysql只服务于Tomcat,他们使用相同网络空间

 

创建共享存储卷并加入基础镜像的网络

[root@localhost b2]# docker run --name nginx --network container:infracon --volumes-from infracon -it busybox

 

推荐阅读