This chapter follows Artifact Registry. Cloud Run is a fully managed platform for containers that speak HTTP (or gRPC). You deploy an image and a revision; Google scales instances to zero and up based on traffic.
Compared to always-on VMs (Azure Compute covers a similar spectrum on another cloud), Run charges mainly for request time and allocated memory while instances handle traffic.
Services, jobs, and the container contract
A Cloud Run service serves HTTP traffic. A job runs a container to completion on a schedule or manual execution—useful for batch work, not for the series API.
Your container must:
- Listen on the port in
PORT(default 8080) - Handle
SIGTERMfor graceful shutdown within the request timeout - Stay stateless; persist data in Cloud Storage or a database (next chapter)
Deploy the series image
Set variables to match your registry push:
export REGION=europe-west1export PROJECT_ID=YOUR_PROJECT_IDexport IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/file-api/app:v1"export RUNTIME="file-api-runtime@${PROJECT_ID}.iam.gserviceaccount.com"Deploy:
gcloud run deploy file-api \ --image="${IMAGE}" \ --region="${REGION}" \ --service-account="${RUNTIME}" \ --allow-unauthenticated \ --port=8080 \ --memory=512Mi \ --max-instances=10The command prints a HTTPS URL. Test:
curl -s "$(gcloud run services describe file-api --region="${REGION}" --format='value(status.url)')/health"For private services, omit --allow-unauthenticated and grant roles/run.invoker to callers instead.
Revisions and traffic splitting
Each deploy creates a new revision. By default 100% of traffic moves to the latest revision. Split traffic for canaries:
gcloud run services update-traffic file-api \ --region="${REGION}" \ --to-revisions=REVISION_NAME=10,LATEST=90List revisions:
gcloud run revisions list --service=file-api --region="${REGION}"Roll back by sending 100% traffic to a known-good revision.
Concurrency, scaling, and timeouts
Concurrency is how many requests one instance handles at once (default 80). Higher concurrency reduces instance count but needs enough CPU for your Node event loop.
| Setting | Effect |
|---|---|
--min-instances |
Reduces cold starts; costs when idle |
--max-instances |
Caps scale-out |
--timeout |
Max request duration |
--cpu-boost |
Faster cold start (when enabled) |
Example for a low-traffic API:
gcloud run services update file-api \ --region="${REGION}" \ --concurrency=40 \ --min-instances=0 \ --max-instances=5 \ --timeout=60Environment variables and secrets
Pass configuration without baking secrets into the image:
gcloud run services update file-api \ --region="${REGION}" \ --set-env-vars="NODE_ENV=production,GCS_BUCKET=file-api-uploads"Mount Secret Manager values as env vars or volumes when you add API keys later:
gcloud run services update file-api \ --region="${REGION}" \ --update-secrets=MY_SECRET=my-secret:latestThe runtime service account needs secretAccessor on that secret.
Identity and ingress
The service account attached to the revision is what Cloud Storage and other APIs see—use file-api-runtime, not your user account.
Ingress controls who can reach the service URL:
| Ingress | Meaning |
|---|---|
| all | Public internet (default with allow-unauthenticated) |
| internal | VPC and internal clients only |
| internal-and-cloud-load-balancing | Internal plus external Application Load Balancer |
The Cloud Armor chapter sets internal-and-cloud-load-balancing so only the load balancer is public.
Next: Google Cloud Storage adds bucket uploads and listing to the API.
Check your understanding
Question 1 of 6
0 of 6 checked