Deployment
GCP Cloud Run Deployment
Deploy Jiffoo Mall on Google Cloud Platform using Cloud Run
GCP Cloud Run Deployment
Prerequisites
- Google Cloud CLI (gcloud) installed
- GCP Project with billing enabled
- Docker for building images
- Appropriate IAM permissions (Cloud Run Admin, Cloud SQL Admin)
Architecture Overview
This guide deploys Jiffoo Mall using:
- Cloud Run for serverless container orchestration
- Cloud Load Balancing for traffic distribution
- Cloud SQL PostgreSQL for database
- Memorystore Redis for caching
- Secret Manager for sensitive configuration
- Artifact Registry for container images
Quick Start
1. Configure GCP CLI
# Login to GCP
gcloud auth login
# Set your project
gcloud config set project <your-project-id>
# Set default region
gcloud config set run/region us-central12. Enable Required APIs
gcloud services enable \
run.googleapis.com \
sqladmin.googleapis.com \
redis.googleapis.com \
secretmanager.googleapis.com \
artifactregistry.googleapis.com3. Create Artifact Registry Repository
gcloud artifacts repositories create jiffoo \
--repository-format=docker \
--location=us-central1 \
--description="Jiffoo Mall container images"4. Build and Push Images
# Configure Docker authentication
gcloud auth configure-docker us-central1-docker.pkg.dev
# Build and push API
docker build -t us-central1-docker.pkg.dev/<project-id>/jiffoo/api:latest \
-f apps/api/Dockerfile .
docker push us-central1-docker.pkg.dev/<project-id>/jiffoo/api:latest
# Build and push Shop
docker build -t us-central1-docker.pkg.dev/<project-id>/jiffoo/shop:latest \
-f apps/shop/Dockerfile .
docker push us-central1-docker.pkg.dev/<project-id>/jiffoo/shop:latest
# Build and push Admin
docker build -t us-central1-docker.pkg.dev/<project-id>/jiffoo/admin:latest \
-f apps/admin/Dockerfile .
docker push us-central1-docker.pkg.dev/<project-id>/jiffoo/admin:latest5. Create Cloud SQL PostgreSQL Instance
gcloud sql instances create jiffoo-db \
--database-version=POSTGRES_15 \
--tier=db-f1-micro \
--region=us-central1 \
--root-password=<your-password> \
--backup-start-time=03:00
# Create database
gcloud sql databases create jiffoo --instance=jiffoo-db
# Get connection name (needed later)
gcloud sql instances describe jiffoo-db --format="value(connectionName)"6. Create Memorystore Redis Instance
gcloud redis instances create jiffoo-redis \
--size=1 \
--region=us-central1 \
--redis-version=redis_7_0 \
--tier=basic
# Get Redis host (needed later)
gcloud redis instances describe jiffoo-redis \
--region=us-central1 \
--format="value(host)"Secrets Management
Store sensitive configuration in Secret Manager:
# Database URL
echo -n "postgresql://postgres:<password>@<cloud-sql-private-ip>:5432/jiffoo" | \
gcloud secrets create database-url --data-file=-
# Redis URL
echo -n "redis://<memorystore-host>:6379" | \
gcloud secrets create redis-url --data-file=-
# JWT Secret
echo -n "<your-jwt-secret>" | \
gcloud secrets create jwt-secret --data-file=-
# Grant Cloud Run access to secrets
gcloud secrets add-iam-policy-binding database-url \
--member="serviceAccount:<project-number>[email protected]" \
--role="roles/secretmanager.secretAccessor"
gcloud secrets add-iam-policy-binding redis-url \
--member="serviceAccount:<project-number>[email protected]" \
--role="roles/secretmanager.secretAccessor"
gcloud secrets add-iam-policy-binding jwt-secret \
--member="serviceAccount:<project-number>[email protected]" \
--role="roles/secretmanager.secretAccessor"Deploy Cloud Run Services
Deploy API Service
gcloud run deploy jiffoo-api \
--image=us-central1-docker.pkg.dev/<project-id>/jiffoo/api:latest \
--platform=managed \
--region=us-central1 \
--allow-unauthenticated \
--port=3001 \
--cpu=1 \
--memory=1Gi \
--min-instances=0 \
--max-instances=10 \
--set-env-vars="NODE_ENV=production" \
--set-secrets="DATABASE_URL=database-url:latest,REDIS_URL=redis-url:latest,JWT_SECRET=jwt-secret:latest" \
--add-cloudsql-instances=<project-id>:us-central1:jiffoo-db \
--vpc-connector=<vpc-connector-name>Deploy Shop Service
gcloud run deploy jiffoo-shop \
--image=us-central1-docker.pkg.dev/<project-id>/jiffoo/shop:latest \
--platform=managed \
--region=us-central1 \
--allow-unauthenticated \
--port=3000 \
--cpu=0.5 \
--memory=512Mi \
--min-instances=0 \
--max-instances=10 \
--set-env-vars="NEXT_PUBLIC_API_URL=https://jiffoo-api-<hash>-uc.a.run.app"Deploy Admin Service
gcloud run deploy jiffoo-admin \
--image=us-central1-docker.pkg.dev/<project-id>/jiffoo/admin:latest \
--platform=managed \
--region=us-central1 \
--allow-unauthenticated \
--port=3003 \
--cpu=0.5 \
--memory=512Mi \
--min-instances=0 \
--max-instances=10 \
--set-env-vars="NEXT_PUBLIC_API_URL=https://jiffoo-api-<hash>-uc.a.run.app"VPC Connector (For Private Resources)
If using private Cloud SQL or Memorystore:
gcloud compute networks vpc-access connectors create jiffoo-connector \
--region=us-central1 \
--subnet=default \
--subnet-project=<project-id> \
--min-instances=2 \
--max-instances=3 \
--machine-type=e2-microCustom Domain Setup
1. Map Custom Domain
# Map domain to API
gcloud run domain-mappings create \
--service=jiffoo-api \
--domain=api.yourdomain.com \
--region=us-central1
# Map domain to Shop
gcloud run domain-mappings create \
--service=jiffoo-shop \
--domain=shop.yourdomain.com \
--region=us-central1
# Map domain to Admin
gcloud run domain-mappings create \
--service=jiffoo-admin \
--domain=admin.yourdomain.com \
--region=us-central12. Update DNS Records
Add the DNS records shown in the domain mapping output to your DNS provider.
Database Migrations
Run migrations using Cloud Run Jobs:
# Create migration job
gcloud run jobs create jiffoo-migrations \
--image=us-central1-docker.pkg.dev/<project-id>/jiffoo/api:latest \
--region=us-central1 \
--set-secrets="DATABASE_URL=database-url:latest" \
--add-cloudsql-instances=<project-id>:us-central1:jiffoo-db \
--vpc-connector=jiffoo-connector \
--command="pnpm" \
--args="db:push"
# Execute migration
gcloud run jobs execute jiffoo-migrations --region=us-central1Cloud Logging
View logs for your services:
# API logs
gcloud logs tail "resource.type=cloud_run_revision AND resource.labels.service_name=jiffoo-api" --follow
# Shop logs
gcloud logs tail "resource.type=cloud_run_revision AND resource.labels.service_name=jiffoo-shop" --follow
# Admin logs
gcloud logs tail "resource.type=cloud_run_revision AND resource.labels.service_name=jiffoo-admin" --follow
# Filter by severity
gcloud logs read "resource.type=cloud_run_revision AND resource.labels.service_name=jiffoo-api AND severity>=ERROR" --limit=50Scaling Configuration
Cloud Run auto-scales by default. Configure limits:
Update Service Concurrency
gcloud run services update jiffoo-api \
--region=us-central1 \
--concurrency=80 \
--min-instances=1 \
--max-instances=20CPU Allocation
# CPU always allocated (better performance, higher cost)
gcloud run services update jiffoo-api \
--region=us-central1 \
--cpu-throttling
# CPU only during request (lower cost)
gcloud run services update jiffoo-api \
--region=us-central1 \
--no-cpu-throttlingMonitoring
Cloud Monitoring Dashboards
Create a custom dashboard:
# View service metrics
gcloud monitoring dashboards create --config-from-file=dashboard.jsondashboard.json:
{
"displayName": "Jiffoo Mall Metrics",
"dashboardFilters": [],
"mosaicLayout": {
"columns": 12,
"tiles": [
{
"width": 6,
"height": 4,
"widget": {
"title": "Request Count",
"xyChart": {
"dataSets": [{
"timeSeriesQuery": {
"timeSeriesFilter": {
"filter": "resource.type=\"cloud_run_revision\" AND resource.labels.service_name=\"jiffoo-api\"",
"aggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_RATE"
}
}
}
}]
}
}
}
]
}
}Cloud Monitoring Alerts
# High error rate alert
gcloud alpha monitoring policies create \
--notification-channels=<channel-id> \
--display-name="Jiffoo API High Error Rate" \
--condition-display-name="Error rate > 5%" \
--condition-threshold-value=0.05 \
--condition-threshold-duration=300sTroubleshooting
Service Not Starting
Check service status and logs:
gcloud run services describe jiffoo-api --region=us-central1
gcloud logs read "resource.type=cloud_run_revision AND resource.labels.service_name=jiffoo-api" \
--limit=50 --format=jsonDeployment Failures
View revision details:
gcloud run revisions list \
--service=jiffoo-api \
--region=us-central1
gcloud run revisions describe <revision-name> \
--region=us-central1Database Connection Issues
Verify Cloud SQL connection:
# Check if Cloud SQL instance is running
gcloud sql instances describe jiffoo-db
# Test connection using Cloud SQL Proxy
cloud_sql_proxy -instances=<connection-name>=tcp:5432Memory Issues
Check container memory usage:
gcloud monitoring time-series list \
--filter='metric.type="run.googleapis.com/container/memory/utilizations"' \
--format=jsonIf containers are OOMing, increase memory:
gcloud run services update jiffoo-api \
--region=us-central1 \
--memory=2GiCold Start Optimization
Reduce cold starts with minimum instances:
gcloud run services update jiffoo-api \
--region=us-central1 \
--min-instances=1Cost Optimization
- Use minimum instances = 0 for non-critical services (shop, admin)
- Set minimum instances = 1 only for API to reduce cold starts
- Configure request timeout to prevent long-running requests
- Use Cloud SQL shared-core instances (db-f1-micro) for development
- Enable Cloud SQL automatic backups with 7-day retention
- Use Memorystore basic tier for non-HA workloads
- Monitor with Cloud Billing Budget Alerts
# Set request timeout
gcloud run services update jiffoo-api \
--region=us-central1 \
--timeout=60s
# Configure auto-delete for old revisions
gcloud run services update jiffoo-api \
--region=us-central1 \
--revision-suffix=v$(date +%Y%m%d-%H%M%S)CI/CD Integration
GitHub Actions Example
name: Deploy to Cloud Run
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- id: auth
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v1
- name: Configure Docker
run: gcloud auth configure-docker us-central1-docker.pkg.dev
- name: Build and Push API
run: |
docker build -t us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT }}/jiffoo/api:${{ github.sha }} \
-f apps/api/Dockerfile .
docker push us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT }}/jiffoo/api:${{ github.sha }}
- name: Deploy to Cloud Run
run: |
gcloud run deploy jiffoo-api \
--image=us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT }}/jiffoo/api:${{ github.sha }} \
--region=us-central1 \
--platform=managedUsing gcloud CLI
# Build and push new image
docker build -t us-central1-docker.pkg.dev/<project-id>/jiffoo/api:v2 \
-f apps/api/Dockerfile .
docker push us-central1-docker.pkg.dev/<project-id>/jiffoo/api:v2
# Deploy new revision
gcloud run deploy jiffoo-api \
--image=us-central1-docker.pkg.dev/<project-id>/jiffoo/api:v2 \
--region=us-central1
# Gradual rollout (traffic splitting)
gcloud run services update-traffic jiffoo-api \
--region=us-central1 \
--to-revisions=LATEST=10,PREVIOUS=90
# Once validated, shift all traffic
gcloud run services update-traffic jiffoo-api \
--region=us-central1 \
--to-latestSecurity Best Practices
1. Use IAM for Authentication
# Remove public access
gcloud run services remove-iam-policy-binding jiffoo-api \
--region=us-central1 \
--member="allUsers" \
--role="roles/run.invoker"
# Grant specific service account access
gcloud run services add-iam-policy-binding jiffoo-api \
--region=us-central1 \
--member="serviceAccount:<sa-email>" \
--role="roles/run.invoker"2. Use VPC Service Controls
gcloud access-context-manager perimeters create jiffoo-perimeter \
--title="Jiffoo Mall Services" \
--resources=projects/<project-number> \
--restricted-services=run.googleapis.com,sqladmin.googleapis.com3. Enable Binary Authorization
gcloud container binauthz policy import policy.yamlBackup and Disaster Recovery
Cloud SQL Backups
# Enable automated backups
gcloud sql instances patch jiffoo-db \
--backup-start-time=03:00 \
--backup-location=us
# Create on-demand backup
gcloud sql backups create \
--instance=jiffoo-db \
--description="Pre-deployment backup"
# Restore from backup
gcloud sql backups restore <backup-id> \
--backup-instance=jiffoo-db \
--backup-instance=jiffoo-db-restoredExport Database
# Export to Cloud Storage
gcloud sql export sql jiffoo-db \
gs://<bucket-name>/backups/jiffoo-$(date +%Y%m%d).sql \
--database=jiffoo