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

时间:2018-05-02 03:32:42

标签: docker

使用

构建多阶段Dockerfile时
docker build -t myimage .

它生成标记为myimage的最终图像,以及中间图像。要完全清楚,我们在这里谈的不是关于容器,而是关于图像。它看起来像这样:

enter image description here

查看这些<none>张图片?这就是我所说的。

现在已经在某种程度上讨论了这个“问题”herehere

以下是一些相关部分:

  

如果这些中间图像会被自动清除/修剪,那么构建缓存将随着每次构建而消失,因此每次强制您重建整个图像。

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

有些人这样做:

  

目前,我在docker image prune -f命令之后使用docker build -t app .来清理那些中间图像。

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

  

它删除了“所有悬空图像”,因此在共享环境(如Jenkins奴隶)中,它更像是在脚下射击。 :)

这是我发现自己的一个场景。

所以没有什么可以在Docker端“修复”。但是如何才能删除那些额外的图片,仅从一个特定的构建

更新

从下面的d4nyll中读到非常好的答案,这是向前迈出的一大步,我想在这个问题上添加一些限制;)首先,让我总结一下答案:

  • 可以使用ARG将构建ID从CI / CD传递给Dockerfile构建器
  • 然后可以使用LABEL语法将构建ID元数据添加到正在构建的舞台图像
  • 然后可以使用docker image prune命令的--filter选项仅删除具有当前构建ID的图像

向前迈出了一大步,但我仍然在努力将其融入我的使用场景,而不会增加不必要的复杂性。

在我的情况下,要求是编写Dockerfiles并将其检入源控制系统的应用程序开发人员负责确保他们的Dockerfiles构建满意的映像。他们不需要以特定的方式制作他们所有的Dockerfiles,“所以我们的CI / CD过程不会破坏”。他们只需提供Dockerfile即可生成正确的泊坞窗图像。

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

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

我有更好的(阅读更简单)选项吗?

5 个答案:

答案 0 :(得分:3)

ZachEddythaJeztah 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内为此构建ID添加ARG指令
  3. 通过docker build标志将内部版本ID传递到--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
...

答案 1 :(得分:2)

我们正在这样做,在构建时将标签应用于Dockerfile,如下所示:

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

为帮助OP可能为时已晚,但希望这对面临相同问题的人很有用。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

如果根本不想使用缓存,则可以在docker build命令上使用--no-cache = true选项

Leverage build cache

答案 4 :(得分:0)

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

docker build --force-rm -t myimage .