Skip to content

07 — Artifact Registry

Previous: 06 — GCP Project & APIs

Artifact Registry is where Docker images are stored. When GitHub Actions builds your app, it pushes the image here. Cloud Run pulls from here when deploying.


What is Artifact Registry?

Artifact Registry is GCP's private container registry — like Docker Hub, but inside your GCP project and private. Docker images are stored here, and only Cloud Run (or other GCP services) can pull from it.

Why private? Because the image contains your code. You don't want it publicly accessible.


Create the registry with Terraform

Add to infrastructure/main.tf:

# Artifact Registry repository for Docker images
resource "google_artifact_registry_repository" "app" {
  location      = var.region
  repository_id = "app-repo"
  description   = "Docker images for MyCoolProject"
  format        = "DOCKER"

  # Cleanup on destroy (removes all images when you run terraform destroy)
  force_destroy = true
}

output "artifact_registry_url" {
  value       = google_artifact_registry_repository.app.repository_url
  description = "The URL of the Artifact Registry repository"
}

Run:

terraform plan   # Review
terraform apply  # Create

What this creates

The repository URL will be:

southamerica-east1-docker.pkg.dev/mycoolproject-prod/app-repo

Images pushed here will be named like:

southamerica-east1-docker.pkg.dev/mycoolproject-prod/app-repo/app:latest
southamerica-east1-docker.pkg.dev/mycoolproject-prod/app-repo/app:<git-sha>


Configure local Docker authentication

To push images from your local machine, you need to authenticate Docker to Artifact Registry. This is a one-time setup per machine:

gcloud auth configure-docker southamerica-east1-docker.pkg.dev

This updates ~/.docker/config.json to use your gcloud credentials when pushing to this registry. GitHub Actions handles this automatically with its own authentication.


Image naming convention

We'll use two tags for each image:

  • latest — always points to the most recent build
  • <git-sha> — a unique tag per commit (e.g., a3f9c12) — enables precise rollbacks

GitHub Actions workflow will: 1. Build the image with both tags 2. Push both tags to Artifact Registry 3. Deploy using the <git-sha> tag

This way, if something goes wrong, you can instantly roll back to the previous image using git-sha.


Update main.tf with all resources so far

After completing chapters 05-07, your main.tf should contain:

terraform {
  required_version = ">= 1.5.0"

  backend "gcs" {
    bucket = "mycoolproject-terraform-state"
    prefix = "terraform/state"
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}

# Enable required GCP APIs
resource "google_project_service" "apis" {
  for_each = toset([
    "run.googleapis.com",
    "artifactregistry.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "iam.googleapis.com",
    "storage.googleapis.com",
    "secretmanager.googleapis.com",
    "cloudscheduler.googleapis.com",
    "cloudtasks.googleapis.com",
    "servicenetworking.googleapis.com",
    "vpcaccess.googleapis.com",
  ])

  project = var.project_id
  service = each.value

  disable_dependent_services = false
  disable_on_destroy         = false
}

# Artifact Registry repository
resource "google_artifact_registry_repository" "app" {
  location      = var.region
  repository_id = "app-repo"
  description   = "Docker images for MyCoolProject"
  format        = "DOCKER"
  force_destroy = true
}

# Fetch project data
data "google_project" "project" {}

# Outputs
output "project_id" {
  value = var.project_id
}

output "project_number" {
  value = data.google_project.project.number
}

output "region" {
  value = var.region
}

output "artifact_registry_url" {
  value = google_artifact_registry_repository.app.repository_url
}