Oxcart Download
Menu

Run and test Google Cloud Run containers locally on a Mac

To test a Cloud Run service on an Apple silicon Mac, build it for linux/amd64 and run it with the PORT variable: docker run -e PORT=8080 -p 8080:8080 IMAGE. On Oxcart both our own service and Google’s Cloud Run sample ran this way, the amd64 images through Rosetta, so you test the exact image you deploy.

Updated

The Cloud Run container contract

Cloud Run runs any container that follows a short contract. Google’s documentation says requests go to port 8080 by default, the PORT environment variable is set on the ingress container, and the container “must listen for requests on 0.0.0.0” and “should not listen on 127.0.0.1”. It also says Cloud Run “specifically supports the Linux x86_64 ABI format” and that a multi-architecture image must include linux/amd64.

Two of those rules trip up Mac developers: an app that binds localhost works in a local terminal and fails in Cloud Run, and an image built natively on Apple silicon is arm64. Testing the real container locally catches both before you deploy.

Test a Cloud Run service locally on Apple silicon

  1. Listen on $PORT and 0.0.0.0. Make the server read the PORT environment variable (Cloud Run sends requests to 8080 by default) and bind 0.0.0.0, not 127.0.0.1.
  2. Build for linux/amd64. Run docker buildx build --platform linux/amd64 --load -t my-service .. Cloud Run supports the Linux x86_64 ABI, so an arm64 image built natively on your Mac is the wrong target.
  3. Run it as Cloud Run would. Run docker run --rm --platform linux/amd64 -e PORT=8080 -p 8080:8080 my-service. Oxcart runs the amd64 image through Rosetta.
  4. Call it. Run curl localhost:8080. To check the PORT handling, start a second copy with -e PORT=9090 -p 9090:9090.
  5. Push to Artifact Registry. Run gcloud auth configure-docker REGION-docker.pkg.dev once, then tag the image as REGION-docker.pkg.dev/PROJECT/REPO/my-service:TAG and docker push it.

What we ran on Oxcart

A small Python service that binds $PORT, run twice with different ports, plus Google’s own sample image:

docker run -d -e PORT=8080 -p 18081:8080 my-service
docker run -d -e PORT=9090 -p 18090:9090 my-service
curl localhost:18081        # hello from PORT=8080
curl localhost:18090        # hello from PORT=9090

docker run -d -e PORT=8080 -p 8081:8080 us-docker.pkg.dev/cloudrun/container/hello
docker image inspect us-docker.pkg.dev/cloudrun/container/hello --format '{{.Os}}/{{.Architecture}}'
# linux/amd64
curl localhost:8081         # "It's running!"

Google’s sample is an amd64-only image; Oxcart pulled it and ran it through Rosetta without extra flags. For amd64-only images you build yourself, pass --platform linux/amd64 on docker run as well: in our tests a locally built amd64 image was found only when the platform was given.

Building for linux/amd64 on Apple silicon

# Cloud Run target: amd64
docker buildx build --platform linux/amd64 --load -t my-service:amd64 .

# Both architectures in the local image store (runs locally either way)
docker buildx build --platform linux/amd64,linux/arm64 -t my-service:multi .

Oxcart’s default builder lists both linux/amd64 and linux/arm64, and the multi-platform build completes locally with both variants runnable. Pushing a multi-platform image from Oxcart is not supported, so for Cloud Run push the amd64 tag, which is the one it runs. Builds are quick: 341 ms uncached and 121 ms cached for a small local context, the fastest of the three runtimes we tested.

Push to Artifact Registry and deploy

gcloud auth configure-docker us-central1-docker.pkg.dev
docker tag my-service:amd64 us-central1-docker.pkg.dev/my-project/apps/my-service:1.0.0
docker push us-central1-docker.pkg.dev/my-project/apps/my-service:1.0.0
gcloud run deploy my-service \
  --image us-central1-docker.pkg.dev/my-project/apps/my-service:1.0.0 --region us-central1

Dependencies with Compose

A Cloud Run service usually talks to a database, a cache or another service. Run them next to it with Compose, set PORT in the service’s environment, and gate start order on healthchecks:

services:
  api:
    build: .
    platform: linux/amd64
    environment:
      PORT: "8080"
      REDIS_URL: redis://cache:6379
    ports: ["8080:8080"]
    depends_on:
      cache:
        condition: service_healthy
  cache:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 2s
      retries: 30

docker compose up -d --wait returns once the cache is healthy and the API has started. The Compose on Apple silicon guide covers healthchecks, amd64 images and ports in depth.

Ports on your Mac

Published ports listen on all of the Mac’s interfaces, as with Docker’s default. If another Mac app already listens on 127.0.0.1:8080, localhost:8080 can reach that app instead of your container, so pick a free host port (-p 18080:8080) and keep PORT as Cloud Run sets it. Oxcart’s Ports view shows every listener on the Mac next to your containers, and explains why a container port is not answering, including a server bound to 127.0.0.1 inside the container, the same mistake Cloud Run rejects. See container networking on a Mac.

Questions

How do I run a Cloud Run service locally on a Mac?

Run its container with the PORT variable set and the port published: docker run -e PORT=8080 -p 8080:8080 IMAGE. That is the method Google documents for local testing with Docker. On Oxcart we verified it with our own image on ports 8080 and 9090 and with Google’s us-docker.pkg.dev/cloudrun/container/hello sample.

Why does my Cloud Run deploy fail with an image built on Apple silicon?

Google documents that Cloud Run supports the Linux x86_64 ABI and that a multi-architecture image must include linux/amd64. A plain docker build on an Apple silicon Mac produces an arm64 image. Build with --platform linux/amd64.

Can I run the amd64 image on my Mac before deploying?

Yes. Oxcart runs linux/amd64 images through Rosetta. Pass --platform linux/amd64 when you run an amd64-only image you built locally; pulled amd64 images, such as Google’s hello sample, ran without it in our test.

My container works locally but Cloud Run says it failed to listen on the port. Why?

The most common cause is binding to 127.0.0.1 or a hard-coded port. Cloud Run’s container contract says the container must listen on 0.0.0.0 on the port in PORT. Test locally with a non-default PORT (for example 9090) to catch hard-coded ports.

Do I need gcloud beta code dev or Cloud Code?

No, they are optional. Google lists plain Docker, Docker with Google Cloud access, the Cloud Code emulator and gcloud beta code dev as ways to test locally. Docker on Oxcart lets you test the image and its PORT handling directly. gcloud beta code dev adds a Kubernetes-based development workflow using minikube or an existing Kubernetes context; choose it when you need that integration.

How do I give the local container access to Google Cloud APIs?

Mount credentials the way Google documents for “Docker with Google Cloud access”, typically Application Default Credentials passed in through a mounted file and GOOGLE_APPLICATION_CREDENTIALS. Outbound connections from containers on Oxcart are opened by your Mac, so your VPN and DNS apply.

Sources and method

  • Examples tested with Oxcart 0.1.2, Mac17,14, macOS 27.2, 2026-10-10 (PORT on 8080 and 9090, Google’s hello sample as linux/amd64, Buildx single- and multi-platform builds).
  • Cloud Run container contract (port, 0.0.0.0, x86_64): https://docs.cloud.google.com/run/docs/container-contract. Local testing options: https://docs.cloud.google.com/run/docs/testing/local and https://docs.cloud.google.com/sdk/gcloud/reference/beta/code/dev. Checked 2026-10-10.
  • Build speed: Oxcart 0.1.2, 2026-10-10, Apple M5 Max, 8 CPUs and 12 GiB, medians of five samples; the other runtimes were measured earlier the same day on the same Mac and harness with the docker 29.4 client.

Try Oxcart on your own projects

Free for 60 days. Then $20 per user, per major version: not a subscription.

Apple silicon · macOS 26 or later

Read next

Release notes

Oxcart 0.1.4

Latest release

Licensing and refinements.

  • Secure email-link license activation.
  • License and Mac management from Settings.
  • Offline license verification.
  • Performance improvements, UI polish, and bug fixes.

Requires macOS 26.0 or later

Oxcart 0.1.3

Idle memory reclamation.

  • Reclaims VM memory when no containers are running.
  • Preserves containers, images, volumes, and networks.

Requires macOS 26.0 or later

Oxcart 0.1.2

Command-line tool integration.

  • Switch between Oxcart's bundled Docker tools and an existing installation.
  • UI polish.

Requires macOS 26.0 or later

Oxcart 0.1.1

Bundled Docker tools and agent controls.

  • Docker CLI 29.9, Compose 5.6, and Buildx 0.38 included.
  • Docker context integration and secure Keychain credentials.
  • MCP agent connections with per-agent permissions and blocking.

Requires macOS 26.0 or later

Oxcart 0.1.0

Docker-compatible containers for Apple silicon.

  • Docker CLI, Compose, and Buildx compatibility.
  • Offline setup with bundled runtime components.
  • Ports organized by project and Git branch.
  • MCP integration with read-only access by default.
  • Verified automatic updates.

Requires macOS 26.0 or later