将多个体系结构(例如amd64、arm64)的图像推送到Docker Hub,并自动拉取正确的图像
我试图为不同的体系结构创建一个映像,即amd64和arm64 我创建的Dockerfile的内容完全相同 当我在我的主机(amd64上)上从此Dockerfile构建时,生成的映像将在所有其他amd64机器上运行。但是,当我尝试在arm64上运行此映像时,我将看到exec错误 罪魁祸首似乎来自我使用Ubuntu作为基础映像(将多个体系结构(例如amd64、arm64)的图像推送到Docker Hub,并自动拉取正确的图像,docker,arm,dockerfile,dockerhub,Docker,Arm,Dockerfile,Dockerhub,我试图为不同的体系结构创建一个映像,即amd64和arm64 我创建的Dockerfile的内容完全相同 当我在我的主机(amd64上)上从此Dockerfile构建时,生成的映像将在所有其他amd64机器上运行。但是,当我尝试在arm64上运行此映像时,我将看到exec错误 罪魁祸首似乎来自我使用Ubuntu作为基础映像(来自:Ubuntu:latest),它不知怎么地“知道”我在构建哪个体系结构。结果,我最终得到了一个不同的图像,这取决于我构建的架构 这本身不是问题。毕竟,我可以在amd64
来自:Ubuntu:latest
),它不知怎么地“知道”我在构建哪个体系结构。结果,我最终得到了一个不同的图像,这取决于我构建的架构
这本身不是问题。毕竟,我可以在amd64上构建一次,再在arm64上构建一次
我想做的是能够为每个架构推送一个映像,并让它们自动拉到其他机器上,而不必配置两组DockerFile。另一种说法是,我真的很想知道Ubuntu的团队是如何配置他们的图像的:最新版本和正确的架构
任何建议都将不胜感激
编辑:作为参考,我使用Docker 19.03.5。Dockerfile如下所示:
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一起使用,buildx在19.03中提供。首先,您可能需要在Linux主机上使用qemu和binfmt_misc进行交叉编译。如果没有它,您将需要为每个要构建的平台创建一个构建节点。使用binfmt_misc,您需要两个重要的细节才能在容器中工作,第一个是您需要静态用户二进制文件,第二个是将它们注入内核时需要使用
--fix binary
标志。首先,这归结为您安装的包名,例如,在Debian上,包名是qemu user static。第二,这可能需要一个不稳定版本的包。例如,以下是一些错误报告,以包括更改:
/proc/sys/fs/binfmt\u misc/*
中查找F
标志来验证--fix binary
结果
接下来,您需要设置buildx工作程序。这可以通过以下方式实现:
docker buildx创建--驱动程序docker容器--名称本地--使用\
unix:///var/run/docker.sock
docker buildx inspect--本地引导
您应该在inspect中看到如下内容,注意多个平台:
$ 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\u和_标记必须是外部注册表,buildx可以在其中推送图像。您不能在本地拥有多拱门映像,因为本地docker映像必须是单个平台,但类似注册表的docker Hub确实支持多拱门清单:
docker buildx构建平台linux/amd64、linux/arm64\
--输出类型=注册表-t$image\u和\u标记。
您甚至可以使用qemu跨平台支持测试这些其他图像:
docker容器运行——平台linux/arm64$image\u和\u标记
请注意,您可能需要在docker中启用实验性CLI选项,我忘记了哪些功能尚未进入GA。在~/.docker/config.json
中,添加:
{
"auths": {
...
},
"experimental": "enabled"
}
或者您可以导出一个变量(添加到.bashrc以使其持久化):
注意:docker desktop包含qemu/binfmt_misc的设置已经有一段时间了,因此您可以直接跳到该环境中的buildx步骤。Buildx也可以作为独立工具运行。有关更多详细信息,请参见回购协议:您正在构建哪个版本的Docker?请共享您的Docker文件或一个具有代表性的示例。@BMitch我在Docker 19.03.5上。我试图构建的Dockerfile相当简单。我已经用包含代表性样本的编辑更新了原始问题。感谢您提供的超详细指南!这比我想象的要复杂一些,但这似乎正是我想要的。我将在本周末对此进行一次尝试:)@DentonZhou如果您想在ARM主机上本机构建,您可以跳过所有qemu/binfmt_杂项部分,直接跳转到buildx与多个节点对话。
docker buildx create
命令有一个--append
选项来添加更多节点。每个体系结构需要一个节点。但是,如果您正在为低功耗设备(如Pi)进行构建,那么在更快的构建主机上进行qemu仿真可能会更好。事实上,我正在为Pi 4B进行构建,这就是我最初发现自己处于这个兔子洞的原因。在我的笔记本电脑上构建一些只需花费很少时间的东西,在Pi上大约需要半个小时!我不认为需要太频繁地重建此图像,因此我现在可以跳过qemu,并尝试使用buildx的--append
选项。谢谢你的建议!
export DOCKER_CLI_EXPERIMENTAL=enabled