没有输出的输入是不完整的

0%

Docker提升-实现原理

docker镜像是一个特殊的文件系统。
本篇文章将介绍docker镜像的层级结构,同时学习如何查看中间层镜像。

本文的 intermediate image 输出主要对应旧版 legacy builder。现代 BuildKit 的构建缓存不完全等同于这些中间镜像,不能只用 docker image ls 判断全部缓存。

docker的原理

Docker 的镜像就是它的文件系统,一个镜像可以放在另外一个镜像的上层,那么位于下层的就是它的父镜像。所以,Docker 会存在很多镜像层,每个镜像层都是只读的,并且不会改变。当我们创建一个新的容器时,Docker 会构建出一个镜像栈,并在栈的最顶层添加一个读写层,如图所示。
image

旧版构建器在构建过程中还会生成中间镜像,它和图中的文件系统层不是同一个概念。被其他镜像依赖的内容不能随意删除,下面先看看如何查看这些中间镜像。

如何查看中间层镜像

1
2
3
4
# 查看镜像
docker image ls
# 查看所有镜像(包含中间层镜像)
docker image ls -a

带 -a 参数就可以把旧构建器的中间镜像也列出来。

none:none 标签镜像

列表中的 <none>:<none> 又是什么意思呢?它表示没有对应的仓库名和标签,不能仅凭这一点判断镜像是不是 intermediate image。还有一类 dangling image(悬空镜像),也可能通过下面的命令看到:

1
docker image ls

如果只想查看悬空镜像,可以使用 docker image ls --filter dangling=true。

那么dangling image是如何产生的呢?
比如我们最开始通过如下命令构造一个名称为test:v1的镜像,

1
docker build -t test:v1 .

然后我们后期对代码进行了修改,所以我们会重新构造一个镜像。

1
docker build -t test:v1 .

我们没有为它分配新的名字,新构造的镜像还是叫做test:v1,原来的镜像就会失去这个标签。不过旧镜像可能仍被已有容器使用,清理前要先确认是否还需要它。

对于没有被容器使用、也不再需要的悬空镜像,可以通过如下命令清理。

1
docker image prune

写在最后

记得多关注一下docker的help文档,以查看镜像命令为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  log docker image ls --help

Usage: docker image ls [OPTIONS] [REPOSITORY[:TAG]]

List images

Aliases:
ls, images, list

Options:
-a, --all Show all images (default hides intermediate images)
--digests Show digests
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc Don't truncate output
-q, --quiet Only show numeric IDs

前面用到的 -a 选项就是从这里找到的。多翻翻 help,既能了解命令的默认行为,也能发现一些平时没用过的选项。

更细节的原理可以查看这篇文章What are Docker <none>:<none> images?。