【问题标题】:Remove older docker images but not layers that are still referenced删除较旧的 docker 映像,但不删除仍被引用的层
【发布时间】:2019-01-29 04:49:52
【问题描述】:

假设我有一台构建机器,可以构建许多 docker 镜像myimage:myversion。每创建 100 个图像我会消耗大约 1GB 的磁盘空间,而且我当然不需要所有这些。例如,我想保留最近的 10 个图像(并删除所有较旧的图像),但我想确保我拥有 10 个构建/图像中的所有缓存层。如果我缓存了所有层,那么我更有可能在下次运行时快速构建。

问题是所有图像(非常旧和全新)共享很多层,因此我不能盲目删除旧图像,因为与新图像有大量重叠。

我不想使用docker image prune (https://docs.docker.com/config/pruning/#prune-images),因为这取决于我拥有哪些容器(无论状态如何)并且正在删除容器,所以 prune 最终会删除太多东西。

是否有一个简单的命令可以让我定期运行以达到我上面描述的状态?

【问题讨论】:

    标签: docker


    【解决方案1】:

    很简单,不,但是一些 shell 魔法是可能的。我认为这个 shell 脚本会做你想做的事:

    #!/bin/sh
    docker images --filter 'reference=myimage:*' \
                  --format '{{ .CreatedAt }}/{{ .ID }}/{{ .Repository }}:{{ .Tag }}' \
      | sort -r \
      | tail +11 \
      | cut -f/ -d2 \
      | xargs docker rmi
    

    (您可以尝试一次运行这一步,看看会发生什么。)

    小块:

    1. 以日期开头的格式列出所有myimage:* 图像。 (如果您使用私有注册表,则必须将注册表名称作为单独的部分包含在内,并且必须明确包含标记;例如,列出您需要的所有 GCR 图像-f 'reference=gcr.io/*/*:*'。)
    2. 按日期对它们进行排序,最新的在前。
    3. 跳过前 10 行,从第 11 行开始打印。
    4. 只取第二个斜线分隔的字段(来自--format 选项的是十六进制图像 ID)。
    5. 将其转换为docker rmi 的命令行参数。

    extended docker images documentation 列出了所有有效的--format 选项。

    【讨论】:

    • 我(几乎)正在这样做,但担心 1)删除常见的共享层,例如ubuntu 或 - 场景 2 - 如果 Docker 抱怨由于共享层(再次像 ubuntu 或某些已安装的包)而没有删除图像,那么它根本不会删除任何层。假设每个图像只有两层:第一层在所有图像之间共享,第二层对每个图像都是唯一的,如何删除所有旧图像的第二层?
    • 您可以删除与新图像共享公共层的旧图像。 Docker 只会在对该层的最后引用消失后删除该层。如果所有层仍在使用中,您会看到 docker 只删除了标签。
    • 您也可以--filter=reference=... 获取您感兴趣的特定图像名称。
    猜你喜欢
    • 2021-09-25
    • 1970-01-01
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多