当在苹果M1芯片(基于ARM的系统)上构建容器时,出现“exec格式错误”。

33

期望行为:我可以使用苹果M1芯片构建的容器运行。

观察到的行为:

假设你拥有Google Cloud Run帐户并且可以将Docker镜像推送到Google Container Registry。在本示例中,我使用https://github.com/seenickcode/trivial-go-api

  1. `git clone git@github.com:seenickcode/trivial-go-api.git'
  2. cd trivial-go-api
  3. docker build -t gcr.io/<YOUR GCR PROJECT ID>/example .
  4. docker push -t gcr.io/<YOUR GCR PROJECT ID>/example
  5. 转到console.cloud.google.com,Google Cloud Run > 创建新服务 > 选择所有默认选项的已推送Docker镜像 > 运行
  6. 显示错误:
Cloud Run error: Container failed to start. 
Failed to start and then listen on the port defined by the PORT environment variable. 
Logs for this revision might contain more information.

日志:

2021-04-02 09:35:40.045 EDT
Cloud Run ReplaceService example hello@redactedforso.com {@type: type.googleapis.com/google.cloud.audit.AuditLog, authenticationInfo: {}, authorizationInfo: [], methodName: google.cloud.run.v1.Services.ReplaceService, request: {}, requestMetadata: {}, resourceLocation: {}, resourceName: namespaces/myprojectforso-282419/services/example, response: {}, servi…
Error
2021-04-02 09:35:49.034 EDT
terminated: Application failed to start: Failed to create init process: failed to load /app/main: exec format error
Warning
2021-04-02 09:35:49.174 EDT
Application exec likely failed
Notice
2021-04-02 09:57:43.102 EDT
Cloud Run ReplaceService example hello@redactedforso.com {@type: type.googleapis.com/google.cloud.audit.AuditLog, authenticationInfo: {}, authorizationInfo: [], methodName: google.cloud.run.v1.Services.ReplaceService, request: {}, requestMetadata: {}, resourceLocation: {}, resourceName: namespaces/myprojectforso-282419/services/example, response: {}, servi…
Error
2021-04-02 09:57:50.657 EDT
terminated: Application failed to start: Failed to create init process: failed to load /app/main: exec format error

我正在构建镜像的系统详细信息:

  • 操作系统:macOS 11.2.3
  • 芯片:Apple M1
  • Docker版本:Docker Desktop for macOS v3.3.0 (62345)

重要提示:

  • 当我使用其他架构时,例如通过Google容器构建或我的家用Windows(WSL)桌面,这一切都完全正常。
  • 在使用苹果M1芯片构建的其他代码库中也存在此问题,例如我编写的另一个Rust项目和Dart。似乎与语言无关。
  • 我已经使用Google Cloud Run多年了,在使用搭载苹果M1芯片的新笔记本电脑时出现了这个问题。

1
你正在ARM平台上构建代码,并尝试在x86_64平台上运行它。查看此文档,似乎Google Cloud没有提供ARM平台。你需要在与目标环境兼容的平台上构建你的镜像。 - larsks
3个回答

55

您正在构建一种与ARM兼容的镜像,但Google Cloud不支持。

我曾遇到类似问题,将Mac M1构建的镜像推送到Heroku时解决了该问题,方法是使用buildx并设置预期平台。

docker buildx build --platform linux/amd64 -t myapp .

我写了一篇Medium文章来解释这个问题并提出了两种解决方案。

Docker是多平台设计的,可以在不同的架构上运行,但是镜像必须与它们将要运行的平台匹配。而这不是我们的情况。


2
有道理。虽然 buildx 方法适用于上述简单的 Go 示例,但当我将其用于中等规模的 Rust webapp 时,随机库无法编译。我得到了退出码 101,并且失败发生在随机 Rust 库的编译过程中。有什么想法吗? - seenickcode
没有看到错误的情况下很难说,我会尝试另一个选项(设置DOCKER_DEFAULT_PLATFORM)。 - Beppe C
我使用了一台廉价的CPU优化AWS Spot实例,并在上面安装了Buildkite代理程序。很酷,谢谢,我会查看的。 - seenickcode
1
这仍然完美地运作。 - lapurita
1
我在我的AKS部署中遇到了CrashLoopBackOff的问题,原因是我在我的M1 Mac上构建了镜像,并将其推送到ACR,然后当AKS尝试在Linux上运行我的镜像时出现了问题。非常感谢。 - Jonas Braga
显示剩余2条评论

18
自从Docker API的1.40版本起,您可以使用--platform选项指定构建镜像所需的平台,而无需使用buildx。 详见文档
docker build --platform=linux/amd64 -t myapp .

2
我尝试过这个方法,它有效。不需要使用buildx - satoru
在AWS中,buildx出现了错误,但这个方法运行得很好。 - Talha Akbar

2
您可以使用单个命令构建与x86兼容的镜像,并将其推送到工件注册表:
docker buildx build \
--platform linux/amd64 \
--push \
-t us-central1-docker.pkg.dev/your_project/your_registry/myapp .

我尝试了两个命令:´docker build --platform linux/amd64´ 和 ´docker buildx build --platform linux/amd64´都没有成功。我的规格如下: MacOS:13.6 Docker Desktop:23.0.5当我尝试在GCP上运行构建镜像时,出现了“exec format error”的错误。有什么办法可以解决这个问题吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接