Docker:为多个体系结构导出映像

gg58donl  于 2022-12-18  发布在  Docker
关注(0)|答案(3)|浏览(158)

我有一个场景,我需要以可导出、可传输的格式捆绑多容器系统。具体来说,我需要从Docker Hub获取映像并将其存储在便携式媒体(例如USB驱动器)上,然后可以将其加载到没有互联网接入的气隙计算机中。
我通常可以这样做:

# On the development server
docker pull nginx:1.23
docker save -o nginx.tar nginx:1.23

... store the .tar on portable media...

# On the air-gapped machine
docker load < myimage.tar

然而,尽管映像是为多个体系结构构建的,并且支持多个体系结构,但这似乎只存储了单个体系结构(运行docker pull的计算机的体系结构)的映像。我需要它将所有体系结构的映像导出到.tar文件,以便可以将它们加载到任何体系结构的计算机上。
我试过了

docker pull --platform linux/amd64 nginx:1.23
docker pull --platform linux/arm64 nginx:1.23

手动指定amd64arm64映像都应该被提取,但是docker save仍然只导出一个映像(我们可以从manifest.json文件只有一个条目的事实中看出这一点)。
我也试过:

docker pull --platform linux/amd64 --platform linux/arm64 nginx:1.23

但结果是一样的。
当我docker load映像时,如何导出/保存支持多个不同体系结构的映像?理想情况下,我可以在任何支持体系结构的计算机上docker load单个.tar文件,让它导入该体系结构的映像,然后运行该映像。

编辑:

经过进一步测试,我发现如果我执行以下操作:

docker pull --platform linux/amd64 nginx:1.23
docker save -o nginx.tar

那么.tar文件中有一个manifest.json,它只有一个图像(对于amd64)。

docker pull --platform linux/arm64 nginx:1.23
docker save -o nginx.tar

那么.tar文件包含一个manifest.json,其中包含两个图像(amd64arm64)。
不过,这不是“你必须两个都拉”的问题;如果我再次提取amd64版本,然后再次提取docker save,我们将返回到manifest.json中的单个图像。

3pmvbmvn

3pmvbmvn1#

摘自我关于上级DevOps SE的帖子:

这个问题在Docker blog post on multi-platform docker builds中得到了解答。对于您的特定情况,您可以为每个平台执行构建和推送,然后创建一个清单文件并推送它。然后您可以执行保存。它看起来像这样:

$ docker buildx build --platform linux/amd64 --push -t localhost:5000/myimage:amd64 .
$ docker buildx build --platform linux/arm64 --push -t localhost:5000/myimage:arm64 .
$ docker manifest create myimage:latest myimage:amd64 myimage:arm64
$ docker manifest push localhost:5000/myimage:latest
$ docker image save -o myimage.tar localhost:5000/myimage:latest
pdsfdshx

pdsfdshx2#

当我用docker加载一个映像时,如何导出/保存它并支持多个不同的架构?理想情况下,我可以在任何支持架构的机器上用docker加载一个.tar文件,让它导入该架构的映像,然后运行该映像。
目前,你还不能。docker引擎目前只支持单一平台的镜像,所以当你拉一个镜像时,它会被你选择的平台解引用。随着docker如何使用containerd后端,这很快就会改变,因为containerd支持多平台镜像。在那之前,可以存储多平台映像的两个位置是使用注册表和使用OCI布局语法将映像存储在磁盘上(该格式与docker saveload使用的格式略有不同)。
在注册表和/或OCI布局之间进行复制时,你不需要Docker引擎。各种工具都支持这一点,包括Google的起重机、RedHat的skopeo和我自己的regclient。例如,在一个隔离的环境中导入tar文件:

regctl image export nginx:1.23 nginx.tar
# copy tar image to host in isolated environment
regctl image import internal-registry.example.org/library/nginx nginx.tar
docker pull internal-registry.example.org/library/nginx
mqxuamgl

mqxuamgl3#

如果您正在从本地计算机构建和推送平台映像,使用--load而不是--push可以让您不必推送2个您并不真正需要的映像?
如果在推送清单之后您仍然需要得到的latest映像,您仍然可以在最后拉入。

$ docker buildx build --platform linux/amd64 --load -t myimage:amd64 .
$ docker buildx build --platform linux/arm64 --load -t myimage:arm64 .
$ docker manifest create myimage:latest myimage:amd64 myimage:arm64
$ docker manifest push localhost:5000/myimage:latest
$ docker image save -o myimage.tar localhost:5000/myimage:latest

然后清除未使用的:

echo y | docker rmi $(docker images --filter=reference=myimage:amd64 --format "{{.ID}}")

echo y | docker rmi $(docker images --filter=reference=myimage:arm64 --format "{{.ID}}")

相关问题