将图像推送到 Docker 多个架构的集线器(例如 amd64、arm64)并自动拉取正确的一个
Pushing images to Docker Hub for multiple architectures (e.g. amd64, arm64) and pulling the correct one automatically
我正在尝试为不同的体系结构创建一个映像,即 amd64 和 arm64。
我创建的Docker文件的内容完全相同。
当我在 amd64 主机上从这个 Docker 文件构建时,生成的映像将在所有其他 amd64 机器上 运行。但是,当我尝试在 arm64 上 运行 此图像时,我会看到执行错误。
罪魁祸首似乎源于我使用 Ubuntu 作为基础图像 (FROM: ubuntu:latest
),这不知何故 "knows" 我正在构建的架构。结果,我最终得到了不同的图像,具体取决于我正在构建的架构。
这本身不是问题。毕竟,我可以在 amd64 上构建一次,然后在 arm64 上构建一次。
我想做的是能够为每个架构推送一个映像,并让它们自动拉到其他机器,而无需配置两组 Docker文件。另一种说法是,我真的很想知道 Ubuntu 的团队如何配置他们的图像,以便 :latest 提取最新版本 和 正确的架构。
如有任何建议,我们将不胜感激!
编辑:作为参考,我使用的是 Docker 19.03.5。 Docker文件如下所示:
FROM ubuntu:latest
COPY /requirements.txt /tmp/
RUN apt-get update && \
apt-get install -y python3-pip python3-dev build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev && \
apt-get install -y libtiff5-dev libjpeg8-dev zlib1g-dev
RUN cd /usr/local/bin && \
ln -s /usr/bin/python3 python && \
pip3 install --upgrade pip
RUN pip install lxml && \
pip install -r /tmp/requirements.txt && \
pip install gunicorn
我建议将 BuildKit 与 buildx 一起使用,它在 19.03 中可用。首先,您可能需要在 Linux 主机上使用 qemu 和 binfmt_misc 进行交叉编译。没有它,您将需要为每个要构建的平台创建一个构建节点。使用 binfmt_misc,您需要两个重要细节才能在容器内工作,首先是您需要静态用户二进制文件,其次是将它们注入内核时需要使用 --fix-binary
标志。首先,这归结为您安装的包名称,例如在 Debian 上,包名称是 qemu-user-static。其次,这可能需要来自不稳定版本的软件包版本。例如。这里有一些包含更改的错误报告:
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=868030
- https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1815100
完成此操作后,您可以通过在 /proc/sys/fs/binfmt_misc/*
.
中查找 F
标志来验证 --fix-binary
结果
接下来,您需要设置一个buildx worker。这可以通过以下方式完成:
docker buildx create --driver docker-container --name local --use \
unix:///var/run/docker.sock
docker buildx inspect --bootstrap local
您应该从检查中看到类似以下内容,注意多个平台:
$ docker buildx inspect --bootstrap local
[+] Building 54.1s (1/1) FINISHED
=> [internal] booting buildkit 54.1s
=> => pulling image moby/buildkit:buildx-stable-1 45.4s
=> => creating container buildx_buildkit_local0 8.7s
Name: local
Driver: docker-container
Nodes:
Name: local0
Endpoint: unix:///var/run/docker.sock
Status: running
Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
现在您可以为多个体系结构执行构建。 $image_and_tag
必须是外部注册表,buildx 可以在其中推送映像。您不能在本地拥有多架构镜像,因为 docker 本地镜像必须是单一平台,但像 Docker Hub 这样的注册表确实支持多架构清单:
docker buildx build --platform linux/amd64,linux/arm64 \
--output type=registry -t $image_and_tag .
您甚至可以使用 qemu 跨平台支持测试其他图像:
docker container run --platform linux/arm64 $image_and_tag
请注意,您可能需要在 docker 中启用实验性 CLI 选项,我忘记了哪些功能尚未进入 GA。在~/.docker/config.json
中添加:
{
"auths": {
...
},
"experimental": "enabled"
}
或者您可以导出一个变量(添加到您的 .bashrc 以使其持久化):
export DOCKER_CLI_EXPERIMENTAL=enabled
注意:docker 桌面已包含 qemu/binfmt_misc 的设置一段时间,因此您可以直接跳到该环境中的 buildx 步骤。 Buildx 也可以 运行 作为一个独立的工具。有关详细信息,请参阅存储库:https://github.com/docker/buildx
我正在尝试为不同的体系结构创建一个映像,即 amd64 和 arm64。
我创建的Docker文件的内容完全相同。
当我在 amd64 主机上从这个 Docker 文件构建时,生成的映像将在所有其他 amd64 机器上 运行。但是,当我尝试在 arm64 上 运行 此图像时,我会看到执行错误。
罪魁祸首似乎源于我使用 Ubuntu 作为基础图像 (FROM: ubuntu:latest
),这不知何故 "knows" 我正在构建的架构。结果,我最终得到了不同的图像,具体取决于我正在构建的架构。
这本身不是问题。毕竟,我可以在 amd64 上构建一次,然后在 arm64 上构建一次。
我想做的是能够为每个架构推送一个映像,并让它们自动拉到其他机器,而无需配置两组 Docker文件。另一种说法是,我真的很想知道 Ubuntu 的团队如何配置他们的图像,以便 :latest 提取最新版本 和 正确的架构。
如有任何建议,我们将不胜感激!
编辑:作为参考,我使用的是 Docker 19.03.5。 Docker文件如下所示:
FROM ubuntu:latest
COPY /requirements.txt /tmp/
RUN apt-get update && \
apt-get install -y python3-pip python3-dev build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev && \
apt-get install -y libtiff5-dev libjpeg8-dev zlib1g-dev
RUN cd /usr/local/bin && \
ln -s /usr/bin/python3 python && \
pip3 install --upgrade pip
RUN pip install lxml && \
pip install -r /tmp/requirements.txt && \
pip install gunicorn
我建议将 BuildKit 与 buildx 一起使用,它在 19.03 中可用。首先,您可能需要在 Linux 主机上使用 qemu 和 binfmt_misc 进行交叉编译。没有它,您将需要为每个要构建的平台创建一个构建节点。使用 binfmt_misc,您需要两个重要细节才能在容器内工作,首先是您需要静态用户二进制文件,其次是将它们注入内核时需要使用 --fix-binary
标志。首先,这归结为您安装的包名称,例如在 Debian 上,包名称是 qemu-user-static。其次,这可能需要来自不稳定版本的软件包版本。例如。这里有一些包含更改的错误报告:
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=868030
- https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1815100
完成此操作后,您可以通过在 /proc/sys/fs/binfmt_misc/*
.
F
标志来验证 --fix-binary
结果
接下来,您需要设置一个buildx worker。这可以通过以下方式完成:
docker buildx create --driver docker-container --name local --use \
unix:///var/run/docker.sock
docker buildx inspect --bootstrap local
您应该从检查中看到类似以下内容,注意多个平台:
$ docker buildx inspect --bootstrap local
[+] Building 54.1s (1/1) FINISHED
=> [internal] booting buildkit 54.1s
=> => pulling image moby/buildkit:buildx-stable-1 45.4s
=> => creating container buildx_buildkit_local0 8.7s
Name: local
Driver: docker-container
Nodes:
Name: local0
Endpoint: unix:///var/run/docker.sock
Status: running
Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
现在您可以为多个体系结构执行构建。 $image_and_tag
必须是外部注册表,buildx 可以在其中推送映像。您不能在本地拥有多架构镜像,因为 docker 本地镜像必须是单一平台,但像 Docker Hub 这样的注册表确实支持多架构清单:
docker buildx build --platform linux/amd64,linux/arm64 \
--output type=registry -t $image_and_tag .
您甚至可以使用 qemu 跨平台支持测试其他图像:
docker container run --platform linux/arm64 $image_and_tag
请注意,您可能需要在 docker 中启用实验性 CLI 选项,我忘记了哪些功能尚未进入 GA。在~/.docker/config.json
中添加:
{
"auths": {
...
},
"experimental": "enabled"
}
或者您可以导出一个变量(添加到您的 .bashrc 以使其持久化):
export DOCKER_CLI_EXPERIMENTAL=enabled
注意:docker 桌面已包含 qemu/binfmt_misc 的设置一段时间,因此您可以直接跳到该环境中的 buildx 步骤。 Buildx 也可以 运行 作为一个独立的工具。有关详细信息,请参阅存储库:https://github.com/docker/buildx