【docker系列】镜像分层原理及容器层写时复制

举报
字母哥哥 发表于 2022/04/14 01:59:51 2022/04/14
【摘要】 文章目录 一、镜像分层与容器层二、为什么会产生分层?三、什么是写时复制? 一、镜像分层与容器层 在进行docker pull 下载镜像的时候,通过下面的脚本运行过程可以看到镜像是分层下...

一、镜像分层与容器层

在进行docker pull 下载镜像的时候,通过下面的脚本运行过程可以看到镜像是分层下载并解压的。如nginx:1.20.2的镜像,其镜像是分为6层。下文中以<一串数字>:Pull Complete表示完成一个镜像层的下载和解压,一共是6个分层。

# docker pull nginx:1.20.2
1.20.2: Pulling from library/nginx
c229119241af: Already exists 
2906ff8f593b: Pull complete 
605202120923: Pull complete 
b0013ba53a96: Pull complete 
f2e7470d98f2: Pull complete 
8da6a894027c: Pull complete

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

当我们运行一个新的容器的时候,实际上是在镜像分层的基础上新添加了一层:container layer(容器层)。之后所有容器运行时对文件系统产生的修改实际都只影响这一层。并且针对这一层所作的修改(写操作),在容器重启之后会全部丢失。所以说在使用docker的过程中,在需要修改运行时容器文件数据的时候,尽量去重新构建镜像而不是直接修改容器内文件。如果重构镜像解决不了的问题,使用数据卷。

构建镜像的方法是通过Dockerfile定义,数据卷的使用详解,专栏后续文章笔者会详细介绍。

在这里插入图片描述

注意 :对于运行时的容器而言,镜像层只读的,容器层可读也可写。对于镜像层的只读文件,容器层如果想做修改,实际上是进行了写时复制操作。(下文介绍)。

二、为什么会产生分层?

通过上文的介绍,我们已经知道镜像是分层的,那么镜像分层的依据是什么?或者说构建镜像的时候究竟是什么动作产生了分层?我们来看下面的这张图,使用docker history查看镜像的构建历史。

注意上图中红色边框的部分,我们可以看到:在进行ADD、COPY、执行shell脚本等操作的时候操作步骤对应的SIZE不等于0,正好是6个操作,和我们上文中nginx:1.20.2镜像分层的数量是一样的。所以我们可以做一个大胆的猜想:在镜像构建过程中需要向镜像写入数据的时候会产生分层,一个写操作指令产生一个分层。 大家可以自己去观察更多的镜像去验证这个猜想。笔者要说的是:我读过Dokcer的源码,所以这是一个可以被信任的结论。

FROM debian:bullseye-slim  #写指令

LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
ENV NGINX_VERSION   1.20.2
ENV NJS_VERSION     0.7.0
ENV PKG_RELEASE     1~bullseye

#写指令
RUN set -x \    #这里省略若干行shell脚本

COPY docker-entrypoint.sh /   #写指令
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d  #写指令
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d  #写指令
COPY 30-tune-worker-processes.sh /docker-entrypoint.d  #写指令
ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

上面的这段代码是nginx:1.20.2的Dockerfile(镜像构建过程定义文档),也就是构建nginx:1.20.2镜像的构建步骤定义文档(官方)。其中FROM(ADD)指令–添加基础镜像或文件、RUN指令–执行命令行脚本、COPY指令–文件复制,这些都是写操作命令,都会产生新的镜像分层。

三、什么是写时复制?

上文中我们提到了一个概念:写时复制。这个概念如果用专业名词的方式说明还是比较难以理解,所以我用白话的方式说明一下。举个例子:

  • 一个授课老师写了一本练习册(原始镜像)。
  • 然后老师留作业了,练习册第12页。全班同学把练习册的第12页全都复印了一份,带回家做作业。

在这里插入图片描述
老师的练习册是原始文稿(正本)(原始文稿构建之后就只读不写,镜像层文件也是),同学们的练习册是在需要使用到的时候复印出来的,并在复印本(副本)上完成作业书写,不影响原来老师那本练习册(正本)的内容。这个就是典型的“写时复制”。
对于容器而言,复制出来的文件在面向容器内的运行时软件时,会覆盖原始镜像文件(对于学生而言也只看自己复制出来那份–不要抬杠:抄作业的除外,不看老师的原始文件)。也就是说发生写时复制之后原始镜像文件被隐藏,容器读写操作都只认复制出来的副本文件。注意:该副本文件存在于容器层,容器重启之后容器层重新建立,上一次容器运行时对于文件的修改全部丢失!

文章来源: zimug.blog.csdn.net,作者:字母哥哥,版权归原作者所有,如需转载,请联系作者。

原文链接:zimug.blog.csdn.net/article/details/124054888

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。