Docker Foundation - Union FS
Union FS
Docker 的创新在文件系统:通过镜像解决容器分发的问题
- 将不同目录挂载到同一个虚拟文件系统下的文件系统
- 支持为每一个成员目录(类似于 Git Branch)设定权限:
readonly
、readwrite
、whiteout-able
- 文件系统分层,对
readonly
权限的 Branch 可以逻辑上进行修改(增量、不影响readonly
部分) - 用途
- 将多个 Disk 挂在同一个目录下
- 将一个
readonly
的 Branch 和一个writeable
的 Branch 联合在一起
Docker 镜像
层可以复用,增量分发
1 | # docker image inspect --format '{{.RootFS}}' centos:latest |
镜像文件系统
- bootfs
- Bootloader 引导加载 kernel
- 当 kernel 被加载到内存后,umount bootfs
- rootfs
- rootfs:
/dev
、/proc
等标准目录和文件
- rootfs:
- 不同的 Linux 发行版,bootfs 基本一致,而 rootfs 会有差异,容器关心的只是 kernel
容器运行态
容器是 Linux 上的一个进程,没有 bootfs(复用宿主机的 kernel),只有 rootfs
容器需要借助 mnt namespace 进行隔离,可见的是镜像的 rootfs
- Linux
- 在启动时,先将 rootfs 设置为 readonly,在进行一系列检查后,将其切换成 readwrite 供用户使用
- Docker 启动
- 初始化时,同样将 rootfs 以 readonly 的方式加载并检查
- 然后利用 Union FS 的方式将一个 readwrite 文件系统挂载在 readonly 的 rootfs 之上
- 再次将下层的 FS 设为 readonly,并向上叠加 – 迭代
- 这样构成了 container 的运行态:N 个 readonly FS 层 + 1 个 writeable FS 层
写操作
镜像是共享的,容器对可写层的操作依赖于存储驱动提供的写时复制和用时分配机制 – 提高存储和内存资源的利用率
- 写时复制
- 当需要修改镜像的文件时,从镜像的文件系统复制一份到容器的可写层进行修改,镜像里的文件不会改变
- 同一个镜像可以对应多个容器,对应的镜像文件只会有一份,内容不同的是各自容器的可写层
- 不同容器对文件的修改是互不影响的
- 当需要修改镜像的文件时,从镜像的文件系统复制一份到容器的可写层进行修改,镜像里的文件不会改变
- 用时分配:当一个文件被创建出来后,才会分配空间
容器存储驱动
主流:OverlayFS
OverlayFS
- OverlayFS 是一种 Union FS,属于文件级的存储驱动(
BtrFS
和ZFS
都是块级别的存储驱动) - Overlay 只有两层:Lower 层代表镜像层,Upper 层代表容器可写层
work 是临时工作目录,以 merged 为准
1 | # mkdir upper lower merged work |
1 | # docker inspect --format '{{.GraphDriver.Name}}' 4201f70592fb |
OCI
Open Container Initiative – Google 主导
Specification | Desc |
---|---|
Image Specification | 定义应用如何打包 |
Distribution Specification | 定义如何分发容器镜像 |
Runtime Specification | 定义如何解压应用包并运行 |
Docker 引擎架构
containerd 是一个单纯的 daemon,fork 出来的子进程的父进程是一个 shim(shim 的父进程是 systemd),这样 containerd 重启时不会影响其他进程
6469 就是 shim
1 | # docker inspect --format '{{.State.Pid}}' 4201f70592fb |
容器内的 1 号进程,是 EntryPoint 进程,并非宿主机上的 systemd
1 | docker exec -it 4201f70592fb ps -ef |
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.