首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过交叉编译为多个平台建立对接图像?

如何通过交叉编译为多个平台建立对接图像?
EN

Stack Overflow用户
提问于 2022-10-06 19:07:35
回答 2查看 375关注 0票数 0

我正在尝试构建一个多平台(linux/a 64,linux/arm64)节点映像。据我所知,我可以尝试corss-编译方法。使用docker构建并推送到码头注册中心不会引发任何错误。在构建机器上运行映像也很好,但是在我的raspberry-pi4 (运行ubuntu 64位)上,在提取映像后会发生以下操作

exec /usr/local/bin/docker-entrypoint.sh: exec格式错误

我的Dockerfile:

代码语言:javascript
复制
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/类型记录。然后在收集构建工件时切换到目标体系结构,然后这些机器可以运行这些构件。

示例:

代码语言: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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-10-07 18:10:27

问题是您使用的是BUILDPLATFORM,它将始终是与主机相同的架构。在这种情况下,它将永远是x86_64。您需要的是TARGETPLATFORM,它无论如何都是隐式的。您可以在对多平台码头建房的解释中看到这一点。

您可以使用docker version | grep 'OS/Arch'获取Docker信息(这将首先给客户端,然后是服务器)。

您实际上想要的是在为该平台构建时为linux/arm64使用linux/arm64映像。将其改为以下内容将有效:

代码语言:javascript
复制
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,您几乎肯定不想这样做。

票数 1
EN

Stack Overflow用户

发布于 2022-10-06 20:51:28

这两幅图像都是为构建平台而构建的,而不是使用以下行构建的目标平台:

代码语言:javascript
复制
FROM --platform=$BUILDPLATFORM ...

你不想让--platform=$BUILDPLATFORM站在目标舞台上。这用于交叉编译或输出非平台特定结果的中间阶段,您可以将这些结果复制到目标阶段。

有关由buildkit定义的这些变量的更多详细信息,请访问:https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope

我还会将您的运行步骤更改为复制步骤,这样就不需要在构建服务器上进行任何模拟了。这意味着运行:

代码语言:javascript
复制
echo "console.log('hello world!');" > main.js

在与您的Dockerfile相同的目录中,在构建上下文中创建main.js文件。然后将Dockerfile更改为:

代码语言:javascript
复制
FROM node:18-alpine as node
WORKDIR /usr/src/app
COPY main.js .
EXPOSE 4000
CMD [ "node", "main.js" ]

这样,您就可以使用原始的docker buildx build命令构建多平台映像。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73978929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档