我有一个go web服务,我一直在用docker build
构建,并在我的M1 Mac和各种Linux机器上用docker run
运行了一段时间。它是一个安装在distroless基础上的简单二进制文件,运行得很好。现在我想导出一个多平台映像,发送给同事在他们的计算机(M1和Intel Mac)上运行。我已经这样导出了一个OC:
docker buildx build --platform linux/amd64,linux/arm64 -t toy -o type=oci,dest=toy.oci .
导入工作正常:
docker image import toy.oci toy
sha256:02f7342d9d6ec2a1b66440aedb8d9a6ae0e968373fc8f2b698f7c8e73e6747e0
运行它是另一回事:
docker run -d --name toy -p 4242:4242 toy:latest
docker: Error response from daemon: No command specified.
See 'docker run --help'.
这很奇怪,因为我的Dockerfile有一个ENTRYPOINT
。不管怎样,我试着告诉它要运行的命令:
docker run -d --name toy -p 4242:4242 toy:latest /bin/toy
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "/bin/toy": stat /bin/toy: no such file or directory: unknown.
几乎就像容器里没有文件一样!docker image ls
显示了我的32 MB图像,所以我知道那里有东西,但是它在哪里?是不是缺少了一个图层?
FWIW我也试过type=tar
,得到了同样的结果。
我想我错过了一个步骤,但我的DuckDuckGo-foo失败了。如何构建实际工作的可导出多平台Docker映像?
3条答案
按热度按时间uplii1fm1#
这里同时发生了几件事:
docker load
。docker import
命令从容器加载文件系统导出,并且不包含任何映像元数据。docker load
命令需要与OCI布局不同的自己的元数据。我在
regctl
中有一个功能,可以提取特定的平台,并执行刚刚签入到main中的转换(因此它将在v0.4.5中发布,或者如果您不想自己构建它,可以直接从GHA提取二进制文件)。从Docker转换到containerd进行映像管理时,此行为将发生变化。发生这种情况时,多平台映像可以直接加载到Docker中,并且其导入命令应直接支持OCI布局。截至本次更新,这在Docker Desktop中处于试验阶段,尚未随Linux上的Docker引擎发布。
wgeznvg72#
我在M1上使用多拱支架构建图像的方法是:
docker buildx create --bootstrap
docker buildx ls
上,并且已选中该平台,节点名称旁边有一个星号,否则运行:docker buildx use [node]
.docker buildx build --platform linux/amd64,linux/arm64 -t sample:v1 . --push
。这会将映像推送到注册表。一旦图像在注册表中,你的同事就可以开始拉它了。这是最简单的方法,因为我在过去尝试其他目标输出时遇到过问题。
sczxawaw3#
@BMitch的回答很好地解决了这里的各种问题,足以让我了解到我可以完全使用Docker。问题是缺乏对加载多平台图像的支持,因此每个平台必须有单独的图像。这方面的咒语是:
然后,可以与任何人共享各个tar文件,并加载:
在AMD 64平台上切换到
toy-amd64.tar
。为了好玩,我创建了
make
目标来执行构建和加载,如下所示: