Prepare and test your skills
Prepare and test your skills
Cloud Build (opens in a new tab) and Artifact Registry (opens in a new tab) form an automated pipeline that turns source code into versioned, deployable container images. Cloud Build compiles source into an image, checks the image for security issues, and pushes only trusted images to Artifact Registry. Artifact Registry then stores the images in controlled Docker repositories where runtimes such as Google Kubernetes Engine (GKE), Cloud Run, and Compute Engine can pull them.
Building and pushing images from source to Artifact Registry is the secure transfer of a built image to an address in the form LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME. The simplest path runs gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME from a directory with source and a Dockerfile, which builds and pushes without a config file. A build config file gives more control by defining steps that run builders such as gcr.io/cloud-builders/docker, and each step container attaches to a local Docker network named cloudbuild that provides Application Default Credentials for Google Cloud services.
Storing built images (opens in a new tab) in Artifact Registry supports three output mechanisms that differ in timing and visibility:
| Storage option | What it stores | Visibility in build results |
|---|---|---|
images field | Docker image pushed after the build completes | Shown on the Build description page, in Build.get(), and in gcloud builds list |
docker push step | Container image pushed during the step sequence | Not shown in build results |
artifacts.oci field | Open Container Initiative (OCI) image folder uploaded with file and registryPath | Stored as OCI artifact with optional tags |
Choose the images field when visibility in build results matters, and choose docker push when the push must happen at a specific point, such as only after a vulnerability check passes. To make an image available to later steps and still show it in results, include both with the same image path.
Exam tip: An image stored with the images field appears in Cloud Build results, while an image stored with docker push does not.
A cloudbuild.yaml file defines automation through its steps field, where each step runs a container as an instance of docker run. Each step names a builder image in name and passes tool commands in args, and by default Cloud Build runs all steps serially on the same machine. A config can include up to 300 steps with up to 100 arguments per step.
A typical containerization pipeline moves source through an ordered sequence:
docker builder runs docker build -t LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME . from the Dockerfile and workspace source.docker builder runs docker push with the same Artifact Registry path to send the image from the build worker to the repository.gcr.io/google.com/cloudsdktool/cloud-sdk with a gcloud entrypoint, to scan the image or deploy it.Steps share data through the /workspace directory, so one step can write an image digest or scan ID that a later step reads. Use id to name steps for tracking, waitFor to allow concurrent steps, and -f DOCKERFILE_PATH when the Dockerfile lives outside the source directory.
Substitution variables let one cloudbuild.yaml file target different projects, repositories, and environments without editing the file. Custom substitutions start with an underscore, such as $_IMAGE, $_PROJECT_ID, and $_SEVERITY, and are declared in a top-level substitutions map with default values. Built-in values such as ${PROJECT_ID} and ${BUILD_ID} resolve automatically, so the path LOCATION-docker.pkg.dev/${PROJECT_ID}/REPOSITORY/IMAGE_NAME adapts to the project that runs the build.
The build depends on options flags to control how substitutions flow into containers. Setting dynamicSubstitutions: true allows values like ${BUILD_ID} to resolve correctly, while automapSubstitutions: true maps substitutions into the container environment. Setting substitutionOption: ALLOW_LOOSE tells Cloud Build to ignore unused substitutions instead of failing. The same delivery goal can then start in three ways: with a config file using gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY, with only a Dockerfile using --tag, or with buildpacks using --pack image=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME and no Dockerfile. Build triggers extend this by watching Cloud Source Repositories, GitHub, or Bitbucket and starting the same build automatically on pushes or pull requests.
Scanning images and enforcing deploy-time integrity keeps vulnerable or unproven images out of production. Automatic vulnerability scanning scans images when they are uploaded to Artifact Registry and monitors them for new vulnerabilities for up to 30 days after the push. The On-Demand Scanning API scans local or stored images when gcloud artifacts docker images scan is called, so Cloud Build can scan after the build and block the push if a blocked severity is found.
A secure pipeline orders build, scan, check, and push so only clean images are stored:
/workspace/image-digest.txt./workspace/scan_id.txt.vulnerability.effectiveSeverity, and fail with exit 1 if a blocked severity is found.docker push only if the check succeeded.The gate blocks only levels in the _SEVERITY substitution, with supported values CRITICAL, HIGH, MEDIUM, and LOW. Because matching is exact, blocking HIGH and above requires CRITICAL|HIGH. At deploy time, Binary Authorization (opens in a new tab) enforces policy by allowing deployment only with required proof, such as vulnerability-scan compliance. Cloud Build supports this with ephemeral virtual machine workers destroyed after each build and Supply Chain Levels for Software Artifacts (SLSA) Level 3 provenance that verifies source, entry point, parameters, and builder identity.
Docker repositories (opens in a new tab) in Artifact Registry are regional or multi-regional containers for related images in one project, addressed as LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/IMAGE:TAG. Teams create separate repositories for testing, staging, or production and control access at the repository level. Images are versioned by mutable or immutable tags and manifest digests, and each Dockerfile instruction creates a layer. Images in the same registry reuse shared layers for storage efficiency, layers are never shared across registries, and unreferenced layers are cleaned up daily. The target repository must already exist before a push to the pkg.dev domain.
Access control grants Identity and Access Management (IAM) roles on individual repositories. The default Cloud Build service account can upload, download, and create gcr.io repositories in the same project, while the Compute Engine default service account, also used by GKE nodes and Cloud Run, can pull in the same project. Pushes across projects or with a user-specified service account require the Artifact Registry Writer role on the repository project. Repositories can also use customer-managed encryption keys (CMEK), VPC Service Controls perimeters, Pub/Sub notifications, and Image streaming to reduce GKE cold-start latency.
Artifact Registry is the recommended registry and separates administration from usage:
| Capability | Container Registry | Artifact Registry |
|---|---|---|
| Repository creation | Images push directly to gcr.io hosts backed by Cloud Storage buckets | Creating a repository is a separate step with no buckets to manage |
| Location | Four multi-regional hosts per project | Multiple regional or multi-regional repositories per project |
| Access control | Cloud Storage roles on the whole host | Artifact Registry roles on individual repositories, with conditional access by tags |
| Encryption | Encrypt buckets holding images with CMEK | Encrypt individual repositories with CMEK |
Efficient Dockerfiles order stable dependency steps before changing code, such as copying package*.json and running npm install --omit=dev or copying requirements.txt and running pip install before copying code. Java and .NET use multi-stage builds where a builder stage compiles the artifact and only the final output enters a smaller runtime image.
Configuring provenance in Cloud Build means generating verifiable build metadata and enforcing it at deploy time so only trusted images run. Cloud Build generates Supply-chain Levels for Software Artifacts (SLSA) provenance automatically, stores it in Artifact Analysis, and Binary Authorization (opens in a new tab) verifies required attestations when a workload deploys to Google Kubernetes Engine (GKE) or Cloud Run. The chain flows from builder to metadata store to admission control.
Attestors and attestations link a security gate to cryptography that Binary Authorization can verify. An attestor represents a trusted authority, such as a security team, and is associated with an Artifact Analysis note and one or more public keys. An attestation is a signed statement that a specific immutable image digest passed that authority's requirements, identified as IMAGE_PATH@IMAGE_DIGEST with a hash such as sha256:37e528....
An attestation authorizes the digest, not the mutable tag, so one attestation covers the identical image in Artifact Registry, Container Registry, or an external registry. Attestations are enforced only when the policy requires them through a default or cluster-specific rule naming those attestors. A special built-by-cloud-build attestor can require that only images built by Cloud Build deploy, which connects build provenance directly to enforcement.
Creating attestors and signing image digests establishes who is trusted and records each approval. An attestor is created after enabling Binary Authorization, using the console, Google Cloud CLI, or REST API, with its identity in an attestor project and its public key referencing a private key held locally or in Cloud Key Management Service (Cloud KMS). Using Cloud KMS keeps the private key in Google's managed service for central auditing, rotation, and reduced exposure. The attestor definition can live in a security-controlled attestor project while attestations are stored as occurrences in a separate attestation project, so no single identity controls both sides of the trust boundary.
The signing identity needs roles/containeranalysis.notes.attacher on the note and roles/containeranalysis.occurrences.editor on the attestation project. The end-to-end setup follows an ordered dependency:
build-secure or prod-qa, with its Cloud KMS public key and note.Images are not accessed during attestation creation, so the path does not need to refer to a live image at signing time.
Exam tip: An attestation always signs the immutable image digest, not the tag, so the same attestation remains valid when the identical digest appears in different registries.
Enforcing Binary Authorization policies controls which images run even when policy, cluster, and images live in different projects. The policy project holds the Binary Authorization policy, the cluster project holds the GKE cluster, and the artifact project holds the Artifact Registry or Container Registry repository. The Binary Authorization service agent is the Google Cloud-managed service account that reads policy and image metadata to decide admission.
Cross-project access is required when the policy project differs from the cluster project, because the cluster must read policy from another project. Access is also required when the cluster project differs from the artifact project, because the service agent must read image metadata from another project. If either permission path is missing, allowed images cannot be verified and dependent deployments fail. Preparing enforcement means creating or selecting a project with billing enabled, enabling the binaryauthorization.googleapis.com API, and managing setup with project creation, selection, and API enablement commands. Project creation needs the Project Creator role with resourcemanager.projects.create, while enabling APIs needs serviceusage.services.enable through Owner or Service Usage Admin.
Generating and storing SLSA build provenance explains how verifiable metadata moves from builder to long-term storage. Cloud Build provenance describes builder identity, build inputs, and outputs, including signed builder identities, the service account that initiated the build, and dependencies in resolvedDependencies. The full payload is stored base-64 encoded, with a current signature recommended for new Binary Authorization policies and a second builtByGCB signature kept only for legacy usage.
Generation for non-container artifacts happens automatically when standalone applications are built and uploaded to Artifact Registry, covering Go applications, Java applications built with Maven, Python applications, and Node.js applications built with npm. Data flows from the Cloud Build job to Artifact Registry as the artifact destination and from Cloud Build to Artifact Analysis as the metadata destination. Storage in Artifact Analysis keeps each record as a BUILD occurrence with in-toto SLSA provenance, linked by build.inTotoSlsaProvenanceV1.predicate.runDetails.metadata.invocationId containing https://cloudbuild.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/builds/BUILD_ID. Retrieval filters for kind="BUILD" and the matching invocationId using gcloud container analysis occurrences list or the Container Analysis API, though filtering on the nested invocationId can be slower in projects with very many occurrences.
| Signing option | Where private key lives | Choose when |
|---|---|---|
| Locally stored key | On signer workstation or build worker | Workflow is a small test without central key control |
| Cloud KMS key | In Cloud KMS, using versions and algorithms such as ECDSA_P256_SHA256 | Production gates need central management, auditing, separation of duties, and protection from exfiltration |
Continue with this study guide: Configuring provenance in Cloud Build (e.g., Binary Authorization)
LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME.images field appears in Cloud Build results, while an image stored with docker push inside a build step does not.BUILD occurrence linked by invocation ID containing project ID, location, and BuildID.The images field pushes the Docker image after the build completes and shows it on the Build description page, in Build.get(), and in gcloud builds list, while a docker push step pushes the image during the step sequence and does not appear in build results. Choose the images field when visibility in build results matters and choose docker push when the push must happen at a specific point, such as only after a vulnerability check passes.
On-Demand Scanning scans local or stored images when called so Cloud Build can scan after the build and block the push if a blocked severity is found. Automatic vulnerability scanning scans images when they are uploaded to Artifact Registry and monitors them for new vulnerabilities for up to 30 days after the push.
An attestation is a signed statement that a specific immutable image digest passed a trusted authoritys requirements, so it authorizes the digest and not the mutable tag. Binary Authorization verifies the required attestations when a workload deploys to Google Kubernetes Engine or Cloud Run and allows deployment only with the required proof, as defined by a default or cluster-specific policy rule naming those attestors.
Last updated