将Docker与许多交叉构建工具链一起使用

问题描述

在我的团队中,我们目前使用单个docker映像进行交叉构建软件库,在一个docker映像(/ opt / ...)中添加多个交叉构建工具链。 Dockerfile和工具链都在一个git存储库中(工具链通过git-lfs归档)。

Dockerfile方便了对构建环境的全面正式描述,可以在不同的机器上使用。

现在,我们不断从客户那里获得工具链,有时还会获得这些工具链的新版本。 因此,我们的docker映像正在快速增长,目前使用约40GB。更糟糕的是,如果我们需要添加/修改/删除工具链,则需要花费新的时间来构建新的Docker映像。

所以我开始怀疑我们是否以“良好实践”的方式来做事情。

为每个工具链使用单独的docker映像将节省每次构建大型单个docker映像的时间。但是在空间方面更糟(因为每个docker镜像都包含带有构建工具等的Linux子系统)。

我很高兴能以更好的方式完成此操作。

  • 是否有任何“既定”方式来处理这种情况?
  • 其他团队如何处理此用例?

解决方法

为每个工具链使用单独的docker映像将节省每次构建大型单个docker映像的时间。但是在空间方面更糟(因为每个docker镜像都包含带有构建工具等的Linux子系统)。

由于称为layers的Docker功能,多数情况并非如此。

什么是图层?每次在Dockerfile中有一条命令时,都会创建一个新层,其中包括自创建最后一层以来已更改的文件。创建后,图层是不可变的。

这为您买了两件事。

  • 首先得到的是您可以拥有“构建缓存”。如果更改Dockerfile中的最后一个命令,然后重新运行整个程序,则仅需要重新运行最后一个命令。其他所有内容将从缓存中获取。
  • 它完成的第二件事是,如果多个docker映像具有相同的层,则它们可以共享磁盘上的这些层。第一次使用基于Ubuntu的映像时,它将花费数GB。第二次,它不会花费任何费用。

构建自定义基本图片

在此之前,我说过“大部分”是不正确的。请注意什么?

有一种减小许多不同图像尺寸的方法。如果您可以识别许多人使用的公共依赖项,则可以节省空间以将该依赖关系提取到“基本映像”中。

想象一下,您有两个由以下Dockerfile定义的Docker映像:

# Image A
FROM ubuntu:latest
RUN apt-get install -y foo
RUN apt-get install -y gcc
# Image B
FROM ubuntu:latest
RUN apt-get install -y bar
RUN apt-get install -y gcc

在这里,我们有两个映像,并且两个映像都安装了gcc。但是,这两次安装的gcc将创建两层,因为Docker无法说出它们是相同的。这是浪费空间。

您可以做的是创建一个定义基本映像的Dockerfile:

# Base image
FROM ubuntu:latest
RUN apt-get install -y gcc

然后,您运行docker build -t my-cool-base-image .

现在,您可以像这样引用基本图像:

# Image A
FROM my-cool-base-image:latest
RUN apt-get install -y foo
# No need to install gcc here

现在,您的两个容器将共享磁盘上gcc的单个副本。