当前位置: 首页 > 后端技术 > Java

镜像分层原理与容器层copy-on-write

时间:2023-04-01 16:15:45 Java

1.镜像分层与容器层执行dockerpull下载镜像时,可以看到镜像是逐层下载解压的,如下图所示。比如nginx:1.20.2的镜像分为6层。当我们运行一个新的容器时,实际上是在镜像层的基础上增加了一个新的层:容器层(containerlayer)。容器运行时对文件系统的所有后续修改实际上只影响这一层。并且所有对该层的修改(写操作)在容器重启后都会丢失。所以在使用docker的过程中,当需要修改运行时容器文件数据时,尽量重建镜像,而不是直接修改容器中的文件。如果重构图像不能解决问题,请使用数据卷。通过Dockerfile定义了构建镜像的方法,并详细说明了数据卷的使用。笔者将在专栏后续文章中详细介绍。注意:对于运行时容器,镜像层是只读的,容器层是可读可写的。对于镜像层中的只读文件,如果容器层要修改它们,实际上是进行了写时复制操作。(如下面所描述的)。第二,为什么会出现分层?通过上面的介绍,我们已经知道镜像是分层的,那么镜像分层的依据是什么呢?或者在构建图像时创建分层的动作到底是什么?我们看下图,使用dockerhistory查看镜像的构建历史。注意上图中红色边框的部分,我们可以看到:在进行ADD、COPY等操作、执行shell脚本时,操作步长对应的SIZE不等于0,恰好是6次操作,这与我们上面的nginx:1.20相同。2镜像层数相同。所以我们可以大胆猜测:在镜像构建过程中,当需要向镜像写入数据时,会生成一个层,一条写操作指令会生成一个层。大家可以自己观察更多的图片来验证这个猜想。我想说的是:我看过Dokcer的源码,所以这是一个可以相信的结论。上图是nginx:1.20.2的Dockerfile(镜像构建过程定义文件),是构建nginx:1.20.2镜像的构建步骤定义文件(官方)。其中FROM(ADD)命令--添加一个基础镜像或文件,RUN命令--执行一个命令行脚本,COPY命令--文件复制,这些都是写操作命令,会生成一个新的镜像层。3.什么是写时复制?上面我们提到了一个概念:copy-on-write。这个概念如果用专业术语解释还是很难理解,所以我就用大白话解释一下。例如:老师写了一本练习册(原版镜像)。然后老师留下作业,练习册第12页。全班同学复印了练习册的第12页,带回家做作业。老师的练习本是原稿(original)(原稿构建后只能读不能写,镜像层文件也一样),学生的练习本需要的时候复印在不影响原教师作业本(原件)内容的情况下,在电脑上完成作业写作。这是典型的“写时复制”。对于容器来说,当复制的文件面对容器中的运行时软件时,会覆盖掉原来的镜像文件(对于学生来说,只需要看自己复制的副本即可——别开玩笑:除了抄作业,别看老师原档)。也就是说,发生copy-on-write后,原始镜像文件被隐藏,容器的读写操作只识别复制的copy文件。注意:这个副本文件存在于容器层。容器重启后,重新建立容器层。上次容器运行期间对文件的所有修改都将丢失!欢迎关注我的博客,本文转载更多优质知识合集,注明出处(一定要有链接,不能只是文字):字母哥博客-zimug.com如果觉得对你有帮助,请点赞分享!您的支持是我创作不竭的动力!.另外,作者近期输出了以下优质内容,期待大家的关注。《kafka修炼之道》《手摸手教你学Spring Boot2.0》《Spring Security-JWT-OAuth2一本通》《实战前后端分离RBAC权限管理系统》《实战SpringCloud微服务从青铜到王者》