在一个 Docker 构建阶段构建 .deb 包,在另一阶段安装,但 .deb 包本身不会占用最终映像中的空间?

问题描述 投票:0回答:1

我有一个多阶段 Docker 构建文件。第一阶段创建一个可安装包(例如 .deb 文件)。第二阶段只需要安装.deb包即可。

这是一个例子:

FROM debian:buster AS build_layer
COPY src/ /src/
WORKDIR /src
RUN ./build_deb.sh
# A lot of stuff happens here and a big huge .deb package pops out. 
# Suppose the package is 300MB.

FROM debian:buster AS app_layer
COPY --from=build_layer /src/myapp.deb /
RUN dpkg -i /myapp.deb && rm /myapp.deb
ENTRYPOINT ["/usr/bin/myapp"]

# This image will be well over 600MB, since it contains both the
# installed package as well as the deleted copy of the .deb file.

这样做的问题是

COPY
阶段在自己的层中运行,并将大型 .deb 包放入最终的构建上下文中。然后,下一步将安装该软件包并删除 .deb 文件。但是,由于
COPY
阶段必须独立执行,因此 .deb 包仍然占用最终映像中的空间。如果它是一个小包,您可能只是处理它,但在我的情况下,包文件有数百 MB,因此它在最终构建层中的存在确实显着增加了图像大小,但没有任何好处。

SO 上有相关帖子,例如 thisone 讨论包含机密的文件,以及 thisone 用于将大型安装程序从容器外部复制到容器中(该解决方案仍然有点janky,要求您运行临时的本地 http 服务器)。然而,这些都没有解决需要从另一个构建阶段复制但不将复制的文件保留在最终包中的情况。 我能想到的唯一方法是扩展 Web 服务器的想法并提供 SFTP 或类似服务器,以便构建层可以将包上传到某个地方。但这也需要额外的基础设施,现在您还需要处理 SSH 机密等,这开始变得非常复杂,并且在其他开发人员的系统或 CI/CD 环境中的重现性要差很多。

或者,我可以使用 BuildKit 中的

--squash

选项,但这最终会破坏图层系统的优势。然后,我无法在多个映像中重用类似的层(例如,该映像现在无法利用 Debian 基础映像可能已存在于最终用户系统上的事实)。这将最大限度地减少空间使用,但由于许多其他原因,这并不理想。

解决这个问题的推荐方法是什么?

您只需使用
docker dockerfile docker-build
1个回答
0
投票
命令即可挂载构建层:

FROM debian:buster AS build_layer
COPY src/ /src/
WORKDIR /src
RUN ./build_deb.sh

FROM debian:buster AS app_layer
RUN --mount=type=bind,from=build_layer,target=/mnt dpkg -i /mnt/src/myapp.deb
ENTRYPOINT ["/usr/bin/myapp"]


© www.soinside.com 2019 - 2024. All rights reserved.