我正在尝试构建一个多平台(linux/a 64,linux/arm64)节点映像。据我所知,我可以尝试corss-编译方法。使用docker构建并推送到码头注册中心不会引发任何错误。在构建机器上运行映像也很好,但是在我的raspberry-pi4 (运行ubuntu 64位)上,在提取映像后会发生以下操作
exec /usr/local/bin/docker-entrypoint.sh: exec格式错误
我的Dockerfile:
FROM --platform=$BUILDPLATFORM node:18-alpine as node
WORKDIR /usr/src/app
RUN echo "console.log('hello world!');" > main.js
EXPOSE 4000
CMD [ "node", "main.js" ]我以以下方式塑造和推动我的形象:
docker buildx build --platform=linux/amd64,linux/arm64 -t buntel/node-multi-arch --push .
我以以下方式运行容器(在我的笔记本上没有问题,但在raspberry-pi上失败):
docker run --rm -it buntel/node-multi-arch
在docker注册表中,我还看到了两个平台的标记( https://hub.docker.com/r/buntel/node-multi-arch/tags )。这里出什么问题了?
更多信息:
docker buildx ls
名称/节点驱动程序/端点状态BUILDKIT平台loving_tesla *docker-容器 loving_tesla0 unix://var/run/docker.sock运行v0.10.4linux/amd64 64、linux/amd64 64/v2、linux/amd64 64/v3、linux/386默认值 默认默认运行20.10.18 linux/amd64 64、linux/386
docker buildx inspect
名称: loving_tesla驱动程序:码头-容器 节点:名称: loving_tesla0端点:unix://var/run/docker.sock状态: running : v0.10.4平台: linux/amd64 64、linux/amd64 64/v2、linux/amd64 64/v3、linux/386
笔记本电脑:docker version
Client: Version: 20.10.18 API版本: 1.41 Go版本: go1.19.1 Git提交: b40c2f6b5d构建: Sat 9月10日11:31:10 2022 OS/Arch: linux/amd64 64上下文: 默认实验:真 服务器: Engine: Version: 20.10.18 API版本: 1.41 (最低版本1.12) Go版本: go1.19.1 Git提交: e42327a6d3构建:星期六9月10日11:30:17 OS/Arch: linux/amd64 64实验: false containerd: Version: v1.6.8 GitCommit: 9cd3357b7fd7218e4aec3eae239db1f68a6ec6.mrunc:版本: 1.1.4 GitCommit: docker: 版本: 0.19.0 GitCommit: de40ad0
覆盆子-pi docker version
Client: Docker Community : 20.10.18 API版本: 1.41 Go版本: go1.18.6 Git提交: b40c2f6构建:清华9月8日23:10:58 2022 OS/Arch: linux/arm64上下文:默认实验: true 服务器: Docker引擎-社区引擎:版本: 20.10.18 API版本: 1.41 (最低版本1.12) Go版本: go1.18.6 Git提交: e42327a构建:清华9月8日23:09:16 2022 OS/Arch: linux/arm64实验: 假容器:版本: 1.6.8 GitCommit: 9cd3357b7fd7218e4aec3eae239db1f68a6ec6 runc:版本: 1.1.4 GitCommit: v1.1.40-g5fd4c4d坞-init:版本: 0.19.0 GitCommit: de40ad0
更新:
在我的例子中,我不需要模仿任何东西,因为我没有处理二进制构建。因此,对我来说,关键是在我的构建阶段使用--platform=$BUILDPLATFORM,在最后阶段使用--platform=$TARGETPLATFORM。这将使用机器的体系结构来构建我的JavaScript/类型记录。然后在收集构建工件时切换到目标体系结构,然后这些机器可以运行这些构件。
示例:
FROM node:18-alpine as node
WORKDIR /usr/src/app
RUN echo "console.log('hello world!');" > main.js
FROM --platform=$TARGETPLATFORM node:18-slim
WORKDIR /usr/src/app
COPY --from=node /usr/src/app/main.js .
CMD [ "node", "main.js" ]
EXPOSE 4000发布于 2022-10-07 18:10:27
问题是您使用的是BUILDPLATFORM,它将始终是与主机相同的架构。在这种情况下,它将永远是x86_64。您需要的是TARGETPLATFORM,它无论如何都是隐式的。您可以在对多平台码头建房的解释中看到这一点。
您可以使用docker version | grep 'OS/Arch'获取Docker信息(这将首先给客户端,然后是服务器)。
您实际上想要的是在为该平台构建时为linux/arm64使用linux/arm64映像。将其改为以下内容将有效:
FROM node:18-alpine as node
WORKDIR /usr/src/app
RUN echo "console.log('hello world!');" > main.js
EXPOSE 4000
CMD [ "node", "main.js" ]如果您仍然希望构建linux/amd64并在您的ARMv8计算机上运行它,则必须安装宾夫姆才能使用正确的Qemu模拟器注册这些x86_64二进制文件。然后,这将在您的ARM机器上模拟x86_64,您几乎肯定不想这样做。
发布于 2022-10-06 20:51:28
这两幅图像都是为构建平台而构建的,而不是使用以下行构建的目标平台:
FROM --platform=$BUILDPLATFORM ...你不想让--platform=$BUILDPLATFORM站在目标舞台上。这用于交叉编译或输出非平台特定结果的中间阶段,您可以将这些结果复制到目标阶段。
有关由buildkit定义的这些变量的更多详细信息,请访问:https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope。
我还会将您的运行步骤更改为复制步骤,这样就不需要在构建服务器上进行任何模拟了。这意味着运行:
echo "console.log('hello world!');" > main.js在与您的Dockerfile相同的目录中,在构建上下文中创建main.js文件。然后将Dockerfile更改为:
FROM node:18-alpine as node
WORKDIR /usr/src/app
COPY main.js .
EXPOSE 4000
CMD [ "node", "main.js" ]这样,您就可以使用原始的docker buildx build命令构建多平台映像。
https://stackoverflow.com/questions/73978929
复制相似问题