Docker:存储原理
Docker:存储原理
- 镜像
- 联合文件系统
- overlay
- 镜像存储结构
- 容器存储结构
- 存储卷
- 绑定挂载
- 存储卷结构
镜像
联合文件系统
联合文件系统Union File System
是一种分层,轻量且高效的文件系统。其将整个文件系统分为多个层,层与层之间进行覆盖,并对外表现为一个一致的文件系统。
上图有三种操作,A(add)
表示新建文件,C(change)
表示修改文件,D(delete)
表示删除文件。这个文件系统分为三层,但是对外用户只能看到红色这一层。
比如a.txt
,在第二层就被删除了,那么用户看不到这个文件,但是其实这个文件依然被存储在文件系统的第一层中。删除文件只是一种标记,表示上层不可见,不会真的删除文件。
再比如b.txt
,在第一层创建,在第二层修改,那么第二层的内容就会覆盖掉第一层的内容,用户看到第二层的内容。但是对于b.txt
,其实保存了两份在文件系统中,第一份在第一层,第二份在第二层。
在红色层,其实是没有存储任何具体的文件的,而是存储了大量文件的引用。比如访问c.txt
,其实访问到的是第二层中的文件,其并没有把文件系统内部的文件再进行一次拷贝。但是如果用户要修改文件,此时触发写时拷贝
,那么会把该文件拷贝一份到当前层,然后再修改。比如b.txt
在第二层进行了修改,其实就是把第一层的文件拷贝一份到第二层,然后再进行修改。所以先前才说b.txt
在文件系统中保存了两份。
overlay
overlay
是联合文件系统的一种具体实现,其也是Docker
采用的联合系统方案。
overlay
采用三层结构,每一层由一个目录管理。从下往上依次是:
lowerdir
:最底层,内部的所有文件都是只读文件upperdir
:中间层,可以读写,可以在该层创建,删除,修改文件merged
:最顶层,也就是用户所看到的层,其基于前两层提供一个统一的视图
除去这三个层,还有一个workdir
层,这层并不展示给用户,当upperdir
层要修改文件时,会先在workdir
层进行修改,只有操作完成后,才会同步到upperdir
层。
- 读取文件: 用户读取文件时,可以同时看到
upperdir
或者lowerdir
层,只要文件没有被覆盖,就可以被读取到 - 写入文件:如果文件在
upperdir
层,直接进行修改,如果文件在lowerdir
层,发生写时拷贝,将文件拷贝到upperdir
层再修改 - 删除文件:如果文件在
upperdir
层,那么直接删除文件,如果文件在lowerdir
层,不会删除文件,而是标记为不可见
对于大部分Linux
系统,都是自带overlay
文件系统的,可以基于mount
命令模拟一下overlay
文件系统。
- 创建四个目录,表示不同层
在overlay
中,其实一层就是一个目录,创建四个目录,后续在这四个目录上创建一个overlay
文件系统。
- 写入文件
往lower
和upper
目录中写入一些文件,low.txt
只在lower
层出现,up.txt
只在upper
层出现,both.txt
在两个层都出现。
- 创建文件系统
mount -t overlay overlay
-o lowerdir=./lower,upperdir=./upper,workdir=./work ./merged
这个命令,会创建一个overlay
文件系统,-t overlay
表示文件系统类型,第二个overlay
是一个应用程序,表示用这个程序来操控文件系统。
-o
指定文件系统的相关参数,用,
逗号分隔,可以看出分别代表lowerdir
、upperdir
、workdir
三个层。
最后的./merged
不是-o
的参数,这是挂载点,表示用户最后通过./merged
目录访问整个文件系统。
执行命令挂载成功后,./merged
就被初始化了,其可以看到low.txt
、up.txt
、both.txt
。
此处merged
目录中,所有文件都是一个引用,文件都存储在lower
和upper
中。这可以通过查询inode
来证明,如果两个文件的inode
一样,那么在硬盘中指向的就是同一块空间,通过ls
的-i
参数。
查询merge
和upper
的up.txt
文件,第一栏都是562812
,也就是说两者inode
相同,就是同一个文件。
借此,可以查看merge/both.txt
使用的哪一层的内容:
可以看到merge/both.txt
和upper/both.txt
的inode = 562810
,相同的,也就是说lower
层的both.txt
被覆盖了,用户看不到这层的both.txt
。
- 修改
merged/low.txt
:
此时不仅仅是merged
内部的low.txt
改变了,而upper
层多出一个low.txt
,这是因为写时拷贝。如果修改的文件在lower
层,会把文件拷贝到upper
层再修改,不会影响原文件。
因此后续cat
输出文件内容时,可以看到upper/low.txt
是最新写入的内容,而lower/low.txt
是一个空文件。
- 删除
merge/low.txt
:
删除文件后,lower
层内部的文件还在,在upper
目录下,多出一个low.txt
,work
也多出一个新内容。
看看多出的upper/low.txt
:
其权限为c---------
,也就是没有任何权限,这就是一个删除标记,表示这个文件虽然在lower
中存在,但是已经被标记为删除了,所以用户看不到这个文件。
- 删除
merge/up.txt
:
此时这个up.txt
真的就被删除了,没有任何标记,因为upper
层本身就是可以读写的,删除文件 并不会被标记。
实验完毕,可以通过umount
卸载这个文件系统:
umount 挂载路径
那么这个联合文件系统,到底和Docker
什么关系?
其实Docker
就是使用的overlay
结构存储文件,镜像层就是lowerdir
层,容器层就是upperdir
层,用户看到的是merged
层。
一个镜像可以实例化为多个容器,就是因为所有容器都共用一个lowerdir
层,因为这个层只读,不会修改镜像的内容,任何容器做的所有修改,都在自己的upperdir
中。
镜像存储结构
docker inspect centos
查看一个centos
镜像的详细信息:
可以看到,在GraphDriver
中,包含了三个熟悉的目录,MergedDir
、UpperDir
、WorkDir
,并且使用的文件系统为overlay2
。
查看这个UpperDir
的内容:
这就是操作系统的根目录!所以每当创建一个centos
容器时,看到的就是这个目录,让用户感觉自己处于一个新的操作系统中。
由于centos
镜像,本身就是一个非常底层的镜像,所以它没有lowerDir
,此时可以基于centos
镜像再创建一个镜像:
以上操作,创建了一个centos
容器,然后进去创建了三个文件,退出后通过commit
创建了一个test:v1
镜像。
docker inspect test:v1
查看这个镜像的信息:
这个新建的镜像,就有LowerDir
了,查看LowerDir
的内容,其实就是centos
镜像的内容,说明新的镜像把老的镜像作为了基底。
而在UpperDir
中,是之前在容器内部创建的三个文件。
容器存储结构
刚才发现,在一个镜像内部,有upperdir
层,lowerdir
层,那么容器层去哪里了,不是说upper
层是容器吗?为什么镜像也有upper
层?
把刚才的test:v1
镜像,实例化为一个容器:
docker run -d --name test test:v1
然后再查看容器的详细信息:
docker container inspect test
可以发现,容器也分为LowerDir
、UpperDir
等等内容,在LowerDir
,有很长一个路径,细看可以看出是由:
冒号分隔的三段路径:
/data/var/lib/docker/overlay2/9f8d970f2ece5d2ad7985cad1d12821e0c10355f60846ce5429207788b8b81ed-init/diff
/data/var/lib/docker/overlay2/20c74607fa2b73e5e419e6f2167e4220aa2b3f3e164cbaa928e8ed87421d3051/diff
/data/var/lib/docker/overlay2/ef10e4f37d8b8015c2319620bc8e391a824275741bc50e34bbf92392cb53c474/diff
依次输出这三段路径的内容:
熟悉的目录出现了,依次是centos
层,test:v1
新增的层,以及一个init
层。
原先镜像的所有层,在容器实例化后,都变成了容器的LowerDir
。
此处的init
层,内部包含两个目录dev
和etc
,这在centos
层中也有。其实这个init
层,是容器初始化时的层,因为初始化时修改了dev
和etc
,由于写时拷贝,会把文件拷贝到init
层再修改。
docker
通过overlay
来对容器分层,而镜像本身也被overlay
分层了,所以这里使用了两次联合文件系统。
对于容器来说,将镜像作为LowerDir
进行处理。而对于镜像来说,镜像本身的资源结构也被分层管理了,镜像的所有层,都作为容器的LowerDir
层。
存储卷
绑定挂载
存储卷是基于绑定挂载实现的,绑定挂载是Linux
中的一种挂载操作,它允许将一个文件或目录挂载到文件系统的另一个位置,从而在两个不同的路径下访问相同的文件或目录。这种挂载方式不会复制文件,而是创建一个指向原始文件或目录的引用。
可以使用mount
命令来执行绑定挂载:
mount --bind <source> <target>
source
:要挂载的原始文件或目录的路径target
:挂载点,即你希望文件或目录出现在的位置
要卸载绑定挂载,可以使用umount
命令:
umount 挂载点
这将卸载/mnt/data
的挂载点,但不会删除/data
目录或其内容。
试验一下:
首先创建两个目录,在第一个目录中有三个文件,第二个目录是一个空目录。
把dir2
绑定挂载到dir1
:
此时dir2
也出现了这三个文件,并且查询1.txt
,可以发现两个文件的inode
是一样的。
存储卷结构
Docker
的存储卷,就是使用了绑定挂载,把宿主机的文件,与容器内部的文件进行绑定,此时两个文件其实是同一个文件,互相操作都是可以看到的。
那么问题来了,容器是有文件系统隔离的,在mount --bind
时要指定两个文件,宿主机看不到容器内部的文件,容器内看不到宿主机的文件,如何才能mount --bind
同时指定处于不同环境下的两个文件?
其实这是不可行的,被文件隔离的两个环境,是无法mount --bind
绑定挂载两个文件的,因此要在容器创建后,文件隔离开启前,进行绑定挂载存储卷。
在容器创建后,会经过一段时间的初始化,文件隔离很早就会开启,但是开启文件隔离后,还要chroot
命令,容器与宿主机的文件系统才相互不可见。
所以要在执行chroot
命令之前,就进行绑定挂载:
顺便说一下,联合文件系统中,容器也是要访问宿主机中的镜像底层文件的,这也要在choroot
之前完成挂载,让容器可以看到宿主机中的镜像文件,这基于联合挂载
,是一种和绑定挂载不同的挂载方式,也是联合文件系统依赖的挂载方式。
联合挂载完毕后,就是存储卷的绑定挂载,最后执行chroot
,两个文件系统彻底隔离。
相关文章:

Docker:存储原理
Docker:存储原理 镜像联合文件系统overlay镜像存储结构容器存储结构 存储卷绑定挂载存储卷结构 镜像 联合文件系统 联合文件系统Union File System是一种分层,轻量且高效的文件系统。其将整个文件系统分为多个层,层与层之间进行覆盖&#x…...

ts:数组的常用方法(push、pop、shift、unshift、splice、slice)
前端css中filter的使用 一、主要内容说明二、例子(一)、push方法(尾添加)1.源码1 (push方法)2.源码1运行效果 (二)、pop方法(尾删除)1.源码2(pop方…...
物联网网关确保设备安全
物联网(IoT)网关在确保设备安全方面扮演着至关重要的角色。 作为连接物联网设备和云端或企业系统的中介,物联网网关可以实施多种安全措施来保护设备和数据。 是物联网网关确保设备安全的关键方法: 1. 设备认证和授权 认证&…...

Vue学习笔记(五)
Class绑定 数据绑定的一个常见需求场景式操纵元素的CSS class列表,因为class是attribute,我们可以和其他attribute一样使用v-bind将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此…...
Nestjs返回格式小结
在 NestJS 中,除了 text/event-stream(用于 Server-Sent Events)之外,还有多种格式的返回方式,具体取决于你的应用需求。以下是一些常见的返回格式及其示例: 1. JSON 格式 Get(json) getJsonResponse(Res…...

【力扣刷题实战】相同的树
大家好,我是小卡皮巴拉 文章目录 目录 力扣题目: 相同的树 题目描述 示例 1: 示例 2: 示例 3: 解题思路 题目理解 算法选择 具体思路 解题要点 完整代码(C语言) 兄弟们共勉 &#…...

Golang | Leetcode Golang题解之第515题在每个树行中找最大值
题目: 题解: func largestValues(root *TreeNode) (ans []int) {if root nil {return}q : []*TreeNode{root}for len(q) > 0 {maxVal : math.MinInt32tmp : qq nilfor _, node : range tmp {maxVal max(maxVal, node.Val)if node.Left ! nil {q …...

Zookeeper 对于 Kafka 的作用是什么?
大家好,我是锋哥。今天分享关于【Zookeeper 对于 Kafka 的作用是什么?】面试题?希望对大家有帮助; Zookeeper 对于 Kafka 的作用是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 ZooKeeper 在 Kafka…...

Thread类及线程的核心操作
一. Thread类的常见构造方法 1. Thread() Thread类无参的构造方法, 用于创建Thread类的实例对象. 2. Thread(String name) 带一个参数的Thread类构造方法, 创建一个线程对象, 并给其命名. [注]: 如果不专门给线程命名, 那么线程默认的名字就是Thread-0, Thread-1, Thread-…...

算法|牛客网华为机试11-20C++
牛客网华为机试 上篇:算法|牛客网华为机试1-10C 文章目录 HJ11 数字颠倒HJ12 字符串反转HJ13 句子逆序HJ14 字符串排序HJ15 求int型正整数在内存中存储时1的个数HJ16 购物单HJ17 坐标移动HJ18 识别有效的IP地址和掩码并进行分类统计HJ19 简单错误记录HJ20 密码验证…...

OpenAI低调发布多智能体工具Swarm:让多个智能体协同工作!
大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,专注于分享AI全维度知识,包括但不限于AI科普,AI工…...

性能之光 年度电竞性能旗舰iQOO 13发布
2024年10月30日,被定义为“性能之光”的年度电竞性能旗舰——iQOO 13正式发布,售价3999元起。iQOO 13作为iQOO 品牌在性能上的又一次深入探索,它像是一束光,引领行业不断拉高性能上限,让用户看到更多的可能性。 iQOO …...

如何避免因不熟悉数据保护法规而受损
在当今数字化时代,数据保护法规的遵守对于企业至关重要。不熟悉新的数据保护法规会导致法律风险增加、财务损失、声誉受损、客户信任下降等多方面的负面影响。其中,法律风险增加尤为严重,因为不符合规定可能引发高额罚款和法律诉讼。企业若未…...
LLaMA Factory 核心原理讲解
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…...

Java题集练习5
Java题集练习5(集合) 1.三种集合差别,集合类都是什么,数据结构是什么,都什么时候用 三者关系 Set集合 Set接口是Collection接口的一个子接口是无序的,set中不包含重复的元素,也就是说set中不…...

操作系统学习笔记-2.3哲学家和管程问题
哲学家问题 问题描述 假设有五位哲学家围坐在一张圆桌旁,每位哲学家面前放有一盘意大利面,他们各自间隔放置一根叉子。哲学家的行为分为“思考”和“进餐”两种状态。为了进餐,哲学家需要同时拿起左手边和右手边的两根叉子。用餐结束后&…...

2023年信息安全工程师摸底测试卷
目录 1.密码算法 2.等级保护 3.密码学 4.安全评估 5.网络安全控制技术 6.恶意代码 7.身份认证 8.资产管理 9.密码分类 10.被动攻击 11.商用密码服务编辑 12.超文本传输协议 13.数字水印技术 14.信息系统安全设计 15.重放攻击 16.信息资产保护 17.身份认证 …...
ReactOS系统中平衡二叉树。给定地址超导其所属区块MmFindRegion()
系列文章目录 PMM_REGION NTAPI MmFindRegion( PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address, PVOID* RegionBaseAddress ); 宏函数 //给定地址找到其中所属区块 #define CONTAINING_RECORD(address,type,field) ((type FAR *\(PCHAR)(address)-(PCHAR)(&…...
基于TESSY的单元测试与分类树方法深入解析
在现代软件开发中,单元测试是确保软件质量和可靠性的关键步骤之一。特别是对于嵌入式软件,由于其应用环境的特殊性和高安全性要求,单元测试显得尤为重要。本文将基于《TESSY 用户手册》的内容,详细介绍如何使用TESSY 进行单元测试,并深入探讨分类树方法(Classification T…...

整理了一些大模型的课程,非常详细,大模型零基础入门到精通,收藏我这一篇就够了
目前有多个科普类的大模型课程,这些课程涵盖了从基础理论到实际应用的各个方面。以下是一些主要的科普类大模型课程:复旦大学“大模型开发与赋能”专题讲习班:由复旦大学计算机学院邱锡鹏教授带来的《大模型科普讲解》课程,通过深…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
【题解-洛谷】P10480 可达性统计
题目:P10480 可达性统计 题目描述 给定一张 N N N 个点 M M M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N , M N,M N,M,接下来 M M M 行每行两个整数 x , y x,y x,y,表示从 …...