Skip to main content

Deploy a Cloud Run Service

A Cloud Run Service is a good fit for serving an HTTP API, website, webhook, or any other application that needs to wait for requests.

Step 1: Deploy with the Console

  1. Open Cloud Run.

  2. On the Services page, click Deploy container.

  3. Choose Deploy one revision from an existing container image.

  4. Enter the Artifact Registry image, for example:

    asia-east1-docker.pkg.dev/PROJECT_ID/tkr101-repo/cloud-run-demo:v1
  5. Enter cloud-run-demo for the service name.

  6. Choose asia-east1 for the region.

  7. Under Container(s), Volumes, Networking, Security, configure:

    • Container port: 8080
    • Memory: choose based on the workload, e.g. 512Mi
    • CPU: choose based on the workload, e.g. 1
    • Minimum instances: 0 is fine for practice
    • Maximum instances: set a reasonable cap to avoid unbounded scaling during traffic spikes
  8. Choose an authentication setting:

    • Require authentication: requires IAM authentication, suitable for internal APIs.
    • Allow unauthenticated invocations: a public endpoint; only use this once you've confirmed the data and API are safe to expose publicly.
  9. Click Create.

Step 2: Deploy with gcloud

Deploy first in a mode that requires authentication:

gcloud run deploy cloud-run-demo \
--image=asia-east1-docker.pkg.dev/PROJECT_ID/tkr101-repo/cloud-run-demo:v1 \
--region=asia-east1 \
--port=8080 \
--memory=512Mi \
--cpu=1 \
--min=0 \
--max=10 \
--no-allow-unauthenticated

After deployment, check the service:

gcloud run services describe cloud-run-demo \
--region=asia-east1

Get the URL:

gcloud run services describe cloud-run-demo \
--region=asia-east1 \
--format='value(status.url)'

Step 3: Allow Public Invocation Only When Needed

If this service is explicitly meant to be exposed to browsers or a webhook provider, you can deploy with:

gcloud run deploy cloud-run-demo \
--image=IMAGE_URL \
--region=asia-east1 \
--allow-unauthenticated

Before making it public, confirm that:

  • The endpoint doesn't return personal or sensitive data.
  • The API has its own authentication, rate limiting, or abuse protection.
  • The service can't be triggered into expensive work by arbitrary input.
  • Logging and monitoring are already configured.

Step 4: Test the Service

If authentication is required, use gcloud to obtain an identity token:

SERVICE_URL=$(gcloud run services describe cloud-run-demo \
--region=asia-east1 \
--format='value(status.url)')

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
"$SERVICE_URL/"

If the service allows unauthenticated access:

curl "$SERVICE_URL/"

Port and PORT

A Cloud Run Service injects the PORT environment variable. The application should use:

import os

port = int(os.environ.get("PORT", "8080"))

Common mistakes:

  • The application only listens on 127.0.0.1.
  • The Dockerfile hardcodes a port that differs from the Cloud Run configuration.
  • Applying a Service's port settings to a Job; a Job doesn't need to listen on a port.
  • The server starts too slowly, without a suitable startup probe or enough resources.

CPU and Memory

CPU and memory should be sized based on the workload:

WorkloadStarting point
Simple HTTP APIStart small on CPU/memory, then observe metrics
Flask API with large packagesIncrease memory and check cold start behavior
Selenium or browser workloadsUsually needs more CPU/memory, and load testing first
LLM/model servingRe-evaluate based on the model, latency, and GPU/CPU support

The notebook uses Selenium Grid as an example and recommends raising resources to around 2 CPUs and 2 GB of memory; that's a demonstration setting for that specific workload, not a default for every Service.

Scale to Zero and Cold Start

A Cloud Run Service can scale down to zero instances when there is no traffic:

With traffic: 1+ instances
Without traffic: 0 instances
New request: an instance is created, possibly with a cold start

Cold start time is affected by image size, dependencies, initialization work, and resource configuration. You can:

  • Reduce image size.
  • Avoid unnecessary remote calls during module import.
  • Move initialization work into a reasonable startup flow.
  • Set minimum instances for latency-sensitive services, though this incurs ongoing cost.

Don't blindly keep instances warm with a fixed ping; first confirm whether the latency improvement is worth the cost.

Revisions and Traffic

View revisions:

gcloud run revisions list \
--service=cloud-run-demo \
--region=asia-east1

View service logs:

gcloud run services logs read cloud-run-demo \
--region=asia-east1 \
--limit=50

Before a new version goes live, deploy the revision, test its URL, and shift traffic gradually. Don't mark an untested image as the sole production version.

Service Checklist

  • The container image has been verified locally.
  • The service uses the correct image tag.
  • The application listens on 0.0.0.0:$PORT.
  • Authentication settings match the sensitivity of the data.
  • CPU, memory, concurrency, and min/max instances have been evaluated.
  • The new revision has been tested and can be rolled back.
  • Logs and metrics are observable.
  • The endpoint can't be driven into expensive work by arbitrary input.

Further Reading