A comprehensive, production-ready pipeline template for deploying backend APIs to Google Cloud Run. Includes staging and production environments, security best practices, and automated deployment workflows for scalable API services.
This GitLab CI/CD pipeline template provides a robust foundation for deploying backend APIs to Google Cloud Run. It's specifically designed for Node.js, Python, PHP, Go, and other backend frameworks, supporting multiple environments (staging and production), comprehensive error handling, and can be easily customized for any backend API project requirements.
Save this code as .gitlab-ci.yml
in your repository root.
Customize the variables section according to your project requirements.
# =============================================================================
# GitLab CI/CD Pipeline for Backend API Deployment on Google Cloud Run
# =============================================================================
# This pipeline builds and deploys backend APIs to Google Cloud Run
# Supports multiple environments (staging/production) with customizable settings
# Optimized for Node.js, Python, Java, Go, and other backend frameworks
# Author: EkaivaKriti/Suraj Anand
# Last Updated: 06-07-2025
# =============================================================================
# Base Docker image with Google Cloud SDK pre-installed
# Alternative: Use 'alpine/gcloud' for smaller image size
image: google/cloud-sdk:latest
# =============================================================================
# GLOBAL VARIABLES
# =============================================================================
# These variables can be customized based on your project requirements
# Set these in GitLab CI/CD Variables (Settings > CI/CD > Variables)
variables:
# Application Configuration
APP_NAME: "my-app" # Change to your application name
# Staging Environment Variables
STAGING_SERVICE_NAME: "staging-${APP_NAME}-service"
STAGING_IMAGE: "gcr.io/${STAGING_GOOGLE_PROJECT_ID}/staging-${APP_NAME}:${CI_COMMIT_SHORT_SHA}"
STAGING_BRANCH: "develop" # Branch that triggers staging deployment
# Production Environment Variables
PROD_SERVICE_NAME: "prod-${APP_NAME}-service"
PROD_IMAGE: "gcr.io/${PROD_GOOGLE_PROJECT_ID}/prod-${APP_NAME}:${CI_COMMIT_SHORT_SHA}"
PROD_BRANCH: "main" # Branch that triggers production deployment
# Container Configuration (customize as needed)
CONTAINER_PORT: "8080" # Port your application listens on
MEMORY_LIMIT: "2Gi" # Memory allocation (512Mi, 1Gi, 2Gi, 4Gi, 8Gi)
TIMEOUT: "300s" # Request timeout (max: 3600s)
MAX_INSTANCES: "100" # Maximum number of instances (optional)
# Security Configuration
ALLOW_UNAUTHENTICATED: "true" # Set to "false" for private services
# =============================================================================
# PIPELINE STAGES
# =============================================================================
# Stages define the order of operations in your pipeline
# You can add more stages like: test, security-scan, etc.
stages:
- build # Build and push Docker images
- deploy # Deploy to Cloud Run
# =============================================================================
# REUSABLE SCRIPT TEMPLATES
# =============================================================================
# These templates can be extended by jobs to avoid code duplication
.gcp_auth_template: &gcp_auth
# Install Docker (required for gcloud builds submit)
- apt-get update && apt-get install -y docker.io
# Authenticate with Google Cloud using service account key
- echo "${GCP_SERVICE_KEY}" > "${CI_PROJECT_DIR}/key.json"
- gcloud auth activate-service-account --key-file="${CI_PROJECT_DIR}/key.json"
- gcloud config set project "${GOOGLE_PROJECT_ID}"
.env_setup_template: &env_setup
# Copy environment variables from GitLab CI/CD variables to env.yaml
# Note: Remove the debug line (cat -A) in production to avoid exposing secrets
- cp "${ENV_FILE}" env.yaml
- echo "Environment file created successfully"
# - cat -A env.yaml # DEBUG ONLY: Remove this line in production!
# =============================================================================
# BUILD JOBS
# =============================================================================
# Staging Build Job
# Triggers when code is pushed to the staging branch
build-staging:
stage: build
variables:
GOOGLE_PROJECT_ID: ${STAGING_GOOGLE_PROJECT_ID}
GCP_SERVICE_KEY: ${STAGING_GCP_SERVICE_KEY}
ENV_FILE: ${STAGING_ENV_FILE}
before_script:
- *gcp_auth
- *env_setup
script:
# Build and push Docker image to Google Container Registry
- gcloud builds submit --tag "${STAGING_IMAGE}" .
# Optional: Add additional build steps here (tests, security scans, etc.)
- echo "Staging build completed successfully"
only:
- ${STAGING_BRANCH}
artifacts:
reports:
junit: test-results.xml # Optional: Include test results
tags:
- docker # Use runners with Docker support
# Production Build Job
# Triggers when code is pushed to the production branch
build-production:
stage: build
variables:
GOOGLE_PROJECT_ID: ${PROD_GOOGLE_PROJECT_ID}
GCP_SERVICE_KEY: ${PROD_GCP_SERVICE_KEY}
ENV_FILE: ${PROD_ENV_FILE}
before_script:
- *gcp_auth
- *env_setup
script:
# Build and push Docker image to Google Container Registry
- gcloud builds submit --tag "${PROD_IMAGE}" .
# Optional: Add production-specific build steps
- echo "Production build completed successfully"
only:
- ${PROD_BRANCH}
when: manual # Require manual approval for production builds
tags:
- docker
# =============================================================================
# DEPLOY JOBS
# =============================================================================
# Staging Deploy Job
# Automatically deploys after successful staging build
deploy-staging:
stage: deploy
variables:
GOOGLE_PROJECT_ID: ${STAGING_GOOGLE_PROJECT_ID}
GCP_SERVICE_KEY: ${STAGING_GCP_SERVICE_KEY}
ENV_FILE: ${STAGING_ENV_FILE}
before_script:
- *gcp_auth
- *env_setup
script:
# Deploy to Cloud Run with staging configuration
- |
gcloud run deploy "${STAGING_SERVICE_NAME}" \
--image "${STAGING_IMAGE}" \
--platform "managed" \
--region "${STAGING_GOOGLE_REGION}" \
--port "${CONTAINER_PORT}" \
--memory "${MEMORY_LIMIT}" \
--timeout "${TIMEOUT}" \
--max-instances "${MAX_INSTANCES}" \
--env-vars-file env.yaml \
--allow-unauthenticated \
--quiet
# Optional: Add health check or smoke tests
- echo "Staging deployment completed successfully"
only:
- ${STAGING_BRANCH}
environment:
name: staging
url: https://${STAGING_SERVICE_NAME}-${STAGING_GOOGLE_REGION}.a.run.app
# Production Deploy Job
# Requires manual approval and deploys to production
deploy-production:
stage: deploy
variables:
GOOGLE_PROJECT_ID: ${PROD_GOOGLE_PROJECT_ID}
GCP_SERVICE_KEY: ${PROD_GCP_SERVICE_KEY}
ENV_FILE: ${PROD_ENV_FILE}
before_script:
- *gcp_auth
- *env_setup
script:
# Deploy to Cloud Run with production configuration
- |
gcloud run deploy "${PROD_SERVICE_NAME}" \
--image "${PROD_IMAGE}" \
--platform "managed" \
--region "${PROD_GOOGLE_REGION}" \
--port "${CONTAINER_PORT}" \
--memory "${MEMORY_LIMIT}" \
--timeout "${TIMEOUT}" \
--max-instances "${MAX_INSTANCES}" \
--env-vars-file env.yaml \
--allow-unauthenticated \
--quiet
# Optional: Add database connections for production
# --add-cloudsql-instances="${PROD_GOOGLE_PROJECT_ID}:${PROD_GOOGLE_REGION}:${DATABASE_INSTANCE}" \
- echo "Production deployment completed successfully"
only:
- ${PROD_BRANCH}
when: manual # Require manual approval for production deployment
environment:
name: production
url: https://${PROD_SERVICE_NAME}-${PROD_GOOGLE_REGION}.a.run.app
# =============================================================================
# OPTIONAL: ADDITIONAL JOBS
# =============================================================================
# Optional: Test Job (add before build stage)
test:
stage: test
script:
- echo "Running tests..."
# - npm test
# - pytest
# - go test
only:
- ${STAGING_BRANCH}
- ${PROD_BRANCH}
# Optional: Security Scan Job
security-scan:
stage: test
script:
- echo "Running security scans..."
# - trivy image "${STAGING_IMAGE}"
# - snyk test
allow_failure: true # Don't fail pipeline on security warnings
Navigate to your GitLab project: Settings > CI/CD > Variables
Variable | Description | Protected |
---|---|---|
STAGING_GOOGLE_PROJECT_ID |
Your GCP staging project ID | ✓ |
PROD_GOOGLE_PROJECT_ID |
Your GCP production project ID | ✓ |
STAGING_GCP_SERVICE_KEY |
GCP service account key (JSON) | ✓ |
PROD_GCP_SERVICE_KEY |
GCP service account key (JSON) | ✓ |
STAGING_GOOGLE_REGION |
GCP region (e.g., us-central1) | ✗ |
PROD_GOOGLE_REGION |
GCP region (e.g., us-central1) | ✗ |
STAGING_ENV_FILE |
Environment variables file content | ✓ |
PROD_ENV_FILE |
Environment variables file content | ✓ |
Create your environment variables in YAML format:
# Example env.yaml format
DATABASE_URL: "postgresql://user:pass@host:5432/dbname"
REDIS_URL: "redis://redis-host:6379"
API_KEY: "your-api-key-here"
NODE_ENV: "production"
PORT: "8080"
LOG_LEVEL: "info"
# Using gcloud CLI
gcloud iam service-accounts create gitlab-ci \
--display-name="GitLab CI/CD" \
--description="Service account for GitLab CI/CD"
# Required roles
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:gitlab-ci@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:gitlab-ci@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:gitlab-ci@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/storage.admin"
# Create and download key
gcloud iam service-accounts keys create key.json \
--iam-account=gitlab-ci@PROJECT_ID.iam.gserviceaccount.com
Store this key securely in GitLab variables
Setting | Options | Default |
---|---|---|
Memory | 128Mi, 256Mi, 512Mi, 1Gi, 2Gi, 4Gi, 8Gi | 2Gi |
CPU | 1, 2, 4, 8 vCPU | 1 vCPU |
Timeout | 1s to 3600s | 300s |
Max Instances | 1 to 1000 | 100 |
Concurrency | 1 to 1000 | 80 |
To connect to Cloud SQL, add this parameter to your deployment:
# Add to gcloud run deploy command
--add-cloudsql-instances="PROJECT_ID:REGION:INSTANCE_NAME"
This is already included in the production deployment section (commented out)
# Add to stages
stages:
- test
- build
- deploy
# Test job example
test:
stage: test
script:
- npm test
- npm run lint
coverage: '/Coverage: \d+\.\d+%/'
# Security scan job
security-scan:
stage: test
script:
- trivy image $IMAGE_NAME
- snyk test
allow_failure: true
# Add monitoring labels
--labels="env=production,team=backend"
# Health check endpoint
--set-env-vars="HEALTH_CHECK_PATH=/health"
You now have a comprehensive, production-ready GitLab CI/CD pipeline for deploying backend APIs to Google Cloud Run. Customize the variables, add your specific API requirements, and start deploying your backend services!
Created with care for the developer community