Cloud Build is GCP’s fully managed CI/CD platform. It builds, tests, and deploys code from source repositories — integrating with GitHub, GitLab, Bitbucket, and Cloud Source Repositories. Combined with Artifact Registry, Cloud Deploy, and IAM, it forms a complete delivery pipeline without managing Jenkins or other CI servers.

How Cloud Build Works

  Trigger (push, PR, manual, schedule)
  → Build (steps in containers)
    → Artifacts (images, packages)
      → Deploy (GKE, Cloud Run, App Engine, Cloud Functions)
  

Each step runs in a container; steps execute sequentially or in parallel. Builds run on Google’s infrastructure — no agents to maintain.

Enable and Configure

  gcloud services enable cloudbuild.googleapis.com artifactregistry.googleapis.com

# Create Artifact Registry repository
gcloud artifacts repositories create app \
  --repository-format=docker \
  --location=us-central1 \
  --description="Application container images"

# Grant Cloud Build access to deploy
PROJECT_NUMBER=$(gcloud projects describe learning-gcp-dev --format='value(projectNumber)')

gcloud projects add-iam-policy-binding learning-gcp-dev \
  --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
  --role="roles/run.admin"

gcloud projects add-iam-policy-binding learning-gcp-dev \
  --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
  --role="roles/artifactregistry.writer"

gcloud iam service-accounts add-iam-policy-binding \
  ${PROJECT_NUMBER}[email protected] \
  --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
  --role="roles/iam.serviceAccountUser"
  

cloudbuild.yaml

  steps:
  # Run tests
  - name: 'node:20'
    entrypoint: npm
    args: ['ci']
    id: 'install'

  - name: 'node:20'
    entrypoint: npm
    args: ['test']
    id: 'test'
    waitFor: ['install']

  # Build container image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/app/web:$COMMIT_SHA', '.']
    id: 'build'
    waitFor: ['test']

  # Push to Artifact Registry
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/app/web:$COMMIT_SHA']
    id: 'push'
    waitFor: ['build']

  # Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args: ['run', 'deploy', 'web-app',
           '--image=us-central1-docker.pkg.dev/$PROJECT_ID/app/web:$COMMIT_SHA',
           '--region=us-central1',
           '--platform=managed',
           '--quiet']
    id: 'deploy'
    waitFor: ['push']

images:
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/app/web:$COMMIT_SHA'

options:
  logging: CLOUD_LOGGING_ONLY
  machineType: 'E2_HIGHCPU_8'

timeout: '1200s'
  

Triggers

  # GitHub trigger on push to main
gcloud builds triggers create github \
  --name="deploy-on-push" \
  --repo-name=my-web-app \
  --repo-owner=my-org \
  --branch-pattern="^main$" \
  --build-config=cloudbuild.yaml \
  --region=us-central1

# Pull request trigger (run tests only, no deploy)
gcloud builds triggers create github \
  --name="test-on-pr" \
  --repo-name=my-web-app \
  --repo-owner=my-org \
  --pull-request-pattern="^main$" \
  --build-config=cloudbuild-test.yaml \
  --comment-control=COMMENTS_ENABLED

# Manual trigger
gcloud builds triggers run deploy-on-push --branch=main
  

GKE Deployment

Add a deploy step for Kubernetes:

    - name: 'gcr.io/cloud-builders/gke-deploy'
    args:
      - run
      - --filename=k8s/
      - --image=us-central1-docker.pkg.dev/$PROJECT_ID/app/web:$COMMIT_SHA
      - --location=us-central1
      - --cluster=prod-cluster
    id: 'deploy-gke'
    waitFor: ['push']
  

Or use kubectl with cluster credentials:

    - name: 'gcr.io/cloud-builders/kubectl'
    args: ['apply', '-f', 'k8s/']
    env:
      - 'CLOUDSDK_COMPUTE_REGION=us-central1'
      - 'CLOUDSDK_CONTAINER_CLUSTER=prod-cluster'
  

Secrets in Builds

  # Store secret in Secret Manager
echo -n "my-api-key" | gcloud secrets create api-key --data-file=-

# Grant Cloud Build access
gcloud secrets add-iam-policy-binding api-key \
  --member="serviceAccount:[email protected]" \
  --role="roles/secretmanager.secretAccessor"
  

In cloudbuild.yaml:

  availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/api-key/versions/latest
      env: 'API_KEY'

steps:
  - name: 'node:20'
    entrypoint: npm
    args: ['test']
    secretEnv: ['API_KEY']
  

Progressive Delivery with Cloud Deploy

  gcloud deploy delivery-pipelines create web-pipeline \
  --region=us-central1 \
  --description="Web app progressive delivery"

gcloud deploy targets create staging \
  --delivery-pipeline=web-pipeline \
  --region=us-central1 \
  --gke-cluster=projects/learning-gcp-dev/locations/us-central1/clusters/staging-cluster

gcloud deploy targets create production \
  --delivery-pipeline=web-pipeline \
  --region=us-central1 \
  --gke-cluster=projects/learning-gcp-dev/locations/us-central1/clusters/prod-cluster \
  --require-approval
  

Cloud Deploy manages canary and blue-green rollouts with approval gates.

Cloud Build vs. Alternatives

Feature Cloud Build GitHub Actions Jenkins
Infrastructure Fully managed GitHub-hosted or self-hosted Self-managed
GCP integration Native Via WIF + gcloud Via plugins
Pricing Per build-minute Free tier + per-minute Server cost
Secrets Secret Manager GitHub Secrets Credentials plugin
Best for GCP-native teams GitHub-centric teams Complex custom pipelines

Real-World Scenario: Multi-Environment Pipeline

  PR opened → cloudbuild-test.yaml (lint, unit tests, SAST)
  ↓ merge to main
cloudbuild.yaml → build image → push to Artifact Registry
  ↓
Deploy to staging (automatic)
  ↓
Integration tests on staging
  ↓
Deploy to production (manual approval via Cloud Deploy)
  ↓
Canary: 10% → 50% → 100% traffic shift
  

Common Mistakes

Mistake Impact Fix
No test step before deploy Broken code in production Always test in pipeline
:latest image tags Cannot rollback Tag with $COMMIT_SHA
Secrets in cloudbuild.yaml Leaked in version control Secret Manager
No build timeout Runaway build costs Set timeout in yaml
Deploying from developer laptops No audit trail All deploys through CI/CD

Best Practices

Practice Benefit
Secret Manager Secure build credentials
Build caches Faster subsequent builds
Separate triggers Staging vs production promotion
Artifact Registry Image vulnerability scanning
Cloud Deploy Managed progressive rollouts
Immutable tags Rollback to any commit
Build logs in Cloud Logging Searchable, exportable audit trail
Workload Identity Federation GitHub Actions without SA keys

Troubleshooting

Build fails at push step:

  gcloud builds log BUILD_ID
# Verify Artifact Registry permissions for Cloud Build SA
gcloud artifacts repositories describe app --location=us-central1
  

Deploy step permission denied:

  # Check Cloud Build SA has roles/run.admin and iam.serviceAccountUser
gcloud projects get-iam-policy learning-gcp-dev \
  --flatten="bindings[].members" \
  --filter="bindings.members:cloudbuild"
  

Trigger not firing:

  gcloud builds triggers list
gcloud builds triggers describe deploy-on-push --region=us-central1
# Verify GitHub App connection in Cloud Build settings
  

Slow builds: Use Kaniko for cached Docker builds, or increase machineType to E2_HIGHCPU_32.

Cloud Build integrates natively with Artifact Registry, GKE, Cloud Run, and IAM.

Next: Cloud Run — serverless containers for production workloads.