用什么来存储 Docker 的镜像?

本文深入探讨了Docker镜像的存储机制,从文件系统的基本组成、类型到Docker选用的堆栈式文件系统,详细分析了存储驱动的作用和不同驱动的适用场景。此外,还展示了如何通过文件系统直接查看和理解Docker镜像的layers组成。

1. 写在最前面

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

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

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

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

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

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

2. 分析下文件系统

2.1 文件系统的组成

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

在这里插入图片描述

2.2 文件系统的类型

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

在这里插入图片描述

上图的 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 的存储驱动的话,将无法看到之前所下载的镜像。

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

    技术存储驱动程序名称适用场景
    OverlayFSoverlay or overlay2大并发但是少IO的情景
    AUFSaufs大并发但是少IO的情景
    Btrfsbtrfs不适合在高密度容器的PaaS平台上使用
    Device Mapperdevice mapper密集型IO的场景
    ZFSzfs适合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. 参考资料

<think>好的,我现在需要帮用户解答如何查看本地已有的Docker镜像的命令。首先,我得回忆一下Docker的相关命令,记得用户提到的引用里提到过镜像命令。 根据引用[2],里面明确提到镜像命令中的第一个是列出本地主机上的镜像,使用docker images [options]。所以用户的问题应该用这个命令来解决。不过我需要确认是否有其他参数或者选项需要注意。 另外,用户提供的示例中引用[2]还提到docker images可以有选项,比如-a显示所有镜像,-q只显示镜像ID等。可能需要把这些常用选项也告诉用户,让他们更全面地了解。 用户可能刚接触Docker,所以除了给出命令,最好解释一下命令输出中各列的含义,比如REPOSITORY、TAG、IMAGE ID等,这样用户看到结果时不会困惑。比如IMAGE ID是镜像的唯一标识,CREATED是创建时间,SIZE是大小。 还要考虑用户可能遇到的常见问题,比如镜像列表过长如何过滤,或者如何查看特定的镜像。这时候可以提到使用grep命令来筛选,例如docker images | grep nginx,这样用户可以根据需要查找特定镜像。 另外,是否需要提醒用户关于镜像存储位置或者其他相关命令?比如docker image ls其实是docker images的新写法,两者功能相同。可能用户会看到不同的文档中有不同的写法,可以稍微提一下,避免混淆。 总结一下,回答的结构应该是先给出基本命令,解释输出内容,然后列出常用选项,再给出实际例子,最后可能补充一些使用技巧或相关命令。同时确保引用正确的参考资料,比如引用[2]中的内容。</think>要查看本地已有的Docker镜像,可以通过以下步骤操作: 1. **基础命令** 使用`docker images`命令,该命令会列出本地所有镜像的基本信息,包括: - **REPOSITORY**:镜像名称 - **TAG**:版本标签(默认`latest`) - **IMAGE ID**:镜像唯一标识(前12位) - **CREATED**:镜像创建时间 - **SIZE**:镜像体积 ```bash docker images ``` 2. **常用参数扩展** - `-a`:显示所有镜像(包括中间层镜像) - `-q`:仅显示镜像ID - `--digests`:显示镜像的摘要信息(需镜像支持) ```bash docker images -a # 查看完整镜像列表 docker images -q # 仅输出镜像ID ``` 3. **过滤镜像** 通过`grep`筛选特定镜像,例如查找包含`nginx`的镜像: ```bash docker images | grep nginx ``` 4. **新语法等效命令** Docker新版本支持`docker image ls`命令,功能与`docker images`一致: ```bash docker image ls ``` **注意事项**: - 镜像体积可能因分层存储机制与实际占用空间存在差异 - 未打标签的镜像会显示为`<none>`[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值