Требования к выполнению контейнеров Cloud Run
Cloud Run запускает любой контейнер, который соблюдает несколько требований. Документация Google указывает, что запросы по умолчанию идут на порт 8080, переменная окружения PORT задаётся во входном контейнере, а контейнер «должен слушать запросы на 0.0.0.0» и «не должен слушать на 127.0.0.1». Также указано, что Cloud Run «поддерживает именно формат ABI Linux x86_64», а образ для нескольких архитектур должен включать linux/amd64.
Разработчиков на Mac часто подводят два правила: приложение, привязанное к localhost, работает в локальном терминале, но не в Cloud Run, а образ, нативно собранный на Apple silicon, имеет архитектуру arm64. Локальная проверка настоящего контейнера выявит обе проблемы до развёртывания.
Проверка сервиса Cloud Run локально на Apple silicon
- Слушайте на $PORT и 0.0.0.0. Сервер должен читать переменную окружения
PORT(Cloud Run по умолчанию отправляет запросы на 8080) и привязываться к0.0.0.0, а не к127.0.0.1. - Соберите для linux/amd64. Выполните
docker buildx build --platform linux/amd64 --load -t my-service .. Cloud Run поддерживает ABI Linux x86_64, поэтому нативно собранный на Mac образ arm64 имеет неподходящую целевую архитектуру. - Запустите как в Cloud Run. Выполните
docker run --rm --platform linux/amd64 -e PORT=8080 -p 8080:8080 my-service. Oxcart выполняет образ amd64 через Rosetta. - Обратитесь к сервису. Выполните
curl localhost:8080. Для проверки обработки PORT запустите вторую копию с-e PORT=9090 -p 9090:9090. - Отправьте образ в Artifact Registry. Один раз выполните
gcloud auth configure-docker REGION-docker.pkg.dev, затем присвойте образу тегREGION-docker.pkg.dev/PROJECT/REPO/my-service:TAGи отправьте его черезdocker push.
Что мы запускали на Oxcart
Небольшой сервис Python, привязанный к $PORT, дважды запускали с разными портами, а также использовали пример образа от Google:
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 — образ только для amd64. Oxcart скачал его и запустил через Rosetta без дополнительных флагов. Для собственных образов только amd64 указывайте --platform linux/amd64 и при docker run: в наших тестах локально собранный образ amd64 находился только при указании платформы.
Сборка для linux/amd64 на 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 перечисляет и linux/amd64, и linux/arm64; сборка для нескольких платформ завершается локально, обе версии запускаются. Отправка образа для нескольких платформ из Oxcart не поддерживается, поэтому для Cloud Run отправляйте тег amd64: именно эту версию он выполняет. Сборка быстрая: 341 ms без кеша и 121 ms с кешем для небольшого локального контекста — самый быстрый результат среди трёх протестированных сред.
Отправка в Artifact Registry и развёртывание
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 Зависимости через Compose
Сервис Cloud Run обычно обращается к базе данных, кешу или другому сервису. Запустите их рядом через Compose, задайте PORT в окружении сервиса и поставьте порядок запуска в зависимость от проверок состояния:
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 завершается, когда кеш проходит проверку состояния и API запущен. В руководстве по Compose на Apple silicon подробно разобраны проверки состояния, образы amd64 и порты.
Порты на вашем Mac
Опубликованные порты слушают на всех интерфейсах Mac, как при стандартных настройках Docker. Если другое приложение Mac уже слушает на 127.0.0.1:8080, localhost:8080 может обращаться к нему вместо контейнера. Выберите свободный порт хоста (-p 18080:8080), сохранив PORT таким, каким его задаёт Cloud Run. Раздел Ports в Oxcart показывает все слушающие сервисы Mac рядом с контейнерами и объясняет, почему порт контейнера не отвечает. В том числе он выявляет сервер, привязанный внутри контейнера к 127.0.0.1, — ту же ошибку, которую не допускает Cloud Run. См. сети контейнеров на Mac.
Вопросы
Как запустить сервис Cloud Run локально на Mac?
Запустите его контейнер с заданной переменной PORT и опубликованным портом: docker run -e PORT=8080 -p 8080:8080 IMAGE. Именно такой способ Google документирует для локального тестирования с Docker. На Oxcart мы проверили его с собственным образом на портах 8080 и 9090 и с примером Google us-docker.pkg.dev/cloudrun/container/hello.
Почему развёртывание в Cloud Run не удаётся с образом, собранным на Apple silicon?
Google документирует поддержку ABI Linux x86_64 в Cloud Run и требует включать linux/amd64 в образы для нескольких архитектур. Обычный docker build на Mac с Apple silicon создаёт образ arm64. Собирайте с --platform linux/amd64.
Можно ли запустить образ amd64 на Mac до развёртывания?
Да. Oxcart выполняет образы linux/amd64 через Rosetta. При запуске локально собранного образа только для amd64 указывайте --platform linux/amd64. Скачанные образы amd64, например hello от Google, в нашем тесте запускались без этого флага.
Контейнер работает локально, но Cloud Run сообщает, что он не слушает порт. Почему?
Чаще всего причина — привязка к 127.0.0.1 или порту, жёстко заданному в коде. Требования Cloud Run предписывают контейнеру слушать на 0.0.0.0 порт из PORT. Проверьте локально с нестандартным PORT, например 9090, чтобы обнаружить жёстко заданные порты.
Нужны ли gcloud beta code dev или Cloud Code?
Нет, они необязательны. Google перечисляет обычный Docker, Docker с доступом к Google Cloud, эмулятор Cloud Code и gcloud beta code dev как варианты локального тестирования. Docker на Oxcart позволяет напрямую проверить образ и обработку PORT. gcloud beta code dev добавляет процесс разработки на базе Kubernetes с minikube или существующим контекстом Kubernetes; выбирайте его, если нужна такая интеграция.
Как дать локальному контейнеру доступ к API Google Cloud?
Подключите учётные данные так, как Google описывает для «Docker с доступом к Google Cloud»: обычно это Application Default Credentials через смонтированный файл и GOOGLE_APPLICATION_CREDENTIALS. Исходящие соединения контейнеров Oxcart открывает ваш Mac, поэтому действуют его VPN и DNS.
Источники и методика
- Примеры проверены на Oxcart 0.1.2, Mac17,14, macOS 27.2, 2026-10-10 (PORT на 8080 и 9090, пример hello от Google как linux/amd64, сборки Buildx для одной и нескольких платформ).
- Требования к контейнерам Cloud Run (порт, 0.0.0.0, x86_64): https://docs.cloud.google.com/run/docs/container-contract. Варианты локального тестирования: https://docs.cloud.google.com/run/docs/testing/local и https://docs.cloud.google.com/sdk/gcloud/reference/beta/code/dev. Проверено 2026-10-10.
- Скорость сборки: Oxcart 0.1.2, 2026-10-10, Apple M5 Max, 8 CPU и 12 GiB, медианы пяти замеров; другие среды измеряли ранее в тот же день на том же Mac и теми же средствами, с клиентом docker 29.4.