查找每个Docker镜像的层和层大小

235
为了研究目的,我正在尝试爬取公共Docker注册表(https://registry.hub.docker.com/),并找出1)平均图像有多少层以及2)这些层的大小,以了解分布情况。
然而,我研究了API和公共库以及github上的细节,但我找不到任何方法来:
- 检索所有公共存储库/镜像(即使有成千上万个,我仍然需要一个起始列表来迭代) - 找到图像的所有层 - 找到层的大小(因此不是图像,而是单个层)。
有人能帮我找到检索此信息的方法吗?
编辑:有人能够验证在Docker注册表中搜索“*”是否返回所有存储库,而不仅仅是任何地方提到“*”的内容吗? https://registry.hub.docker.com/search?q=\*

14
查找图像的所有层,如果您不使用API,则可以执行“docker history myimage”命令,然后您将看到每个层的大小。更一般地,在图像上,您可以执行“docker history myimage | awk 'NR>1 {print $1}' | xargs docker inspect --format '{{ ((index .ContainerConfig.Cmd ) 0) }}'”以查看创建图像时发出了哪些命令。 - user2915097
这对第二步已经是一个很大的帮助,尽管这要求我通过Docker将每个图像下载到我的本地机器。我想那是一个选择,但前提是我找到一种检索“myimages”列表的方法(例如,在第一步中公共注册表中的每个图像)。我一定会探索这个选项,谢谢! - user134589
"https://registry.hub.docker.com/search?q=*" 对我来说显示了87031个仓库。 - user2915097
12个回答

199

看看使用golang编写的dive

非常棒的工具!


1
你用什么软件制作了这个gif? - uberrebu
7
或许可以试试 https://asciinema.org/ 这个网站,搜索一下“terminal recording(终端录屏)”即可。 - Koray Tugay
我的14GB图像上出现了潜水断点。 - vicenteherrera

140

您可以先使用以下方式查找图像 ID:

$ docker images -a

然后找到图像的图层以及它们的尺寸:

$ docker history --no-trunc <Image ID>

注意:我使用的是 Docker 版本 1.13.1

$ docker -v
Docker version 1.13.1, build 092cba3

3
+1 我不得不删除 --no-trunc,因为输出在我的终端上无法使用,但这仍然提供了很棒的信息。 - Sherwin F

103

如果您将存储驱动程序配置为aufs(默认选项),则可以在文件夹/var/lib/docker/aufs/layers中找到图像的层级结构。

示例:

 docker ps -a
 CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
 0ca502fa6aae        ubuntu              "/bin/bash"         44 minutes ago      Exited (0) 44 seconds ago                       DockerTest

要查看使用"Ubuntu"镜像创建的容器层,请前往/var/lib/docker/aufs/layers目录并查看以容器ID开头的文件(此处为0ca502fa6aae*)

 root@viswesn-vm2:/var/lib/docker/aufs/layers# cat    0ca502fa6aaefc89f690736609b54b2f0fdebfe8452902ca383020e3b0d266f9-init 
 d2a0ecffe6fa4ef3de9646a75cc629bbd9da7eead7f767cb810f9808d6b3ecb6
 29460ac934423a55802fcad24856827050697b4a9f33550bd93c82762fb6db8f
 b670fb0c7ecd3d2c401fbfd1fa4d7a872fbada0a4b8c2516d0be18911c6b25d6
 83e4dde6b9cfddf46b75a07ec8d65ad87a748b98cf27de7d5b3298c1f3455ae4
这将展示同样的结果通过运行。
root@viswesn-vm2:/var/lib/docker/aufs/layers# docker history ubuntu
IMAGE               CREATED             CREATED BY                                         SIZE                COMMENT
d2a0ecffe6fa        13 days ago         /bin/sh -c #(nop) CMD ["/bin/bash"]             0 B                 
29460ac93442        13 days ago         /bin/sh -c sed -i 's/^#\s*\   (deb.*universe\)$/   1.895 kB            
b670fb0c7ecd        13 days ago         /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic   194.5 kB            
83e4dde6b9cf        13 days ago         /bin/sh -c #(nop) ADD file:c8f078961a543cdefa   188.2 MB 

为查看完整的层 ID,请在历史命令的一部分中使用 --no-trunc 选项运行。

docker history --no-trunc ubuntu

6
从Docker 1.10版本开始,情况已经发生了改变。docker history命令将不会像在/var/lib/docker/aufs/layers文件夹中显示的那样给出镜像层信息。阅读此处的更新。 - Ruifeng Ma
14
自 Docker 1.10 版本引入内容可寻址存储以来,镜像和层现在是分开的。 docker history 命令不再提供有关 Docker 主机上实际层磁盘存储信息的信息。请参阅此博客 - Ruifeng Ma

60

在我看来,docker history <image>就足够了。这会返回每个层的大小:

$ docker history jenkinsci-jnlp-slave:2019-1-9c
IMAGE        CREATED    CREATED BY                                    SIZE  COMMENT
93f48953d298 42 min ago /bin/sh -c #(nop)  USER jenkins               0B
6305b07d4650 42 min ago /bin/sh -c chown jenkins:jenkins -R /home/je… 1.45GB

13

这将检查Docker镜像并打印出其层次结构:

$ docker image inspect nginx -f '{{.RootFS.Layers}}'
[sha256:d626a8ad97a1f9c1f2c4db3814751ada64f60aed927764a3f994fcd88363b659 sha256:82b81d779f8352b20e52295afc6d0eab7e61c0ec7af96d85b8cda7800285d97d sha256:7ab428981537aa7d0c79bc1acbf208c71e57d9678f7deca4267cc03fba26b9c8]

12

1
嗨@bummi,抱歉我认为这个问题最初是在寻找Docker注册表的解决方案,而我们提供的解决方案是直接指向Docker镜像的层。因此,我尝试提供另一个解决方案(我认为更容易)。 - sunnycmf

3
  1. https://hub.docker.com/search?q=* shows all the images in the entire Docker hub, it's not possible to get this via the search command as it doesnt accept wildcards.

  2. As of v1.10 you can find all the layers in an image by pulling it and using these commands:

    docker pull ubuntu
    ID=$(sudo docker inspect -f {{.Id}} ubuntu)
    jq .rootfs.diff_ids /var/lib/docker/image/aufs/imagedb/content/$(echo $ID|tr ':' '/')
    

3) 大小可以在 /var/lib/docker/image/aufs/layerdb/sha256/{LAYERID}/size 找到,尽管 LAYERID != 之前命令中找到的 diff_ids。这时需要查看 /var/lib/docker/image/aufs/layerdb/sha256/{LAYERID}/diff 并将其与之前的命令输出进行比较,以正确匹配相应的 diff_id 和大小。


RE1) 对我没有用,似乎重定向到hub.docker.com。 - joedragons
1
"docker inspect imagename | jq .[].RootFS.Layers" 是一个更简单的方法来执行第二步。 - wheredidthatnamecomefrom

3
要查找图像的所有层以及查找层的大小,您可以通过Docker Hub注册表上的"manifest" experimental feature显示清单:
docker manifest inspect ubuntu

结果是一个JSON文件(此处仅显示前几行):
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 529,
         "digest": "sha256:10cbddb6cf8568f56584ccb6c866203e68ab8e621bb87038e254f6f27f955bbe",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 529,
         "digest": "sha256:dd375524d7eda25a69f9f9790cd3e28855be7908e04162360dd462794035ebf7",
         "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v7"

3
“确实可以从Docker Registry服务器查询清单或blob信息,而无需将镜像下载到本地磁盘。您可以参考Registry v2 API来获取镜像的清单。”
GET /v2/<name>/manifests/<reference>

请注意,您需要处理不同的清单版本。对于 v2,您可以直接获取图层大小和 blob 的摘要。对于 v1 清单,您可以 HEAD blob 下载 URL 以获取实际图层大小。
有一个简单脚本来处理上述情况,将持续维护。

2

目前这会给出一个堆栈跟踪。 - DomQ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接