31

Expected behavior: I can run a container I've built using an Apple M1 chip.

Observed behavior:

Assuming you have a Google Cloud Run account and can push Docker images to Google Container Registry. I'm using https://github.com/seenickcode/trivial-go-api for this example.

  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. Go to console.cloud.google.com, Google Cloud Run > Create new service > select your pushed Docker image with all default options > Run
  6. Error shown:
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.

Logs:

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

System details on where I'm building my image:

  • OS: macOS 11.2.3
  • Chip: Apple M1
  • Docker version: Docker Desktop for macOS v3.3.0 (62345)

Important Notes:

  • This all works completely fine for me when I use another architecture, i.e. via Google Container Build or my home Windows (WSL) desktop.
  • This also doesn't work with other codebases when built using the Apple M1 Chip, such as another project I have written in Rust as well as Dart. Doesn't seem language related.
  • I've been using Google Cloud Run for years, this issue cropped up when using my new laptop with Apple M1 Chip.
satoru
  • 31,822
  • 31
  • 91
  • 141
seenickcode
  • 1,022
  • 1
  • 10
  • 18
  • 1
    You're building code on an ARM platform and trying to run it on an x86_64 platform. Looking at [this doc](https://cloud.google.com/compute/docs/cpu-platforms) it doesn't appear that Google Cloud provides an ARM platform. You're going to need to build your images on a platform that is compatible with your target environment. – larsks Apr 02 '21 at 14:46

3 Answers3

53

You are building an ARM-compatible image which Google Cloud does not support.

I have hit a similar problem pushing my Mac M1 built image to Heroku, which I solved using buildx and setting the expected platform

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

I have written a Medium post to explain the problem and propose 2 solutions.

Docker is by design multi-platform and can run on different architectures, however, the images must match the platform they will be run on. Which is not our case.

Beppe C
  • 11,256
  • 2
  • 19
  • 41
  • 2
    Makes sense. While the `buildx` approach works for the trivial Go example cite above, when I use it for a medium sized Rust webapp, random libraries fail to compile. I get an exit code 101 and the failure is during compilation of random Rust libraries. Any ideas? – seenickcode Apr 03 '21 at 15:39
  • Difficult to say without seeing the errors, I would try the other option (set DOCKER_DEFAULT_PLATFORM) – Beppe C Apr 03 '21 at 15:50
  • The DOCKER_DEFAULT_PLATFORM method yields the same error unfortunately. Either my system isn't powerful enough or using buildx may be brittle for compiling certain Rust libs. For now, I've reserved a cheap compute optimized AWS spot instance as my build server. – seenickcode Apr 04 '21 at 13:35
  • Good option, I use GitHub action to build my docker images and push them to Heroku. If you are interested one of my GitHub repos has an example. – Beppe C Apr 04 '21 at 17:08
  • Yeah I use a cheap CPU optimized AWS Spot instance with a Buildkite agent on it. Cool thx will take a look. – seenickcode Apr 05 '21 at 16:20
  • 1
    This still works perfectly. – lapurita Dec 22 '21 at 08:44
  • 1
    I was getting CrashLoopBackOff from my AKS deployment, that was because I had built my image in my M1 mac, and pushed it to ACR, then when AKS tried to run my image on linux it didn't work Thanks a lot – Jonas Braga Jul 14 '23 at 02:12
18

As from docker API version 1.40, you can specify the platform upon which your image needs to be built by using the --platform option, without using buildx.

docker build --platform=linux/amd64 -t myapp .
N.Berghmans
  • 335
  • 3
  • 8
2

Also you can build x86 compatible image and push to artifact registry with single command:

docker buildx build \
--platform linux/amd64 \
--push \
-t us-central1-docker.pkg.dev/your_project/your_registry/myapp .
vitaliytv
  • 694
  • 7
  • 9