Google Cloud Run
Cloud Run runs containers with automatic scaling — including scale-to-zero. You pay only for actual request processing time.
Prerequisites
- Google Cloud CLI (
gcloud) installed and authenticated - A GCP project with billing enabled
- A Dockerfile in your project
Quick deploy
The fastest path — Cloud Run builds and deploys from source:
# Enable APIs (once)
gcloud services enable run.googleapis.com cloudbuild.googleapis.com
# Deploy directly from source (Cloud Build handles the Dockerfile)
gcloud run deploy my-app \
--source . \
--port 3000 \
--region us-central1 \
--allow-unauthenticatedCloud Run gives you an HTTPS URL like https://my-app-xxxxx-uc.a.run.app.
Deploy from Artifact Registry
For more control over your image:
# Create Artifact Registry repository (once)
gcloud artifacts repositories create my-repo \
--repository-format=docker \
--location=us-central1
# Build and push
gcloud builds submit \
--tag us-central1-docker.pkg.dev/<project-id>/my-repo/my-app:latest
# Deploy the specific image
gcloud run deploy my-app \
--image us-central1-docker.pkg.dev/<project-id>/my-repo/my-app:latest \
--port 3000 \
--region us-central1 \
--allow-unauthenticatedConfiguration
Environment variables
gcloud run services update my-app \
--set-env-vars "RUST_LOG=info,APP_ENV=production" \
--region us-central1Secrets (via Secret Manager)
# Create a secret
echo -n "postgres://..." | gcloud secrets create db-url --data-file=-
# Mount as env var
gcloud run services update my-app \
--set-secrets "DATABASE_URL=db-url:latest" \
--region us-central1Resource limits
gcloud run services update my-app \
--memory 256Mi \
--cpu 1 \
--concurrency 250 \
--timeout 60s \
--region us-central1Scaling
# Min/max instances
gcloud run services update my-app \
--min-instances 0 \
--max-instances 10 \
--region us-central1min-instances=0enables scale-to-zero (cold starts ~300 ms for Rust)min-instances=1keeps one instance warm (avoids cold starts, ~$6/month)
Custom domain
# Map domain
gcloud run domain-mappings create \
--service my-app \
--domain api.example.com \
--region us-central1Then add the DNS records shown in the output. TLS is automatic.
VPC connectivity
Connect to Cloud SQL, Memorystore, or other VPC resources:
# Create a VPC connector (once)
gcloud compute networks vpc-access connectors create my-connector \
--region us-central1 \
--range 10.8.0.0/28
# Attach to Cloud Run
gcloud run services update my-app \
--vpc-connector my-connector \
--region us-central1Cloud SQL
# Connect via Unix socket (recommended)
gcloud run services update my-app \
--add-cloudsql-instances <project>:<region>:<instance> \
--set-env-vars "DATABASE_URL=postgres://user:pass@/db?host=/cloudsql/<project>:<region>:<instance>" \
--region us-central1CI/CD with GitHub Actions
name: Deploy to Cloud Run
on:
push:
branches: [main]
env:
PROJECT_ID: my-project
REGION: us-central1
SERVICE: my-app
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
workload_identity_provider: projects/<num>/locations/global/workloadIdentityPools/github/providers/github
service_account: deploy@${{ env.PROJECT_ID }}.iam.gserviceaccount.com
- name: Deploy to Cloud Run
uses: google-github-actions/deploy-cloudrun@v2
with:
service: ${{ env.SERVICE }}
region: ${{ env.REGION }}
source: .Cost estimate
| Scenario | Monthly cost |
|---|---|
| Scale-to-zero, 100k requests/month | ~$0.50 |
| 1 instance always-on (0.5 vCPU, 256 MB) | ~$6 |
| 5 instances peak, avg 2 | ~$30 |
Cloud Run charges per 100ms of actual processing + request count. Idle = free.
WebSocket support
Cloud Run supports WebSocket connections with automatic timeout handling. Set a longer request timeout for long-lived connections:
gcloud run services update my-app \
--timeout 3600s \
--region us-central1