构建后如何从构建中删除中间图像?

How to remove intermediate images from a build after the build?

当您使用

构建多阶段 Docker 文件时
docker build -t myimage .

它生成标记为 myimage 的最终图像以及中间图像。明确地说,我们在这里谈论的不是容器,而是图像。它看起来像这样:

看到这些 <none> 图片了吗?这些就是我要说的。

现在这个"issue"已经讨论到一定程度了here and here

以下是一些相关部分:

If these intermediate images would be purged/pruned automatically, the build cache would be gone with each build, therefore forcing you to rebuild the entire image each time.

好吧,然后自动修剪没有意义。

有人这样做:

For now, I'm using docker image prune -f after my docker build -t app . command to cleanup those intermediate images.

但不幸的是,这不是我能做的。正如一位讨论参与者评论的那样:

It removes "all dangling images", so in shared environments (like Jenkins slave) it's more akin to shooting oneself in the foot. :)

这就是我所处的场景。

所以"fixed" Docker 方面没什么可说的。但是我怎样才能删除这些额外的图像,仅从一个特定的构建

更新

在阅读了下面 d4nyll 的非常好的答案后,这是向前迈出的一大步,我想为这个问题添加更多限制;)首先,让我总结一下答案:

向前迈出的一大步,但我仍在努力研究如何在不增加不必要的复杂性的情况下将其融入我的使用场景。

在我的例子中,一个要求是编写 Docker 文件并将它们签入源代码控制系统的应用程序开发人员负责确保他们的 Docker 文件构建令他们满意的图像.他们不需要以特定方式 "so our CI/CD process does not break" 制作所有 Docker 文件。他们只需提供 Dockerfile 即可生成正确的 docker 图像。

因此,我真的无法请求他们为每个应用程序在 Dockerfile 中添加内容,只是为了 CI/CD 管道。这是 CI/CD 管道应该自行处理的事情。

我能看到使这项工作起作用的唯一方法是编写一个 Dockerfile 解析器,它将检测多阶段构建并为每个阶段注入一个标签,然后构建修改后的 Dockerfile。这是一个复杂的问题,我非常犹豫是否要添加到 CI/CD 管道中。

我有更好(更简单)的选择吗?

由于 ZachEddy and thaJeztah mentioned 在您链接到的问题之一中,您可以标记中间图像和 docker image prune 基于此标签的图像。

Dockerfile(使用多阶段构建)

FROM node as builder
LABEL stage=builder
...

FROM node:dubnium-alpine
...

构建图像后,运行:

$ docker image prune --filter label=stage=builder

对于自动化服务器(例如 Jenkins)

如果您运行在自动化服务器(例如 Jenkins)中构建构建,并且只想从该构建中删除中间图像,您可以

  1. 在您的 Jenkins 构建中设置一个唯一的构建 ID 作为环境变量
  2. 在您的 Dockerfile
  3. 中为此构建 ID 添加 ARG 说明
  4. 将构建 ID 传递给 docker build through the --build-arg 标志
FROM node as builder
ARG BUILD_ID
LABEL stage=builder
LABEL build=$BUILD_ID
...

FROM node:dubnium-alpine
...
$ docker build --build-arg BUILD_ID .
$ docker image prune --filter label=stage=builder --filter label=build=$BUILD_ID

如果您想在映像中保留构建 ID(可能作为容器内可访问的一种文档形式),您可以添加另一个 ENV 指令,该指令采用 ARG 的值建立论点。这也允许您使用类似 environment replacement 将标签值设置为构建 ID。

FROM node as builder
ARG BUILD_ID
ENV BUILD_ID=$BUILD_ID
LABEL stage=builder
LABEL build=$BUILD_ID
...

FROM node:dubnium-alpine
...

如果您根本不想使用缓存,可以在 docker 构建命令中使用 --no-cache=true 选项

Leverage build cache

我们正是这样做的,将标签应用于 build-time 处的 Dockerfile,如下所示:

sed -i '/^FROM/a\
LABEL build_id=${env.BUILD_TAG}\
' Dockerfile

可能来不及帮助 OP,但希望这对面临同样问题的人有用。

您可以 运行 docker 构建插入另一个参数,这将自动删除中间图像:

docker build --force-rm -t myimage .

简单的方法是 运行 命令 docker rmi -f $(docker images -f "dangling=true" -q)

请使用以下命令删除所有中间图像:

docker rmi $(docker images -a|grep "<none>"|awk '=="<none>" {print }')

有点晚,但最好的选择是

docker builder prune -a