使用 docker 与许多交叉构建工具链

Using docker with many cross build toolchains

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

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

现在我们不断从客户那里获得工具链,有时还会获得这些工具链的新版本。 因此,我们的 docker 图像增长很快,目前使用了大约 40GB。更糟糕的是,如果我们需要 add/modify/remove 一个工具链,那么构建一个新的 docker 图像所花费的时间就更糟了。

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

为每个工具链使用单独的 docker 图像将节省每次构建巨大的单个 docker 图像的时间。但当涉及到 space 时情况更糟(因为每个 docker 图像都包含带有构建工具等的 Linux 子系统)。

对于如何以更好的方式执行此操作的任何提示,我会很高兴。

图层

Using a separate docker image for each toolchain would save time for building the huge single docker image each time. But it's even worse when it comes to space (because each docker image would contain the Linux subsystem with build tools etc).

由于名为 layers 的 Docker 功能,这主要是不正确的。

什么是图层?每次你在 Docker 文件中有一个命令时,都会创建一个新层,其中包含自上一层创建以来更改的文件。一旦创建,层是不可变的。

这会给你带来两样东西。

  • 它带给您的第一件事就是您可以拥有“构建缓存”。如果您更改 Docker 文件中的最后一个命令,并且 re-run 整个文件,则只有最后一个命令需要 re-run。其他一切都将从缓存中获取。
  • 它完成的第二件事是,如果多个 docker 图像具有相同的图层,它们可以在磁盘上共享这些图层。第一次使用基于 Ubuntu 的图像时,会花费几 GB 的费用。第二次,不花钱

构建自定义基础映像

之前,我说“大部分”不是真的。有什么注意事项?

有一种方法可以减小许多不同图像的大小。如果您可以识别其中许多人使用的共同依赖项,它可以节省 space 将该依赖项提取到“基本图像”中。

假设您有两个 Docker 图像,由以下 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 不能说它们是相同的。这是浪费 space.

您可以做的是创建一个 Docker 定义基本图像的文件:

# 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 副本 on-disk。