Google Cloud Build Explained: GCP's Managed CI/CD Service
Cloud Build is Google Cloud’s managed CI/CD service. You define a pipeline as a list of container-based steps in a cloudbuild.yaml file. When code changes, Cloud Build runs those steps automatically: fetching source, running tests, building images, pushing to a registry, and deploying to Cloud Run or GKE. No build servers or agents required.
Simple explanation
Think of Cloud Build as a recipe runner for your code. When you push a commit to GitHub, Cloud Build wakes up, reads the recipe (your cloudbuild.yaml), and follows each instruction in order.
Each instruction runs inside its own container. One step might run your test suite using a Python container. The next builds your Docker image. Another pushes it to Artifact Registry. The last deploys it to Cloud Run. Each container is clean and disposable — there is no shared state between steps unless you use the shared /workspace directory, which Cloud Build mounts automatically.
The key thing to understand: you are not configuring a server. Google provides the execution environment, scales it to zero when you are not building, and handles all the underlying infrastructure. Your job is to write the pipeline config and grant the build service account the right permissions.
If you have used GitHub Actions, Cloud Build is the same idea: a workflow made of steps, triggered by git events, running entirely within GCP. A workflow file in GitHub Actions is a cloudbuild.yaml in Cloud Build. The main difference is that Cloud Build authenticates with GCP services via IAM automatically. No API tokens to manage, no secrets to rotate.
Why Cloud Build matters
The obvious benefit is not having to manage CI servers. Jenkins, self-hosted GitLab runners, TeamCity: all require a machine, an OS, security patches, and someone to maintain them. Cloud Build eliminates that entirely.
The more important benefit is environment cleanliness. Every Cloud Build job runs in a completely fresh environment. There is no leftover state from a previous build: no old package cache, no residual credentials, no zombie processes. This alone eliminates a large category of intermittent CI failures that are genuinely difficult to reproduce and debug on shared runners.
Cloud Build also integrates natively with the rest of GCP. The build service account can push to Artifact Registry, deploy to Cloud Run, update GKE clusters, or pull secrets from Secret Manager, all using IAM with no third-party credential management needed.
On cost: Cloud Build includes 120 free build-minutes per day on the default machine type. For most small to mid-sized teams, this covers a reasonable share of CI activity. Beyond the free tier, you pay per build-minute based on machine type.
How Cloud Build works
Here is the end-to-end flow from a code push to a deployed application:
- A change occurs. A developer pushes a commit to a branch, opens a pull request, or pushes a git tag. This is the event that starts everything.
- A trigger evaluates the event. Cloud Build checks whether any configured trigger matches. If the event matches, the trigger fires and a build starts.
- Cloud Build fetches the source. It pulls the repository at the matching commit into the build environment. Source checkout is handled automatically. You do not need a git step in your pipeline config.
- Steps execute in order. Cloud Build reads your
cloudbuild.yamland runs each step. Each step is a container that runs a command. Steps run sequentially by default. UsewaitForto express dependencies and enable parallel execution. - Artifacts are produced. A typical build produces a container image tagged with the commit SHA. Cloud Build pushes it to Artifact Registry so you can trace exactly which code version is running anywhere.
- Deployment runs (optional). A final step can deploy the image to Cloud Run, GKE, or hand off to Cloud Deploy for controlled multi-environment delivery.
- Logs and status are visible. Build logs stream to Cloud Logging in real time. The trigger status reports back to GitHub as a commit or pull request check.
All steps share the /workspace directory, which Cloud Build mounts as a volume. Files written there in one step are available to subsequent steps. Nothing outside /workspace persists between steps.
Picture a kitchen brigade. When an order arrives (trigger fires), the kitchen fetches the ingredients (source checkout). Each station does its part in sequence: prep, cook, plate. If the prep station rejects the ingredients — a failed test — the dish never reaches the pass. Nothing moves forward until each station is satisfied. Cloud Build works the same way: each step must exit cleanly before the next one starts.
Core concepts
Build steps
A step is the fundamental unit in a Cloud Build pipeline. Each step specifies a container image (name), the command to run inside it, and an optional id for referencing the step in waitFor dependencies. Steps run sequentially unless you use waitFor to express a different order.
steps:
- name: 'python:3.11'
entrypoint: bash
args: ['-c', 'pip install -r requirements.txt && python -m pytest tests/']
id: run-tests
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'europe-west2-docker.pkg.dev/$PROJECT_ID/app/api:$SHORT_SHA', '.']
id: build-image
waitFor: ['run-tests']Using waitFor: [’-’] tells Cloud Build to start a step immediately at build start, without waiting for any prior steps. This is useful for running independent checks in parallel and cutting overall build time.
Triggers
A trigger connects a git event to a build. Three trigger types are available:
- Push to branch: fires when a commit is pushed to a branch matching a pattern. Use this for continuous integration on
mainordevelop. - Push new tag: fires when a tag matching a pattern is pushed, for example
v*. Use this for release pipelines where a version tag triggers a production image build. - Pull request: fires when a PR is opened or updated. Use this to run tests and analysis before merging. Requires a GitHub App connection. By default, Cloud Build only runs PR builds from trusted contributors, which prevents untrusted code from accessing the build environment and any secrets it contains.
Triggers can also be invoked manually via the Cloud Console, gcloud CLI, or the Cloud Build API, which is useful for one-off deployments or debugging a specific commit.
Start with a single push-to-branch trigger on your main branch. That one trigger covers most CI needs and gives you immediate feedback on every merge. Add a tag trigger later when you need release-specific behaviour like a separate production deployment pipeline.
Substitutions
Cloud Build provides built-in variables you can reference in any step argument:
$PROJECT_ID: your GCP project ID$SHORT_SHA: the first 7 characters of the triggering commit SHA. Use this for image tags.$COMMIT_SHA: the full commit SHA$BRANCH_NAME: the branch that triggered the build$TAG_NAME: the git tag, for tag triggers$REPO_NAME: the repository name
You can define custom substitutions in the trigger configuration or build config, prefixed with an underscore: $_ENV, $_REGION. Custom substitutions make a single pipeline config reusable across projects and environments without duplicating files.
Custom substitutions are especially useful for multi-environment setups. Create two triggers pointing at the same cloudbuild.yaml — one for dev, one for production — each with different $_PROJECT and $_REGION values set in the trigger configuration. One config file, two environments, no duplication.
Builder images
Any Docker container image can serve as a build step. Google maintains official builders for common tasks:
gcr.io/cloud-builders/docker: Docker CLI for building, tagging, and pushing imagesgcr.io/google.com/cloudsdktool/cloud-sdk: gcloud, gsutil, bq, and kubectl. Use this for any step that runs gcloud commands.gcr.io/cloud-builders/kubectl: kubectl for GKE deploymentsgcr.io/cloud-builders/git: git CLI, for pipelines that need it
For language-specific steps, use any public image: node:20-alpine, python:3.12-slim, golang:1.22. You can also build your own custom builder image and host it in Artifact Registry for internal tooling shared across pipelines.
Do not use gcr.io/cloud-builders/gcloud — it is deprecated. Use gcr.io/google.com/cloudsdktool/cloud-sdk for all steps that run gcloud commands. The cloud-sdk image is actively maintained and supports all current gcloud features.
Service account and permissions
Cloud Build runs as a service account. By default, a project has a Cloud Build default service account. You can also specify a custom service account per trigger or per build, which is recommended for pipelines that need different permission boundaries.
The service account needs IAM roles for every action the pipeline performs. A pipeline that pushes images and deploys to Cloud Run needs these three roles at minimum:
roles/artifactregistry.writer: to push imagesroles/run.developer: to deploy Cloud Run servicesroles/iam.serviceAccountUser: to act as the Cloud Run service identity
Never grant roles/editor to a build service account. See the secure CI/CD pipelines guide for a thorough walkthrough of least-privilege setup and Workload Identity Federation for builds initiated from GitHub.
A complete example pipeline
This pipeline runs tests, builds and pushes a container image to Artifact Registry, then deploys to Cloud Run. Each stage depends on the one before it. A test failure stops the pipeline before an image is ever built.
steps:
# Step 1: Run unit tests — stop the build here if anything fails
- name: 'python:3.11'
entrypoint: bash
args:
- -c
- |
pip install -r requirements.txt
python -m pytest tests/ -v
id: run-tests
# Step 2: Build the image, tagged with the commit SHA for traceability
- name: 'gcr.io/cloud-builders/docker'
args:
- build
- -t
- europe-west2-docker.pkg.dev/$PROJECT_ID/api/api:$SHORT_SHA
- -t
- europe-west2-docker.pkg.dev/$PROJECT_ID/api/api:latest
- .
id: build-image
waitFor: ['run-tests']
# Step 3: Push both tags to Artifact Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', '--all-tags', 'europe-west2-docker.pkg.dev/$PROJECT_ID/api/api']
id: push-image
waitFor: ['build-image']
# Step 4: Deploy the SHA-tagged image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
args:
- gcloud
- run
- deploy
- api-service
- --image=europe-west2-docker.pkg.dev/$PROJECT_ID/api/api:$SHORT_SHA
- --region=europe-west2
- --platform=managed
waitFor: ['push-image']
images:
- 'europe-west2-docker.pkg.dev/$PROJECT_ID/api/api:$SHORT_SHA'
options:
logging: CLOUD_LOGGING_ONLY
machineType: E2_HIGHCPU_8A few things worth noting here:
- The deployment step uses
$SHORT_SHArather thanlatest. This means you can see exactly which commit is running in Cloud Run and roll back to a specific version if needed. logging: CLOUD_LOGGING_ONLYsends build logs to Cloud Logging rather than a GCS bucket. Easier to query, and keeps logs alongside your application logs.machineType: E2_HIGHCPU_8upgrades from the default 1 vCPU machine. For larger images or longer test suites, upgrading the machine type can cut build times considerably.
For a detailed walkthrough of building Docker images efficiently with Cloud Build, including layer caching and multi-stage builds, see Building Docker Images with Cloud Build.
Setting up service account permissions
Before your pipeline can push images or deploy services, the build service account needs the right roles. Run the following to identify the active service account and grant it:
# Get the Cloud Build default service account for your project
CB_SA=$(gcloud builds get-default-service-account --project=my-app-prod)
# Allow pushing images to Artifact Registry
gcloud projects add-iam-policy-binding my-app-prod \
--member="serviceAccount:${CB_SA}" \
--role="roles/artifactregistry.writer"
# Allow deploying Cloud Run services
gcloud projects add-iam-policy-binding my-app-prod \
--member="serviceAccount:${CB_SA}" \
--role="roles/run.developer"
# Required to act as the Cloud Run service identity
gcloud projects add-iam-policy-binding my-app-prod \
--member="serviceAccount:${CB_SA}" \
--role="roles/iam.serviceAccountUser"Google has updated the default Cloud Build service account behaviour in recent projects. Do not assume the account format — use gcloud builds get-default-service-account to resolve the active account before granting roles. If you are using GitHub-initiated builds, consider Workload Identity Federation instead of service account keys. The secure CI/CD pipelines guide covers the full setup.
When to use Cloud Build
Cloud Build is a practical fit when:
- You are building and deploying container images to GCP. Building an image, pushing it to Artifact Registry, and deploying it to Cloud Run or GKE fits naturally into a single pipeline. This is the core use case.
- You want tests to run on every commit. Connect a trigger to your main branch, define a test step, and Cloud Build handles the rest. Failed tests show up as failed builds in the console and as a GitHub commit status.
- Your team works primarily within GCP. Cloud Build integrates with GCP services without third-party credential management. The build service account authenticates with IAM. There are no API tokens to rotate or store externally.
- You do not want to maintain CI infrastructure. No servers, no agents, no OS updates, no downtime. Cloud Build scales automatically and requires zero maintenance beyond the pipeline config itself.
- You need native secrets integration. Cloud Build integrates with Secret Manager via the
availableSecretsblock. Secrets are injected into step environments at runtime and never stored in config files or build logs. See secrets in CI/CD pipelines for practical examples. - You are setting up CI/CD for Cloud Run. The CI/CD pipelines for Cloud Run guide shows how Cloud Build fits into a complete end-to-end pipeline for Cloud Run services specifically.
When Cloud Build may not be the best fit
Cloud Build is not the right tool for every situation.
- Your organisation is standardised on another CI platform. If your team runs Jenkins, CircleCI, or GitLab CI across all projects, adding Cloud Build creates fragmentation and doubles the surface area your team needs to understand. It is usually better to extend the existing platform with GCP integration than to introduce a second CI system.
- You need complex multi-environment delivery. Cloud Build can run deployments, but it has no native concept of environments, promotion workflows, or approval gates. For controlled delivery across dev, staging, and production, use Cloud Deploy, which is purpose-built for that problem.
- You have strict VPC networking requirements. Standard Cloud Build jobs run on Google-managed infrastructure and make outbound internet calls. If your pipeline needs to reach private resources on a VPC, a private worker pool is required, which adds configuration complexity and cost.
- You deploy to multiple cloud providers. Cloud Build is Linux-only and GCP-focused. If your delivery process spans AWS, Azure, or on-premises targets, a cross-platform tool like GitHub Actions gives you more flexibility.
- Portability across CI systems matters. Cloud Build config files are not portable to other platforms. If you want pipelines that can run locally or on any CI system, something closer to a portable standard (Tekton, which Cloud Build is built on, or Makefile-driven workflows) may suit better.
The multi-environment limitation is by design, not a gap. Cloud Build and Cloud Deploy are intended to work together: Cloud Build produces the tested, tagged artifact; Cloud Deploy delivers it through environments with promotion workflows and approval gates. Using both is the recommended GCP pattern, not a workaround. See Cloud Deploy Overview to understand where the handoff happens.
Cloud Build vs GitHub Actions
Both tools can build containers, run tests, and deploy to GCP. The decision usually comes down to where your team lives and what you are deploying to.
Where Cloud Build has an advantage
- Native GCP IAM integration: the build service account authenticates automatically with Artifact Registry, Cloud Run, and GKE without managing API keys or extra Workload Identity setup
- Build logs go directly to Cloud Logging alongside application logs, in the same tooling your team already uses for observability
- No GitHub Actions minutes consumed for GCP deployments, which can be more cost-effective for GCP-heavy teams
- Tighter integration with Cloud Deploy for multi-environment delivery with approval gates
- Build history and audit trail are retained inside GCP, subject to the same access controls as your other GCP resources
Where GitHub Actions has an advantage
- Simpler setup if your code is already on GitHub and you want a single system for both code review and CI
- Vast marketplace of pre-built actions for third-party services: Slack notifications, Jira updates, Terraform, and hundreds more
- macOS and Windows runners for cross-platform builds and mobile CI
- Better suited for workflows that span multiple cloud providers or on-premises infrastructure
- Pull request automation — comment-triggered builds, label-based workflows, and PR preview environments — is more mature
Choosing between them
Choose Cloud Build if your team is GCP-native, your targets are Cloud Run and GKE, and you want tight IAM integration with Secret Manager without additional credential setup.
Choose GitHub Actions if you are already on GitHub, you deploy to multiple platforms, or you want access to the community actions ecosystem.
Using both together
Many teams run both. GitHub Actions handles pull request checks — linting, formatting, unit tests — because these do not need GCP resources and benefit from the native GitHub PR status integration. Cloud Build handles GCP-specific steps: image builds, registry pushes, and deployments. This avoids granting GitHub Actions broad GCP permissions while keeping CI feedback visible on GitHub commits and PRs.
The most common combined pattern: GitHub Actions fires on pull requests for fast feedback checks. Cloud Build fires on pushes to main to build, push, and deploy. Neither tool needs to do everything. See GitHub Actions for GCP for how to set up Workload Identity Federation when GitHub Actions does need access to GCP resources.
Common beginner mistakes
Granting
roles/editorto the Cloud Build service account. Editor gives far more access than any build pipeline needs and is a significant security risk. Audit the roles your pipeline actually uses and grant only those. Start withroles/artifactregistry.writerandroles/run.developerfor a standard pipeline.Storing secrets in
cloudbuild.yaml. Build config files are committed to version control. Anything in the file is visible to anyone with repository access. Put secrets in Secret Manager and reference them using theavailableSecretsblock. See secrets in CI/CD pipelines for the full setup.Tagging images as
latestonly. Thelatesttag is overwritten on every push. Without a stable tag tied to a specific commit, you cannot see which version is running in production and rolling back becomes guesswork. Always include$SHORT_SHAalongside any mutable tags.Confusing Cloud Build with Cloud Deploy. Cloud Build runs build and test steps and produces an artifact. Cloud Deploy manages the controlled delivery of that artifact through environments. They solve different problems and are designed to work together. If you find yourself writing complex conditional deployment logic in
cloudbuild.yaml, you likely want Cloud Deploy handling that part instead.Assuming every step shares the full filesystem. Steps share only
/workspace. Files written to/tmpor any other path in one step will not be visible to the next. If a step needs to pass output to a later step, write it to/workspace.Using the deprecated
gcr.io/cloud-builders/gcloudbuilder. This image is deprecated and may stop receiving updates. Usegcr.io/google.com/cloudsdktool/cloud-sdkfor all gcloud commands.Using Container Registry for new projects. Container Registry (
gcr.io) is a legacy service. All new projects should use Artifact Registry with theREGION-docker.pkg.devpath format.Not separating build and deployment concerns. Mixing build steps, test steps, and deployment steps into a flat list without clear
waitFordependencies makes pipelines hard to read and debug. Use explicitidnames and keep the dependency chain visible. For multi-environment delivery, move the deployment concern to Cloud Deploy rather than growing thecloudbuild.yamlindefinitely.
Best practices
- Use least privilege for the build service account. Grant only the roles your pipeline needs. Review and remove any roles added for debugging. Consider a dedicated service account per pipeline rather than the project default, so different pipelines cannot access each other’s resources.
- Tag images with commit SHAs. Always include
$SHORT_SHAin your image tags. This gives you a traceable link between a running container and the code that produced it, and makes rollbacks straightforward. - Put your test step first and fail fast. There is no point building and pushing an image if the tests fail. A failed test step stops the pipeline immediately and saves build minutes.
- Keep secrets in Secret Manager. Use the
availableSecretsblock to inject secrets as environment variables at runtime. Secrets handled this way do not appear in logs, config files, or build history. - Use custom substitutions for environment differences. Define
$_REGION,$_PROJECT, and similar variables in your trigger configuration rather than hardcoding values. This makes a single pipeline config reusable across dev and production builds. - Set
logging: CLOUD_LOGGING_ONLY. This sends logs to Cloud Logging rather than a GCS bucket, making them easier to query and available alongside your application logs in the same tooling. - Use Cloud Deploy for multi-environment delivery. If you are promoting builds through dev, staging, and production, move the deployment concern to Cloud Deploy. Keep Cloud Build focused on producing a tested, tagged artifact. Cloud Build creates the release; Cloud Deploy delivers it.
- Link builds to deployments using the commit SHA. Use
$SHORT_SHAas the image tag and, when creating a Cloud Deploy release, as part of the release name. This creates a complete audit trail from commit to deployment that you can trace in either direction.
Frequently asked questions
What is Cloud Build used for?
Cloud Build automates the steps between a code commit and a running application. Typical uses are: running tests on every commit, building container images and pushing them to Artifact Registry, and deploying to Cloud Run or GKE. It handles both CI and simple CD in a single managed service, with no infrastructure to maintain.
Is Cloud Build a CI tool or a CD tool?
Both, depending on how you configure it. Cloud Build is primarily a CI tool: it runs automated build and test steps on every code change. It can also deploy (CD), but for complex multi-environment delivery with promotion workflows and approval gates, Google recommends pairing it with Cloud Deploy. The two services are designed to complement each other, not replace one another.
What is the difference between Cloud Build and Cloud Deploy?
Cloud Build runs the steps that produce an artifact: tests, image builds, registry pushes. Cloud Deploy handles the controlled delivery of that artifact through environments — dev, staging, production — with promotion workflows, approval gates, and rollback. Cloud Build ends when the image is tested and pushed. Cloud Deploy takes over from there. You typically trigger a Cloud Deploy release as the last step of a Cloud Build pipeline.
Does Cloud Build replace GitHub Actions?
Not necessarily. Cloud Build integrates natively with GCP services using IAM and requires no credential management for GCP targets. GitHub Actions works across any platform and has a broader third-party ecosystem. Many teams use both: GitHub Actions for PR feedback checks, Cloud Build for GCP-specific build and deployment steps. See the comparison section above and the GitHub Actions for GCP guide for help deciding.
What permissions does Cloud Build need?
Cloud Build runs as a service account. Grant only the roles your pipeline actually uses. For a standard build-and-deploy pipeline: roles/artifactregistry.writer to push images, roles/run.developer to deploy Cloud Run services, and roles/iam.serviceAccountUser to act as the Cloud Run service identity. Find the active service account with gcloud builds get-default-service-account. Never grant roles/editor to a build service account.
Summary
- Cloud Build is GCP’s managed CI/CD service: container-based steps, no servers or agents to manage
- Pipelines are defined in
cloudbuild.yamlat the root of your repository - Triggers fire on push to branch, push of tag, or pull request events
- Built-in substitutions:
$PROJECT_ID,$SHORT_SHA,$BRANCH_NAME,$TAG_NAME - Always tag images with
$SHORT_SHA, not justlatest - Grant the build service account only the roles it needs, never
roles/editor - Secrets belong in Secret Manager, accessed via
availableSecrets, not in config files - For multi-environment delivery with approval gates, use Cloud Deploy alongside Cloud Build
- Use
gcr.io/google.com/cloudsdktool/cloud-sdkfor gcloud steps — the old gcloud builder is deprecated
Frequently asked questions
What is Cloud Build used for?
Cloud Build automates the steps between a code commit and a running application: running tests, building container images, pushing them to Artifact Registry, and deploying to Cloud Run or GKE. It handles CI and simple CD in a single managed service with no servers to manage.
Is Cloud Build a CI or CD tool?
Both, depending on how you configure it. Cloud Build is primarily a CI tool that runs build and test automation on every code change. It can also deploy, but for multi-environment delivery with promotion workflows and approval gates, Google recommends pairing Cloud Build with Cloud Deploy.
What is the difference between Cloud Build and Cloud Deploy?
Cloud Build runs the steps that produce an artifact: tests, image builds, registry pushes. Cloud Deploy handles the controlled delivery of that artifact through environments with promotion workflows, approval gates, and rollback. They are designed to work together — Cloud Build creates the image, Cloud Deploy delivers it.
Does Cloud Build replace GitHub Actions?
Not necessarily. Cloud Build integrates natively with GCP services using IAM and requires no credential management for GCP targets. GitHub Actions works across any platform and has a broader ecosystem. Many teams use both: GitHub Actions for PR checks, Cloud Build for GCP deployments.
What permissions does Cloud Build need?
Cloud Build runs as a service account. Grant only the roles your pipeline uses: roles/artifactregistry.writer to push images, roles/run.developer to deploy Cloud Run services, and roles/iam.serviceAccountUser to act as the Cloud Run service identity. Never grant roles/editor.