文章目录

  • 1. 写在最前面
  • 2. 分析下文件系统
  • 2.1 文件系统的组成
  • 2.2 文件系统的类型
  • 2.3 存储驱动
  • 3. 非常手段查看镜像
  • 3.1 查看本机可用镜像
  • 3.2 分析镜像 layers 组成
  • 4. 碎碎念
  • 5. 参考资料


1. 写在最前面

「不是你想要用什么,而是你有什么,能用的是什么?」

反复思考这句话的时候,突然意识到不是 docker 选择用文件来存储镜像,而是除了文件以外,docker 别无其他选择。

从宏观来分析,计算机的组成包括了CPU、内存、磁盘,排除法 CPU 负责逻辑,而内存又是易失存储,所以只能用磁盘来存储。

从微观上分析,「Linux 一切皆文件」,而这其中文件的抽象包括了对磁盘文件系统的抽象。

综上所述,所以 docker 的容器和镜像也必然使用了文件来存储。

🤔 他山之石,可以为错,他山之石,可以攻玉。 《诗经 · 小雅 · 鹤鸣》

2. 分析下文件系统

2.1 文件系统的组成

文件系统由两层或者三层组成,有些时候这些层次是被显示的分割开来的,有些时候则是被组合在一起的。

windows docker 容器中获取硬件信息 docker硬件资源_docker

2.2 文件系统的类型

下图是一半的 Linux 存储堆叠图,笔者只重点摘抄了本文要分析绿色的文件系统类型部分,感兴趣的读者可点击Linux Storage Stack Diagram 查看

windows docker 容器中获取硬件信息 docker硬件资源_文件系统_02

上图的 VFS 就是 Logical file system 和 Virtual file system 的结合,它

  • 一方面给用户层提供一些标准的系统调用 open、read、write 来操作文件
  • 一方面对底层的文件系统进行约束,提供统一的抽象接口和方式

文件系统的类型包括:

  • 磁盘文件系统:基于物理存储设备的文件系统,用来管理设备的存储空间,如 ext2, ext4, xfs 等
  • 网络文件系统:用于访问网络中其他设备上的文件,如 NFS,smbfs 等。
  • 堆栈式文件系统:叠加在其他文件系统之上的一种文件系统,本身不存储数据,而是对下层数据的扩展
  • 伪文件系统:并不管理真正的存储空间,所以被称为伪文件。它组织了一些虚拟的目录和文件,通过这些文件可以访问系统或磁盘的硬件数据。它不是用来存储数据的,而是把数据包装成文件来访问,所以不能把伪文件系统当做存储空间来操作,比如 proc 、sysfs 等。
  • 特殊文件系统:特殊文件系统也是一种伪文件系统,它使用起来更像是一个磁盘文件系统,但是读写的是内存而不是磁盘设备。如 tmpfs、ramfs 等。
  • 用户文件系统:也叫做 FUSE,它提供一种方式可以让开发者在用户空间实现文件系统,而不需要修改内核。这种方式更加灵活,但是效率更低。FUSE 直接面向的是用户文件系统,也不会调用 Block 层。

2.3 存储驱动

docker 选择堆栈式文件系统作为其存储,最开始使用的 AUFS 的实现,但是由于 AUFS 并未并入 Linux 内核,以及兼容性问题, Docker 0.7 版本中引入了存储驱动的概念,目前 docker 支持 AUFS、Btrfs、Device mapper、OverlayFS、OverlayFS2、ZFS 存储驱动 。

  1. 存储驱动是用来做什么的 ?
    docker 的镜像是由许多 layers 共同组成。在容器运行时,组装这些 layers 并且对运行时提供可写层是存储驱动负责的事情,不同的存储驱动会影响容器的 IO 性能以及占用磁盘的大小。

注:所有的存储驱动都使用 CoW 技术,切换了 docker 的存储驱动的话,将无法看到之前所下载的镜像。

  1. 各类存储驱动的适用场景?

技术

存储驱动程序名称

适用场景

OverlayFS

overlay or overlay2

大并发但是少IO的情景

AUFS

aufs

大并发但是少IO的情景

Btrfs

btrfs

不适合在高密度容器的PaaS平台上使用

Device Mapper

device mapper

密集型IO的场景

ZFS

zfs

适合PaaS和高密度的场景

3. 非常手段查看镜像

对文件系统有了一个大致的了解以后,让我们先来思考一个问题:

3.1 查看本机可用镜像

不用docker images 这个命令,你如何查镜像?

答: 既然知道 docker 的镜像是用文件存储,所以只要找到存储它们的目录不就解决了嘛。

注:以下操作在 mac 上找不到……,笔者暗戳戳的找了一台云主机。

首先,执行下面的命令,找到 docker 存储数据的根目录。

#docker info  | grep "Docker Root Dir"
 Docker Root Dir: /var/lib/docker

然后,切换到 /var/lib/docker 目录执行

#cd /var/lib/docker & ls
builder  buildkit  containerd  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  trust  volumes
#cd image/overlay2 & ls
distribution  imagedb  layerdb  repositories.json

最后,发现 repositories.json 文件里记录了本机可用的 docker 镜像。

#cat repositories.json | jq .
{
  "Repositories": {
    "agility-playbooks": {
      "agility-playbooks:19-09": "sha256:8859205bb9ffbf9e935de7516ecba9f3f82459cf31ae21e69848dad055f1ec2c"
    },
    "xx.applet": {
      "xx.applet:v1": "sha256:c0519345d5275a721075d1d0ca3398b4cfe86fdb39e6785d61c9f23b6014b180"
    },
    "xx2.applet": {
      "xx2.applet:v1": "sha256:209dad35aa9f65c10dc99f5961f7cd195e0b6e1130d53bd29f4b132070c5fda5"
    },
}

3.2 分析镜像 layers 组成

使用 docker inspect 可以查看 Return low-level information on Docker objects

#docker inspect 8859205bb9ffbf9e935de7516ecba9f3f82459cf31ae21e69848dad055f1ec2c

……
"GraphDriver": {
    "Data": {
         "LowerDir": "/data/docker/overlay2/ba5ba156a3671fbe5783a3828c1744f0e2228eef0609a49194d3581534c86a53/diff",
         "MergedDir": "/data/docker/overlay2/253b3ee790492b6ec7626c0cf36eb9ffd17142f4ec1bfb570570d7e7ec5242e5/merged",
         "UpperDir": "/data/docker/overlay2/253b3ee790492b6ec7626c0cf36eb9ffd17142f4ec1bfb570570d7e7ec5242e5/diff",
         "WorkDir": "/data/docker/overlay2/253b3ee790492b6ec7626c0cf36eb9ffd17142f4ec1bfb570570d7e7ec5242e5/work"
    },
    "Name": "overlay2"
},
……

可见笔者这台云主机上的 docker 所使用的存储驱动是 overlay2。

在多思考下,inspect 这个命令的内容是哪里搞出来的呢?

切换文件目录到 imagedb/content/sha256 下,使用 xxd (命令用于用二进制或十六进制显示文件的内容 ) 查看文件内容,果然找到啦。

[root@docker /var/lib/docker/image/overlay2/imagedb/content/sha256]
#ls | grep "8859205bb9ffbf9e935de7516ecba9f3f82459cf31ae21e69848dad055f1ec2c"
8859205bb9ffbf9e935de7516ecba9f3f82459cf31ae21e69848dad055f1ec2c

[root@docker /var/lib/docker/image/overlay2/imagedb/content/sha256]
#xxd 8859205bb9ffbf9e935de7516ecba9f3f82459cf31ae21e69848dad055f1ec2c
0000000: 7b22 6172 6368 6974 6563 7475 7265 223a  {"architecture":
0000010: 2261 726d 3634 222c 2263 6f6e 6669 6722  "arm64","config"
0000020: 3a7b 2248 6f73 746e 616d 6522 3a22 222c  :{"Hostname":"",
0000030: 2244 6f6d 6169 6e6e 616d 6522 3a22 222c  "Domainname":"",
0000040: 2255 7365 7222 3a22 222c 2241 7474 6163  "User":"","Attac
0000050: 6853 7464 696e 223a 6661 6c73 652c 2241  hStdin":false,"A
…………
0001cc0: 6c69 6e75 7822 2c22 726f 6f74 6673 223a  linux","rootfs":
0001cd0: 7b22 7479 7065 223a 226c 6179 6572 7322  {"type":"layers"
0001ce0: 2c22 6469 6666 5f69 6473 223a 5b22 7368  ,"diff_ids":["sh
0001cf0: 6132 3536 3a31 6564 3531 3231 6135 3230  a256:1ed5121a520
0001d00: 3335 6139 3830 6335 3439 6565 3039 6364  35a980c549ee09cd
0001d10: 3739 3361 3434 3437 6635 6561 6263 3232  793a4447f5eabc22
0001d20: 3339 3962 6532 6236 6531 3166 6634 3962  399be2b6e11ff49b
0001d30: 3035 3164 3822 2c22 7368 6132 3536 3a32  051d8"]}}

4. 碎碎念

依稀记得在看《令人心动的 Offer》第一季的时候,面试李浩源的问题:

「你认为天赋和努力,哪个更重要?」就是这个问题在昨天我终于找到了一个我更加喜欢的答案。

「初中我刷完了 301 套试题,高中我买了市面上能买到的卷子, 天赋能让一个人闪闪发光,但努力也能」

——夏林希

天赋让浩源同学闪闪发光,但是努力才是让普普通通的我们发光的钥匙。(ps 反思,这篇文章写得主题不够清晰,后面要好好改正。嗯,就这样,今天也是开心的一天哦

5. 参考资料