当前位置: 首页 > news >正文

Docker核心技术:Docker原理之Union文件系统

云原生学习路线导航页(持续更新中)

  • 相关内容快捷链接
    • 应用架构演进
    • 容器技术要解决哪些问题
    • Docker的基本使用
    • Docker原理之Namespace
    • Docker原理之Cgroups

本文是 Docker核心技术 系列文章:主要讲解了docker文件系统的基本原理,包括:docker镜像的分层结构、docker容器的rootfs核心机制、unionFS的核心原理等,并以overlayFS 为例讲解了文件系统联合的过程,最后介绍了oci标准与docker引擎架构变化

  • 希望大家多多 点赞 关注 评论 收藏,作者会更有动力继续编写技术文章

1.Docker容器镜像的创举

  • Docker容器最大的创新,就是 使用镜像分层,解决了部署时文件分发的通用难题

    • Dockerfile每一条命令都是一个镜像层,都有一个唯一的checksum。拉取每层镜像前,会先检查这个checksum是否存在,存在的话直接使用缓存,不用再拉取了

    • 假如OS基础镜像层有500MB,你每次变更业务代码只有5MB,那么部署时拉取新镜像就做到了 增量拉取,速度和资源都得到了节约

  • 为什么说是docker容器的创举?

    • 以前,比如java程序部署时,每个公司有自己的file server,把代码或jar包放到file server。在服务器上手动get或编写agent获取到jar包,然后部署。
    • 不同的应用,需要写不同的脚本实现
    • 使用docker,docker repository相当于file server,docker client相当于agent。docker pull的时候还可以增量拉取。把流程标准化了

在这里插入图片描述

2.Docker 容器 rootFS 的核心机制

从 Linux核心技术:Linux文件系统与bootFS/rootFS 可知,docker 容器文件系统中,只包括rootfs层,不包括bootfs层

2.1.分层结构(关键差异)

在这里插入图片描述

  • 相比于linux rootfs结构,docker rootfs 采用了分层结构:
    • 镜像层(只读):容器启动时,以镜像的 rootfs 为不可变基础层,确保镜像文件无法被运行时修改。
    • 容器层(可写):在镜像层之上叠加一个可写层(称为容器层),所有文件变更(如写入、删除)均在此层进行。

2.2.联合挂载(Union Mount)

  • Docker 使用 联合文件系统(如 Overlay2、AUFS)将多层文件系统合并为单一视图。
  • 比如使用 Overlay2 实现联合文件系统:
    • lowerdir:对应镜像的只读层。
    • upperdir:容器的可写层,记录运行时变更。
    • merged:用户看到的统一文件系统视图。

2.3.写时复制(CoW)与 用时分配

在这里插入图片描述

  • 读取:直接访问底层镜像文件(无性能损耗)。
  • 修改:将目标文件从镜像层复制到容器层后再修改,原镜像文件保持只读。

2.4.总结:docker容器文件系统的优势

优势说明
镜像不可变性镜像层始终只读,确保同一镜像启动的容器环境一致,避免依赖冲突。
资源高效利用多个容器共享同一镜像层,减少磁盘占用(如 100 个 CentOS 容器共享一个基础层)。
快速部署容器启动时无需复制完整镜像文件,仅需创建可写层,秒级启动。
版本追溯通过分层机制记录每次镜像构建的变更(Dockerfile 指令对应层),便于调试和回滚。

3.UnionFS 联合文件系统详解

3.1.Union文件系统是什么

  • Union文件系统(Union File System,简称UnionFS)是一种 ​​分层叠加 的文件系统技术​​,它通过将多个目录或文件系统(包括只读和可写层)合并到同一挂载点,形成一个逻辑统一的文件视图。其核心特点包括:
    • 分层存储​​:文件系统由多层组成,底层通常是只读的基础文件(如Docker镜像的基础层),上层为可写层(如容器运行时修改)。
    • 写时复制(CoW):修改文件时,系统会先将文件从只读层复制到可写层进行变更,原文件保持不变,确保高效存储和隔离性。
    • ​​优先级叠加​​:访问文件时,高层内容覆盖低层同名文件,用户看到的是最终叠加结果。
      在这里插入图片描述

3.2.容器存储驱动

3.2.1.容器存储驱动是什么

  • 容器存储驱动是容器引擎(如 Docker、Containerd)的核心组件,负责管理容器文件系统的存储和操作
  • 核心功能包括:
    • 分层管理:实现镜像分层(只读层)与容器运行时层(可写层)的叠加。
    • 写时复制(CoW):保证镜像不可变,仅在容器层修改文件时复制数据。
    • 数据持久化:支持通过卷(Volume)或绑定挂载实现数据持久化。
    • 性能优化:根据场景选择不同驱动,平衡 I/O 性能与资源消耗。

3.2.2.容器存储驱动发展历史

  • 早期阶段(2013-2015)
    • AUFS 作为 Docker 初始驱动,解决了分层存储需求,但依赖非主线内核补丁,兼容性差。
  • 标准化阶段(2015-2017)
    • OverlayFS 进入 Linux 主线内核(3.18+),逐步取代 AUFS 成为主流。
    • Device Mapper 因支持块存储特性,成为企业级场景的选择。
  • 多样化阶段(2018 至今)
    • Btrfs/ZFS 提供高级功能(快照、压缩),但资源消耗较高。
    • Containerd 作为独立运行时,简化驱动支持(如默认放弃 AUFS)。
  • 现状:OverlayFS 2已经成为主流,容器驱动的不二之选

3.2.3.主流存储驱动特点与对比

在这里插入图片描述

驱动名称支持场景核心优点核心缺点
AUFSDocker(仅 Ubuntu/Debian)成熟的分层设计,节省存储空间非主线内核支持,性能在密集 I/O 场景差
OverlayFSDocker/Containerd(Linux 3.18+)内核原生支持,性能均衡,兼容性好不支持页缓存共享,多层叠加性能下降
Device MapperDocker/Containerd(RHEL/CentOS)块级存储,适合生产环境高负载配置复杂,需预分配存储池,空间利用率低
BtrfsDocker(社区版 Debian/Ubuntu,企业版 SLES)/Containerd支持快照、压缩,适合开发测试稳定性风险,修复复杂问题需重启
ZFSDocker(Linux/FreeBSD)数据完整性校验,支持高级存储池管理内存占用高,需专用内核模块

3.2.4.不同存储驱动优缺点对比

在这里插入图片描述

  • Overlay:kernel自带,不需要额外安装,使用容器只需要额外安装docker/containerd等

3.3.OverlayFS

3.3.1.OverlayFS 是什么

在这里插入图片描述

  • OverlayFS是一种联合文件系统,核心功能就是 通过覆盖机制实现上下层文件的联合,得到一个终态的文件系统
  • Overlay:覆盖的意思
  • OverlayFS的分层
    • lower层:对应容器的镜像层,dockerfile的每一条指令都是一个新的只读层,合并在一层统一为lower层
    • upper层:对应容器的容器可写层
    • 合并层:最终mount到容器中的层,对应容器能够看到的目录和文件。
  • OverlayFS文件覆盖策略
    • 如果一个文件 只在下层 存在,则会直接被合并
    • 如果一个文件 只在上层 存在,则会直接被合并
    • 如果一个文件 在上下层 都存在,则上层会覆盖下层,优先级更高

3.3.2.OverlayFS 文件系统练习

在这里插入图片描述

mkdir upper lower merged work
echo "from lower" > lower/in_lower.txt
echo "from upper" > upper/in_upper.txt
echo "from lower" > lower/in_both.txt
echo "from upper" > upper/in_both.txt
# mount
sudo mount -t overlay overlay -o lowerdir=`pwd`/lower,upperdir=`pwd`/upper,workdir=`pwd`/work `pwd`/merged
# 查看 overlay 文件系统生成结果
tree
.
├── lower
│   ├── in_both.txt
│   └── in_lower.txt
├── merged
│   ├── in_both.txt
│   ├── in_lower.txt
│   └── in_upper.txt
├── upper
│   ├── in_both.txt
│   └── in_upper.txt
└── work├── index└── work6 directories, 7 filescat merged/in_both.txt 
from uppercat merged/in_lower.txt 
from lowercat merged/in_upper.txt 
from upper
  • mount 是 Linux 系统中用于将存储设备(如硬盘、U盘、ISO 镜像等)或远程文件系统挂载到指定目录的命令。挂载后,用户可以通过该目录访问存储设备中的内容。
    mount -t <文件系统类型> -o <选项> <设备路径> <挂载点目录>
    
  • 上述 mount 命令的参数解释
    • lowerdir:只读的底层目录(可多个),文件按顺序从下到上叠加(/lower1 在最底层,/lower2 在其上)。
    • upperdir:可写的上层目录,所有修改(新增、删除、修改文件)会记录在此。
    • workdir:供 OverlayFS 内部使用的临时目录,必须与 upperdir 在同一文件系统。
    • /merged:最终的挂载点,用户在此访问合并后的文件系统视图。

3.3.3.如何进入 docker 容器的mount ns

  • 从上面的学习和练习,可以看出,docker容器的文件系统,其实就是docker image lower层+容器可写层,使用mount命令合并之后的merged文件系统。然后这个merged系统被挂载到了容器的mount ns中,所以容器进程能看到和主机不一样的文件系统
  • 那么如何进入容器的 mount ns,查看merged之后的文件系统?
    • 在 Docker核心技术:Docker原理之Namespace 中,学习了使用nsenter命令进入ns的方法
    • nsenter -t ${pid} -m 即可进入一个进程的mount ns
    • 比如:
      [root@VM-226-235-tencentos /proc/11913/ns]# nsenter -t 11913 -m
      -bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
      root@VM-226-235-tencentos:/#
      root@VM-226-235-tencentos:/# ls
      bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  zgy
      

3.3.4.如何查看一个 docker 容器的overlay细节?

  • docker inspect ${container-id},输出中GraphDriver展示了overlay细节
  • GraphDriver 是 Docker 用于管理容器镜像分层存储的核心驱动模块,负责将镜像的只读层与容器的可写层叠加为统一视图。其输出信息包括:
    • ​​存储驱动类型​​(如 overlay2、aufs),决定了分层合并的实现方式
    • ​​具体存储路径​​(如 UpperDir、MergedDir),指向容器可写层和合并后的文件系统目录
    • ​​镜像层 ID​​,记录镜像分层结构(如 LowerDir 中的多个只读层)
  • 如:
    在这里插入图片描述

3.4.Docker 容器采用Union文件系统 + mount ns的好处

  • 采用 Union文件系统 解决了文件更新效率的问题
  • 采用 mount ns 解决了docker容器可移植性问题。
    • 一个容器,只需要把自己所依赖的所有命令、文件、软件…都放入自己的mount ns,然后将mount ns打包压缩,就可以移植到任何的可兼容系统中
    • 容器不需要关心底层os是否包含某些命令和软件,它出生就自带了

4.OCI 容器标准

4.1.OCI 标准是什么

在这里插入图片描述

  • docker作为先行者和商业公司,具有盈利性质,产品更新迭代很快
  • google等作为后来者,想要分市场,只能通过标准化来介入。OCI就是这样的背景下,由google牵头,找大厂背书,搞出来的一个容器标准。
    • docker小公司抵挡不住google的攻击,妥协后也接受了OCI标准,并把自己的容器运行时抽取为containerd

4.2.docker 引擎架构

在这里插入图片描述

  • 早期的docker架构
    • docker daemon是主进程,任何的容器进程都是docker daemon作为父进程 fork出来的子进程
    • 此时如果docker daemon自身要升级,杀掉父进程,所有的子进程就都会有问题
  • 改进后的docker架构
    • 后来引入了一个containerd组件,并引入了一个 dockershim 的概念。containerd只是一个单纯的daemon,它在创建容器进程的时候,会同时创建一个dockershim进程,该进程作为容器进程的主进程。
    • 这样 容器进程 与 containerd 解藕开了,升级containerd不会影响到dockershim,也就不会影响到具体的容器进程。而dockershim本身非常轻量级,基本不需要升级
    • 查看下容器的进程树结构,验证是否是这样的:
      在这里插入图片描述
    • 验证是否每个容器都有一个docker shim?
      在这里插入图片描述

5.docker问题解析

5.1.容器的1号进程是什么

  • 容器的1号进程是它的entrypoint进程
  • 为什么有些容器应用进程就是1号,有些容器应用进程不是1号呢?
    • 有些容器entrypoint直接就指定了应用进程
    • 有些容器是在entrypoint中指定一个启动脚本,由脚本拉起应用进程,所以应用进程就不是1号了

相关文章:

  • Google 推出 Flow —— AI 电影制作新平台
  • 在vue中重复组件导入简化方案
  • 【Leetcode 每日一题】2131. 连接两字母单词得到的最长回文串
  • 校园二手交易系统
  • Java详解LeetCode 热题 100(21):LeetCode 240. 搜索二维矩阵 II(Search a 2D Matrix II)详解
  • 【计算机网络】基于TCP进行socket编程——实现客户端到服务端远程命令行操作
  • DAY36
  • 【MySQL】第十一弹——JDBC编程
  • PHP学习笔记(十)
  • 特征预处理
  • QML混合编程图像刷新策略
  • JavaSE核心知识点03高级特性
  • JavaScript数据类型及内置函数详解目录
  • 【MYSQL】索引、存储引擎
  • Next.js V15 在异步页面中,获取路由动态参数的几个坑
  • 【二刷力扣】【力扣热题100】今天的题目是:283.移动零
  • 2025.5.22 Axure 基础与线框图制作学习笔记
  • 大数据Spark(六十):Spark On Yarn 配置
  • 软件工程重点复习
  • C++学习之打车软件—高德地图API
  • 宝鸡专业做网站/新闻稿范文
  • 搜狐快速建站/灰色词排名上首页
  • 网络开发公司/优化服务公司
  • 网站建设388/常见的网络推广方法有哪些
  • 免费在线建站/市场调研报告怎么写
  • 展示网站/seo优化排名公司