英文:
How do I make multi-arch Docker images?
问题
我已为一个CLI工具创建了一个Dockerfile,在我的Linux笔记本电脑上运行得很好。我尝试在安装了Docker的树莓派上运行容器,但它无法工作。
我知道许多公司创建镜像以支持多种架构,他们是如何做到这一点的?
我想知道这个,因为我希望CLI的容器可以部署到树莓派,以及我的Linux笔记本电脑。
英文:
I've created a Dockerfile for a CLI utility, and it works great on my Linux laptop. I tried running the container on a Raspberry Pi with Docker installed, but it won't work.
I know myriad companies create images to support multiple architectures, how are they doing this?
I want to know, because I want the container for the CLI to be deployable to a Raspberry Pi, as well as my Linux laptop.
答案1
得分: 7
我知道其他公司是如何创建支持多个架构的镜像的,他们是如何做到这一点的?
简而言之,创建一个单一的镜像以支持多个架构是不可能的。但是,看起来好像一个镜像可以满足多个架构,因为实际上您正在与清单文件进行交互。清单文件充当指针,根据请求镜像的Docker客户端,指向正确的镜像。
例如,您可以在x86_64
平台(例如您的Linux笔记本电脑)上运行docker build
,然后在armv7l
平台(例如树莓派)上再次运行,将创建两个完全不同的镜像。应该给生成的镜像指定特定于平台的名称,并将其推送到您的Docker镜像存储库(例如hub.docker.com
)。
完成后,您需要在Docker CLI中启用实验性模式,并且使用平台中性名称创建并上传清单文件,该文件指向相应的特定于平台的镜像。
简而言之,以下三个命令将完成任务(假设您从x86_64
机器工作):
docker manifest create <new-list-ref-name> <image-ref> [<image-ref>...]
docker manifest annotate <new-list-ref-name> <image-ref> --os linux --arch arm
docker manifest push <new-list-ref-name> [--purge]
**注意:**根据您是否使用多架构基础镜像,您可能不需要docker manifest annotate
步骤。
**注意:**在推送清单文件时(即docker manifest push ...
),请确保使用--purge
选项;这在链接的文章中没有讨论。如果您计划在以后重复使用的标签(例如latest
)上使用标签,不使用--purge
将会让您感到困扰。
英文:
> I know other companies create images to support multiple architectures, how are they doing this?
The quick answer is that it is NOT possible to create a single image that will support multiple architectures. However, it appears as if one image will satisfy multiple architectures because you are actually interacting with a manifest file. A manifest file acts as a pointer to the correct image based on the Docker client that requested the image.
For example, you can run docker build
on an x86_64
platform (e.g. your Linux laptop) and again on an armv7l
platform (e.g. a Raspberry Pi), and two completely different images will be created. The resulting images should be given platform specific names and pushed to your Docker image repository (e.g. hub.docker.com
).
Once that has been completed, then you will need to enable experimental mode in the Docker CLI, and create and upload a manifest file with a platform neutral name that points to the corresponding platform specific images.
TL;DR These three commands will do the trick (assuming you are working from the x86_64
machine)
docker manifest create <new-list-ref-name> <image-ref> [<image-ref>...]
docker manifest annotate <new-list-ref-name> <image-ref> --os linux --arch arm
docker manifest push <new-list-ref-name> [--purge]
NOTE: Depending on whether or not you are using a multi-arch base image, you may not need the docker manifest annotate
step.
NOTE: When pushing a manifest file (i.e. docker manifest push ...
), be sure to use the --purge
option; it is not discussed in the linked articles. Not using --purge
, will cause you heartache if you plan on using a tag that will be reused at a later time (e.g. latest
).
答案2
得分: 4
buildx 可用于生成多架构清单列表和推送到仓库的镜像。当您从仓库拉取时,将检索到适用于您平台的适当清单。
这在19.03版本中作为CLI插件提供,当CLI处于实验模式时可用。您可以通过以下方式启用它:
export DOCKER_CLI_EXPERIMENTAL=enabled
对于多节点构建环境,请使用 docker buildx create
配置您的构建器实例,使用 --append
选项将更多节点添加到构建器。然后在该构建器上使用 docker buildx use
来执行您的命令。
要在单节点上进行仿真构建,可以在基于Debian的系统上安装最新的 qemu-user-static
(其他Linux发行版的软件包名称可能有所不同),例如:
apt-get install -t testing 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/qemu-*
中 F
标志的 binfmt_misc 设置的 qemu 后,您可以在本地主机上使用以下命令进行交叉编译:
docker buildx create --driver docker-container --name local \
--use unix:///var/run/docker.sock
docker buildx inspect --bootstrap local
然后,使用以下命令构建多架构镜像:
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
-t $registry_img_and_tag --output type=registry .
使用 --platform
包括您想要支持的每个平台。
我有一个关于此内容的演示。使用 P
查看演示备注。使用 FROM --platform=$TARGETPLATFROM
对于避免需要为其他平台拉取新镜像很有用。
英文:
buildx can be used to generate a multi-arch manifest list and images that are pushed to a registry. When you pull that from the registry, the appropriate manifest for your platform is retrieved.
This is available in 19.03 as a CLI plugin that is available when the CLI is in experimental mode. You can enable this by:
export DOCKER_CLI_EXPERIMENTAL=enabled
For a multi-node builder environment, configure your builder instance with docker buildx create
, using the --append
option to add more nodes to the builder. Then docker buildx use
on that builder to use the instance for your commands.
For building on a single node with emulation, that can be done on debian based systems by installing the latest qemu-user-static
(package name may vary for other Linux distributions), e.g.:
apt-get install -t testing qemu-user-static
For an explanation of why a newer release is needed, see:
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=868030
- https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/1815100
Once you have qemu installed with binfmt_misc setup with the F
flag in /proc/sys/fs/binfmt_misc/qemu-*
, then you can cross compile on your local host using:
docker buildx create --driver docker-container --name local \
--use unix:///var/run/docker.sock
docker buildx inspect --bootstrap local
You then build the multi-architecture image with:
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
-t $registry_img_and_tag --output type=registry .
Include each platform you want to support with --platform
.
I've got a presentation covering this. Use P
to see the presenter notes. Using FROM --platform=$TARGETPLATFROM
is useful to avoid needing to pull fresh images for other platforms.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论