交叉编译多架构容器
Cross-compile multi-arch containers
我正在尝试构建一个 ARM (arm32v7) 容器,但使用 x86_64 主机。虽然我知道有一些非常酷的东西,比如 Resin using Qemu shenanigans, and Multiarch 用于通用容器的交叉构建,但我有一个小问题:我尝试构建的容器开始时是多架构的,所以 Docker 总是选择FROM
指令中的 x86 图像。
我想在 x86 主机上从 Multi-arch Rust image 构建一个 ARM 容器。问题是,我找不到任何文档明确说明我想从 ARM 容器开始并从中构建,而不是 x86 容器。此外,图像上的标签不会消除歧义,所以我不能将它们用于 select 起始容器。
我尝试编辑 /etc/docker/daemon.json
文件以包含:
{
"labels": [ "os=linux", "arch=arm32v7" ],
"experimental": true
}
但这根本没有帮助。 docker pull
仍然检索 x86 图像。所有这一切的目的是最终 运行 在 Raspberry Pi 上提高容器的编译时间;就目前而言,编译时间非常慢。
有什么方法可以明确说明我想从 ARM 映像开始构建?
可以为另一个架构("cross-compile")构建简单的 Docker 容器,方法是使用适合该架构的基础映像。简单来说,我的意思是不需要在 Docker 文件中使用 RUN
命令来构建图像。这是因为 Docker 没有能力在另一个架构的容器中实际 运行 命令。虽然这听起来有限制,但与 multi-stage builds 到 cross-compile 代码结合使用时会非常强大。
让我们来看看这个 step-by-step。首先,让我们为 Docker 客户端启用实验模式,通过将以下选项添加到 ~/.docker/config.json
:
来启用 docker manifest
{
"experimental": "enabled"
}
然后我们可以使用 docker manifest inspect debian:stretch
来显示 fat manifest that contains a digest for the image in the architecture we want to build for. For example, the arm32v7 image has "architecture": "arm"
and "variant": "v7"
specified under the platform
key. Using jq,我们可以通过编程方式提取此图像的摘要:
docker manifest inspect debian:stretch | jq -r '.manifests[] | select(.platform.architecture == "arm" and .platform.variant == "v7") | .digest'`
此摘要随后可用于 Docker 文件中的 FROM
命令:
FROM debian@sha256:d01d682bdbacb520a434490018bfd86d76521c740af8d8dbd02397c3415759b1
然后可以 COPY
cross-compiled 二进制到图像中。该二进制文件可能来自您机器上的 cross-compiler 或 multi-stage 构建中的另一个容器。要删除 Docker 文件的 FROM
行中的 hard-coded 摘要,可以通过 Docker build argument (ARG
).
将其外部化
我正在尝试构建一个 ARM (arm32v7) 容器,但使用 x86_64 主机。虽然我知道有一些非常酷的东西,比如 Resin using Qemu shenanigans, and Multiarch 用于通用容器的交叉构建,但我有一个小问题:我尝试构建的容器开始时是多架构的,所以 Docker 总是选择FROM
指令中的 x86 图像。
我想在 x86 主机上从 Multi-arch Rust image 构建一个 ARM 容器。问题是,我找不到任何文档明确说明我想从 ARM 容器开始并从中构建,而不是 x86 容器。此外,图像上的标签不会消除歧义,所以我不能将它们用于 select 起始容器。
我尝试编辑 /etc/docker/daemon.json
文件以包含:
{
"labels": [ "os=linux", "arch=arm32v7" ],
"experimental": true
}
但这根本没有帮助。 docker pull
仍然检索 x86 图像。所有这一切的目的是最终 运行 在 Raspberry Pi 上提高容器的编译时间;就目前而言,编译时间非常慢。
有什么方法可以明确说明我想从 ARM 映像开始构建?
可以为另一个架构("cross-compile")构建简单的 Docker 容器,方法是使用适合该架构的基础映像。简单来说,我的意思是不需要在 Docker 文件中使用 RUN
命令来构建图像。这是因为 Docker 没有能力在另一个架构的容器中实际 运行 命令。虽然这听起来有限制,但与 multi-stage builds 到 cross-compile 代码结合使用时会非常强大。
让我们来看看这个 step-by-step。首先,让我们为 Docker 客户端启用实验模式,通过将以下选项添加到 ~/.docker/config.json
:
docker manifest
{
"experimental": "enabled"
}
然后我们可以使用 docker manifest inspect debian:stretch
来显示 fat manifest that contains a digest for the image in the architecture we want to build for. For example, the arm32v7 image has "architecture": "arm"
and "variant": "v7"
specified under the platform
key. Using jq,我们可以通过编程方式提取此图像的摘要:
docker manifest inspect debian:stretch | jq -r '.manifests[] | select(.platform.architecture == "arm" and .platform.variant == "v7") | .digest'`
此摘要随后可用于 Docker 文件中的 FROM
命令:
FROM debian@sha256:d01d682bdbacb520a434490018bfd86d76521c740af8d8dbd02397c3415759b1
然后可以 COPY
cross-compiled 二进制到图像中。该二进制文件可能来自您机器上的 cross-compiler 或 multi-stage 构建中的另一个容器。要删除 Docker 文件的 FROM
行中的 hard-coded 摘要,可以通过 Docker build argument (ARG
).