Docker 镜像读写层核心概念:rootfs、Union mount、image以及layser原理详解

Docker 镜像读写层核心概念:rootfs、Union mount、image以及layser原理详解

文章目录

  • Docker 镜像读写层核心概念:rootfs、Union mount、image以及layser原理详解
    • rootfs
    • Union mount
      • 为什么镜像层都是只读的
      • 去掉读写层的话会有什么问题
    • Docker镜像image
    • Docker镜像层layer
    • Docker 镜像下载
    • Docker 镜像存储

rootfs

Rootfs: 代表一个 Docker Container 在启动时(而非运行后)其内部进程可见的文件系统视角,或者是 Docker Container 的根目录。当然,该目录下含有 Docker Container 所需要的系统文件、工具、容器文件等。

在这里插入图片描述

上面这张图展示了Linux系统中的两个重要的文件系统。

  • bootfs 是指 Linux 系统启动时使用的文件系统,**通常包含操作系统内核、启动加载程序和其他引导文件。**Linux 刚启动时会加载 bootfs 文件系统,在Docker 镜像的最底层是引导文件系统 bootfs。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器和内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
  • rootfs 是指 Linux 系统的根文件系统,是系统的主要文件系统,包含所有的文件和目录,比如典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件rootfs 是一个虚拟的文件系统,它由内核挂载并提供给用户空间。在 Linux 系统启动时,内核会将 rootfs 挂载为根文件系统,并将其作为所有其他文件系统的基础。

在Docker镜像中,镜像是由不同的镜像层堆叠而成的,我们常说镜像层都是只读的,容器层是可写的。当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层中。

在这里插入图片描述

如何理解这句话,背后的原理是什么呢?为什么要这样设计的呢?

传统来说,Linux 操作系统内核启动时,内核首先会挂载一个只读(read-only)的 rootfs,当系统检测其完整性之后,决定是否将其切换为读写(read-write)模式,或者最后在 rootfs 之上另行挂载一种文件系统并忽略 rootfs。 Docker 架构下,依然沿用 Linux 中 rootfs 的思想。当 Docker Daemon 为 Docker Container 挂载 rootfs 的时候,与传统 Linux 内核类似,将其设定为只读(read-only)模式。在 rootfs 挂载完毕之后,和 Linux 内核不一样的是,Docker Daemon 没有将 Docker Container 的文件系统设为读写(read-write)模式,而是利用 Union mount 的技术,在这个只读的 rootfs 之上再挂载一个读写(read-write)的文件系统,挂载时该读写(read-write)文件系统内空无一物。

在这里插入图片描述

正如 read-only 和 read-write 的含义那样,该容器中的进程对 rootfs 中的内容只拥有读权限,对于 read-write 读写文件系统中的内容既拥有读权限也拥有写权限。容器虽然只有一个文件系统,但该文件系统由“两层”组成,分别为读写文件系统和只读文件系统。

Union mount

Union mount: 代表一种文件系统挂载的方式,允许同一时刻多种文件系统挂载在一起,并以一种文件系统的形式,呈现多种文件系统内容合并后的目录。

一般情况下,通过某种文件系统挂载内容至挂载点的话,挂载点目录中原先的内容将会被隐藏。而 Union mount 则不会将挂载点目录中的内容隐藏,反而是将挂载点目录中的内容和被挂载的内容合并,并为合并后的内容提供一个统一独立的文件系统视角。 通常来讲,被合并的文件系统中只有一个会以读写(read-write)模式挂载,而其他的文件系统的挂载模式均为只读(read-only)。 实现这种 Union mount 技术的文件系统一般被称为 Union Filesystem,较为常见的有 UnionFS、AUFS、OverlayFS 等。

在这里插入图片描述

假设,在我们使用镜像 ubuntu 创建的容器中,可以暂且将该容器整个 rootfs 当成是一个文件系统。上文也提到,挂载时读写(read-write)文件系统中空无一物。既然如此,从用户视角来看,容器内文件系统和 rootfs 完全一样,用户完全可以按照往常习惯,无差别的使用自身视角下文件系统中的所有内容;然而,从内核的角度来看,两者在有着非常大的区别。追溯区别存在的根本原因,那就不得不提及 AUFS 等文件系统的 COW(copy-on-write)特性。

COW 文件系统和其他文件系统最大的区别就是:从不覆写已有文件系统中已有的内容。 由于通过 COW 文件系统将两个文件系统(rootfs 和 read-write filesystem)合并,最终用户视角为合并后的含有所有内容的文件系统,然而在 Linux 内核逻辑上依然可以区别两者,那就是用户对原先 rootfs 中的内容拥有只读权限,而对 read-write filesystem 中的内容拥有读写权限。

既然对用户而言,全然不知哪些内容只读,哪些内容可读写,这些信息只有内核在接管,那么假设用户需要更新其视角下的文件 /etc/hosts,而该文件又恰巧是 rootfs 只读文件系统中的内容,内核是否会抛出异常或者驳回用户请求呢?答案是否定的。当此情形发生时,COW 文件系统首先不会覆写 read-only 文件系统中的文件,即不会覆写 rootfs 中 /etc/hosts,其次反而会将该文件拷贝至读写文件系统中,即拷贝至读写文件系统中的 /etc/hosts,最后再对后者进行更新操作。 如此一来,纵使 rootfs 与 read-write filesystem 中均由 /etc/hosts,诸如 AUFS 类型的 COW 文件系统也能保证用户视角中只能看到 read-write filesystem 中的 /etc/hosts,即更新后的内容。

当然,这样的特性同样支持 rootfs 中文件的删除等其他操作。例如:用户通过 apt-get 软件包管理工具安装 Golang,所有与 Golang 相关的内容都会被安装在读写文件系统中,而不会安装在 rootfs。此时用户又希望通过 apt-get 软件包管理工具删除所有关于 MySQL 的内容,恰巧这部分内容又都存在于 rootfs 中时,删除操作执行时同样不会删除 rootfs 实际存在的 MySQL,而是在 read-write filesystem 中删除该部分内容,导致最终 rootfs 中的 MySQL 对容器用户不可见,也不可访。

了解了上面容器启动时的rootfs和文件挂载方式,我们不禁要发出疑问,即为什么docker要将容器这样设计?在只读层上添加一个读写层的意义在哪儿?去掉读写层的话会有什么问题?

为什么镜像层都是只读的

  1. 在Docker镜像的设计中,一个镜像是由多个镜像层堆叠而成的。这样设计的好处是之一是有利于镜像层的复用,从而节省存储空间。而可复用就要保证某个镜像的容器在运行中,对该镜像层是不能修改的,也就是只有当镜像层是只读的条件时,才能保证多个容器可以同享某些镜像层。
  2. 提高应用程序的可移植性。由于容器层是可写的,容器中的应用程序可以在容器内部进行读写操作,而不会影响到宿主机的文件系统。这样就可以使应用程序更加容易地移植到不同的环境中。

去掉读写层的话会有什么问题

如果在没有可写层的情况下,那么容器对内部文件的任何更改操作都会直接影响到底层镜像层的内容。举个例子来说,假设我们有一个基于Ubuntu操作系统的Docker镜像,并且该镜像中已经包含了一个名为/etc/nginx/nginx.conf的Nginx配置文件。现在,我们使用该镜像启动了一个容器,并在容器中修改了/etc/nginx/nginx.conf文件,将默认的Nginx欢迎页面修改为自定义的欢迎页面。如果这个容器使用的是没有可写层的配置,那么对/etc/nginx/nginx.conf文件的修改会直接影响到镜像层中的该文件,从而影响到所有基于该镜像构建的容器。也就是说,所有从这个镜像启动的容器都将使用这个自定义的欢迎页面。

这种情况下,如果仍然将镜像层共享复用的话,就会导致以该本地nginx镜像层为基础创建的其他容器下的/etc/nginx/nginx.conf也被修改为自定义的欢迎页,从而对其他镜像造成了影响。

为此,为了避免容器对镜像层内容的影响,通常都会使用可写层。可写层提供了一个可写的文件系统,容器中的任何更改都会被记录在可写层中,而不会直接影响到镜像层的内容。这种设计可以实现容器与镜像的分离,容器层中的任何更改都不会影响到原始镜像的内容。

掌握 Docker 中 rootfs 以及 Union mount 的概念之后,再来理解 Docker 镜像,就会变得水到渠成。

Docker镜像image

Docker 中 rootfs 的概念,起到容器文件系统中基石的作用。对于容器而言,其只读的特性,也是不难理解。神奇的是,实际情况下 Docker 的 rootfs 设计与实现比上文的描述还要精妙不少。

继续以 ubuntu 为例,虽然通过 AUFS 可以实现 rootfs 与 read-write filesystem 的合并,但是考虑到 rootfs 自身接近 200MB 的磁盘大小,如果以这个 rootfs 的粒度来实现容器的创建与迁移等,是否会稍显笨重,同时也会大大降低镜像的灵活性。而且,若用户希望拥有一个 ubuntu 的 rootfs,那么是否有必要创建一个全新的 rootfs,毕竟 ubuntu 和 ubuntu 的 rootfs 中有很多一致的内容。

Docker 中 image 的概念,非常巧妙的解决了以上的问题。最为简单的解释 image,就是 Docker 容器中只读文件系统 rootfs 的一部分。换言之,实际上 Docker 容器的 rootfs 可以由多个 image 来构成。多个 image 构成 rootfs 的方式依然沿用 Union mount 技术。

在这里插入图片描述

多个 Image 构成 rootfs 的示意图。图中,rootfs 中每一层 image 中的内容划分只为了阐述清楚 rootfs 由多个 image 构成,并不代表实际情况中 rootfs 中的内容划分。

从上图可以看出,举例的容器 rootfs 包含 4 个 image,其中每个 image 中都有一些用户视角文件系统中的一部分内容。4 个 image 处于层叠的关系,除了最底层的 image,每一层的 image 都叠加在另一个 image 之上。另外,每一个 image 均含有一个 image ID,用以唯一的标记该 image。

基于以上的概念,Docker Image 中又抽象出两种概念:Parent Image 以及 Base Image。除了容器 rootfs 最底层的 image,其余 image 都依赖于其底下的一个或多个 image,而 Docker 中将下一层的 image 称为上一层 image 的 Parent Image。imageID_0 是 imageID_1 的 Parent Image,imageID_2 是 imageID_3 的 Parent Image,而 imageID_0 没有 Parent Image。对于最下层的 image,即没有 Parent Image 的镜像,在 Docker 中习惯称之为 Base Image。

通过 image 的形式,原先较为臃肿的 rootfs 被逐渐打散成轻便的多层。Image 除了轻便的特性,同时还有上文提到的只读特性,如此一来,在不同的容器、不同的 rootfs 中 image 完全可以用来复用。

多 image 组织关系与复用关系如图下图(图中镜像名称的举例只为将 image 之间的关系阐述清楚,并不代表实际情况中相应名称 image 之间的关系):

在这里插入图片描述

Docker镜像层layer

Docker 术语中,layer 是一个与 image 含义较为相近的词。容器镜像的 rootfs 是容器只读的文件系统,rootfs 又是由多个只读的 image 构成。于是,rootfs 中每个只读的 image 都可以称为一层 layer。

除了只读的 image 之外,Docker Daemon 在创建容器时会在容器的 rootfs 之上,再 mount 一层 read-write filesystem,而这一层文件系统,也称为容器的一层 layer,常被称为 top layer。

因此,总结而言,Docker 容器中的每一层只读的 image,以及最上层可读写的文件系统,均被称为 layer。如此一来,layer 的范畴比 image 多了一层,即多包含了最上层的 read-write filesystem。

有了 layer 的概念,大家可以思考这样一个问题:容器文件系统分为只读的 rootfs,以及可读写的 top layer,那么容器运行时若在 top layer 中写入了内容,那这些内容是否可以持久化,并且也被其它容器复用?

上文对于 image 的分析中,提到了 image 有复用的特性,既然如此,再提一个更为大胆的假设:容器的 top layer 是否可以转变为 image?

答案是肯定的。Docker 的设计理念中,top layer 转变为 image 的行为(Docker 中称为 commit 操作),大大释放了容器 rootfs 的灵活性。Docker 的开发者完全可以基于某个镜像创建容器做开发工作并且无论在开发周期的哪个时间点,都可以对容器进行 commit,将所有 top layer 中的内容打包为一个 image,构成一个新的镜像。 Commit 完毕之后,用户完全可以基于新的镜像,进行开发、分发、测试、部署等。不仅 docker commit 的原理如此,基于 Dockerfile 的 docker build,其核心的思想,也是不断将容器的 top layer 转化为 image。

Docker 镜像下载

Docker Image 作为 Docker 生态中的精髓,下载过程中需要 Docker 架构中多个组件的协作。Docker 镜像的下载流程如图:

在这里插入图片描述

1、docker client发送镜像的tag到registry。
2、registry根据镜像tag,得到镜像的manifest文件,返回给docker client。
3、docker client拿到manifest文件后,根据其中的config的digest,也就是image ID,检查下镜像在本地是否存在。
4、如果镜像不存在,则下载config文件,并根据config文件中的diff_ids得到镜像每一层解压后的digest。
5、然后根据每层解压后的digest文件,检查本地是否存在,如果不存在,则通过manifest文件中的6、layer的digest下载该层并解压,然后校验解压后digest是否匹配。
7、下载完所有层后,镜像就下载完毕。

Docker 镜像存储

Docker Daemon 执行镜像下载任务时,从 Docker Registry 处下载指定镜像之后,仍需要将镜像合理地存储于宿主机的文件系统中。更为具体而言,存储工作分为两个部分:

(1) 存储镜像内容;

(2) 在 graph 中注册镜像信息。

说到镜像内容,需要强调的是,每一层 layer 的 Docker Image 内容都可以认为有两个部分组成镜像中每一层 layer 中存储的文件系统内容,这部分内容一般可以认为是未来 Docker 容器的静态文件内容;另一部分内容指的是容器的 json 文件,json 文件代表的信息除了容器的基本属性信息之外,还包括未来容器运行时的动态信息,包括 ENV 等信息。

存储镜像内容,意味着 Docker Daemon 所在宿主机上已经存在镜像的所有内容,除此之外,Docker Daemon 仍需要对所存储的镜像进行统计备案,以便用户在后续的镜像管理与使用过程中,可以有据可循。为此,Docker Daemon 设计了 graph,使用 graph 来接管这部分的工作。graph 负责记录有哪些镜像已经被正确存储,供 Docker Daemon 调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/121022.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AcWing 1.2.1 最长上升子序列模型 + 动态规划 + 图解(详细)

(1)acwing 4557. 最长上升子序列 4557. 最长上升子序列 - AcWing题库 给定一个长度为 N 的整数序列 a1,a2,…,aN。请你计算该序列的最长上升子序列的长度。上升子序列是指数值严格单调递增的子序列 输入格式 第一行包含整数 N第二行包含 N个整数 a1,a…

大语言模型(LLM)综述(四):如何适应预训练后的大语言模型

A Survey of Large Language Models 前言5. ADAPTATION OF LLMS5.1 指导调优5.1.1 格式化实例构建5.1.2 指导调优策略5.1.3 指导调优的效果5.1.4 指导调优的实证分析 5.2 对齐调优5.2.1 Alignment的背景和标准5.2.2 收集人类反馈5.2.3 根据人类反馈进行强化学习5.2.4 无需 RLHF…

一个比较特别的串口工具

这是08年写的一个 并网带电池逆变器 的通讯工具,和普通的串口调试器相比,多了一个【脚本】功能。能够通过【脚本】完成通讯测试。 PC发给DSP的01命令 01 10 1B 00 CF A3 00 00 90 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 电…

小程序开发——小程序的事件

1.事件对象 事件与事件对象概述 事件是一种用户行为,用户的点击、滑动等操作都可以成为事件。事件也是一种通信方式,能够完成视图层(WXML页面文件)与逻辑层(JS逻辑文件)之间的通信。 事件对象是指用户在点…

uniapp开发app,在ios真机上出现的css样式问题

比如下面的问题,在iphone 13上出现,在iphone xR上正常。 问题一:border:1rpx造成边框显示不全 在iphone13上border边框有一部分不显示: 在iphone xR上显示正常: 解决办法是: 将border边框设置中的1rpx改…

分享一款基于 AI 的 Chrome 插件

最近使用大模型比较多,公司虽然提供了免费的 ChatGPT 但是需要跳转特定页面才能访问,比较麻烦,于是就想到是否可以开发一款类似于有道词典一样的 Chrome 插件,可以在任意页面使用,虽然市面上也有类似的插件&#xff0c…

【ROS入门】机器人系统仿真——URDF集成Gazebo

文章结构 URDF与Gazebo基本集成流程创建功能包编写URDF或Xacro文件启动 Gazebo 并显示机器人模型 URDF集成Gazebo相关设置collisioninertial颜色设置 URDF集成Gazebo实操编写封装惯性矩阵算法的 xacro 文件复制相关 xacro 文件,并设置 collision inertial 以及 colo…

一文搞懂 MineCraft 服务器启动操作和常见问题 2023年10月

文章目录 前言1. 新建文件夹2. 创建 bat 文件3. 编辑 bat 文件4. 启动服务器5. 恭喜完成 文章持续更新中,如果你有问题可以通过 qq 1317699264 获取免费协助,解决的问题将会被更新到本文章中 前言 无论你是使用服务端整合包,还是从上一篇我的…

【开源】基于SpringBoot的天然气工程业务管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四、数据库设计4.1 用户表4.2 分公司表4.3 角色表4.4 数据字典表4.5 工程项目表4.6 使用材料表4.7 使用材料领用表4.8 整体E-R图 五、系统展示六、核心代码6.1 查询工程项目6.2 工程物资…

通过el-tree 懒加载树,创建国家地区四级树

全国四级行政地区树数据库sql下载路径:【免费】全国四级地区(省市县)数据表sql资源-CSDN文库https://download.csdn.net/download/weixin_51722520/88469807?spm1001.2014.3001.5503 我在后台获取地区信息添加了限制,只获取parentid为当前的地…

LeetCode题:70爬楼梯,126斐波那契数

目录 70:爬楼梯 题目要求: 解题思路:(类似斐波那契数) 递归解法: 非递归解法: 126:斐波那契数 题目要求: 解题思路: 递归解法: 非递归解…

python—openpyxl操作excel详解

前言 openpyxl属于第三方模块,在python中用来处理excel文件。 可以对excel进行的操作有:读写、修改、调整样式及插入图片等。 但只能用来处理【 .xlsx】 后缀的excel文件。 使用前需要先安装,安装方法: pip install openpyxl…

Doceker-compose——容器群集编排管理工具

目录 Docker-compose 1、Docker-compose 的三大概念 2、YAML文件格式及编写注意事项 1)使用 YAML 时需要注意下面事项 2)ymal文件格式 3)json格式 3、Docker Compose配置常用字段 4、Docker-compose的四种重启策略 5、Docker Compos…

k8s statefulSet 学习笔记

文章目录 缩写: stsweb-sts.yaml创建sts扩缩容金丝雀发布OnDelete 删除时更新 缩写: sts 通过 kubectl api-resources 可以查到: NAMESHORTNAMESAPIVERSIONNAMESPACEDKINDstatefulsetsstsapps/v1trueStatefulSet web-sts.yaml apiVersion: v1 kind: Service met…

Canal整合SpringBoot详解(一)

文章目录 Canal整合SpringBoot详解(一)什么是canal搭建Kafka3.2.1集群⭐Kafka集群机器规划创建3台虚拟机(centos7系统)必要的环境准备(3台虚拟机都要执行如下操作)⭐分别修改每个服务器的hosts文件&#xf…

docker - window Docker Desktop升级

文章目录 前言docker - window Docker Desktop升级 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来…

【python画画】蘑菇云爱心

来源于网上短视频 数学原理不懂,图个乐 import math from turtle import *def x(i):return 15 * math.sin(i) ** 3 * 20def y(i):return 20 * (12 * math.cos(i) - 5 * math.cos(2 * i) - 2 * math.cos(4 * i))speed(0) color(red) pensize(10) for i in range(51…

C++设计模式_14_Facade门面模式

本篇介绍的Facade门面模式属于“接口隔离”模式的一种,以下进行详细介绍。 文章目录 1. “接口隔离”模式1. 1 典型模式 2. 系统间耦合的复杂度3. 动机(Motivation)4. 模式定义5. Facade门面模式的代码实现6. 结构7. 要点总结8. 其他参考 1. “接口隔离”模式 在组…

笔记44:Batch_Normlization 过程详解

笔记本地地址:D:\work_file\DeepLearning_Learning\03_个人笔记\2.图像处理任务\BN a a a a a a a a a a a a a a a a a

抖音上怎么挂小程序?制作小程序挂载抖音视频

公司企业商家现在已经把抖音作为营销的渠道之一,目前抖音支持短视频挂载小程序,可方便做营销。以下给大家分享这一操作流程。 一、申请自主挂载能力 首先需要在抖音开放平台官网注册一个抖音小程序账号,然后申请短视频自主挂载能力。 二、搭…