docker镜像是一个特殊的文件系统。
本篇文章将介绍docker镜像的层级结构,同时学习如何查看中间层镜像。
本文的 intermediate image 输出主要对应旧版 legacy builder。现代 BuildKit 的构建缓存不完全等同于这些中间镜像,不能只用 docker image ls 判断全部缓存。
docker的原理
Docker 的镜像就是它的文件系统,一个镜像可以放在另外一个镜像的上层,那么位于下层的就是它的父镜像。所以,Docker 会存在很多镜像层,每个镜像层都是只读的,并且不会改变。当我们创建一个新的容器时,Docker 会构建出一个镜像栈,并在栈的最顶层添加一个读写层,如图所示。
旧版构建器在构建过程中还会生成中间镜像,它和图中的文件系统层不是同一个概念。被其他镜像依赖的内容不能随意删除,下面先看看如何查看这些中间镜像。
如何查看中间层镜像
1 | # 查看镜像 |
带 -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 | ➜ log docker image ls --help |
前面用到的 -a 选项就是从这里找到的。多翻翻 help,既能了解命令的默认行为,也能发现一些平时没用过的选项。
更细节的原理可以查看这篇文章What are Docker <none>:<none> images?。