GCP for DevOps — Cloud Run

2 minute read

Cloud Run

Cloud Run is a fully managed serverless container platform. Deploy any container that listens on a port — Cloud Run handles scaling, TLS, and infrastructure. It scales to zero when there’s no traffic.

Deploy a Container

# Deploy from Artifact Registry
$ gcloud run deploy my-api \
    --image=us-central1-docker.pkg.dev/my-project/my-repo/my-api:v1.0.0 \
    --region=us-central1 \
    --platform=managed \
    --allow-unauthenticated

Service [my-api] revision [my-api-00001-abc] has been deployed and is serving 100 percent of traffic.
Service URL: https://my-api-abc123-uc.a.run.app

# Deploy from source (Cloud Build + Cloud Run)
$ gcloud run deploy my-api \
    --source=. \
    --region=us-central1

Configuration Options

# Set CPU, memory, concurrency, and scaling
$ gcloud run deploy my-api \
    --image=us-central1-docker.pkg.dev/my-project/my-repo/my-api:v1.0.0 \
    --region=us-central1 \
    --cpu=2 \
    --memory=1Gi \
    --concurrency=80 \
    --min-instances=1 \
    --max-instances=100 \
    --timeout=300 \
    --port=8080 \
    --set-env-vars="ENV=production,LOG_LEVEL=info"

Environment Variables and Secrets

# Set environment variables
$ gcloud run services update my-api \
    --region=us-central1 \
    --set-env-vars="DB_HOST=10.0.0.5,DB_NAME=mydb"

# Mount Secret Manager secrets
$ gcloud run services update my-api \
    --region=us-central1 \
    --set-secrets="DB_PASSWORD=db-password:latest"

# Mount secret as a file
$ gcloud run services update my-api \
    --region=us-central1 \
    --set-secrets="/secrets/config.json=app-config:latest"

Traffic Management

# Deploy a new revision with no traffic
$ gcloud run deploy my-api \
    --image=us-central1-docker.pkg.dev/my-project/my-repo/my-api:v2.0.0 \
    --region=us-central1 \
    --no-traffic \
    --tag=canary

# Split traffic
$ gcloud run services update-traffic my-api \
    --region=us-central1 \
    --to-tags=canary=20

# Promote to 100%
$ gcloud run services update-traffic my-api \
    --region=us-central1 \
    --to-latest

# Rollback
$ gcloud run services update-traffic my-api \
    --region=us-central1 \
    --to-revisions=my-api-00001-abc=100

Custom Domains

# Map a custom domain
$ gcloud run domain-mappings create \
    --service=my-api \
    --domain=api.example.com \
    --region=us-central1

# Get DNS records to configure
$ gcloud run domain-mappings describe \
    --domain=api.example.com \
    --region=us-central1

VPC Connectivity

Connect Cloud Run to private resources (databases, internal APIs).

# Create a Serverless VPC Access connector
$ gcloud compute networks vpc-access connectors create my-connector \
    --region=us-central1 \
    --subnet=my-subnet \
    --min-instances=2 \
    --max-instances=10

# Deploy with VPC connector
$ gcloud run deploy my-api \
    --image=us-central1-docker.pkg.dev/my-project/my-repo/my-api:v1.0.0 \
    --region=us-central1 \
    --vpc-connector=my-connector \
    --vpc-egress=private-ranges-only

Cloud Run vs GKE

Feature Cloud Run GKE
Infrastructure Serverless Managed Kubernetes
Scaling Scale to zero Min 1 node
Pricing Per request + resources Per node (VM)
Startup time Seconds Minutes (cold start)
Complexity Low High
Stateful apps Limited Full support
GPU Supported Full support
Long-running jobs Up to 24h (Jobs) Unlimited
Custom networking VPC connector Full VPC native

Cloud Run Jobs

Run containers to completion (batch processing, data migration, scheduled tasks).

# Create a job
$ gcloud run jobs create data-migration \
    --image=us-central1-docker.pkg.dev/my-project/my-repo/migrator:v1.0.0 \
    --region=us-central1 \
    --tasks=10 \
    --parallelism=5 \
    --max-retries=3 \
    --task-timeout=3600

# Execute the job
$ gcloud run jobs execute data-migration --region=us-central1

# Schedule a job with Cloud Scheduler
$ gcloud scheduler jobs create http daily-report \
    --schedule="0 2 * * *" \
    --uri="https://us-central1-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/my-project/jobs/daily-report:run" \
    --http-method=POST \
    --oauth-service-account-email=scheduler-sa@my-project.iam.gserviceaccount.com

Common Mistakes

Mistake Why It’s Wrong Fix
No min instances for latency-sensitive Cold starts delay responses Set --min-instances=1
Too low concurrency Over-provisioning instances Set concurrency to 80-250
No VPC connector for private access Can’t reach internal resources Create VPC Access connector
--allow-unauthenticated on internal Security risk Use IAM invoker role
No CPU allocation “always on” CPU throttled between requests Use --cpu-boost or always-allocated

Quick Reference

Command Description
gcloud run deploy S --image=IMG Deploy service
gcloud run services list List services
gcloud run services update-traffic S Split traffic
gcloud run services update S --set-env-vars=K=V Set env vars
gcloud run jobs create J --image=IMG Create a job

Next → GKE Workloads

Updated: