Container Images: Artifact Registry Repository
Scenario
Before you can deploy containers to Cloud Run or GKE, you must store their images in a secure registry. Google Cloud replaced the legacy "Container Registry (GCR)" with Artifact Registry. You need to create a Docker repository and grant a specific service account read access to it so it can pull the images during deployment.
- Create a google_artifact_registry_repository of format DOCKER.
- Set the location of the repository to your region.
- Create a google_service_account to act as your deployment principal.
- Create a google_artifact_registry_repository_iam_member giving that service account the roles/artifactregistry.reader role on the repository.
- Output the full repository pull URL (e.g., us-central1-docker.pkg.dev/proj/repoName).
Additional Context
Cleanup Policies: In a real-world scenario, container registries grow indefinitely, costing money. Artifact Registry supports "Cleanup Policies" (like keeping the 10 most recent images, or deleting anything older than 30 days that isn't tagged 'latest'). Terraform supports this via the `cleanup_policies` block.
Formats: Artifact Registry doesn't just hold Docker images. It can act as a private NPM registry, Maven repository, Python package index, or Apt/Yum package manager backend.
variables.tf
variable "project_id" { type = string }
variable "gcp_region" { type = string; default = "us-central1" }main.tf
provider "google" {
project = var.project_id
region = var.gcp_region
}
# 1. The Deployment Service Account
resource "google_service_account" "deployer" {
account_id = "docker-deployer"
display_name = "Docker Image Deployer"
}
# 2. The Artifact Registry Repository
resource "google_artifact_registry_repository" "app_repo" {
location = var.gcp_region
repository_id = "app-container-repo"
description = "Docker repo for main application services"
format = "DOCKER"
# Basic cleanup policy: keep only the newest 5 versions of any image
cleanup_policies {
id = "keep-minimum-versions"
action = "KEEP"
most_recent_versions {
keep_count = 5
}
}
}
# 3. Grant the SA permission to read images from THIS specific repository
resource "google_artifact_registry_repository_iam_member" "reader" {
project = google_artifact_registry_repository.app_repo.project
location = google_artifact_registry_repository.app_repo.location
repository = google_artifact_registry_repository.app_repo.name
role = "roles/artifactregistry.reader"
member = "serviceAccount:${google_service_account.deployer.email}"
}outputs.tf
output "repository_url" {
value = "${var.gcp_region}-docker.pkg.dev/${var.project_id}/${google_artifact_registry_repository.app_repo.name}"
description = "The root URL used to tag and push docker images"
}Workflow Commands
terraform init
terraform apply -var="project_id=my-gcp-project-123"
# Authenticate local Docker daemon to the registry
gcloud auth configure-docker us-central1-docker.pkg.dev
# Tag a local image for the registry
docker tag my-app:latest $(terraform output -raw repository_url)/my-app:v1
# Push the image
docker push $(terraform output -raw repository_url)/my-app:v1
terraform destroy -var="project_id=my-gcp-project-123"Apply complete! Resources: 3 added, 0 changed, 0 destroyed. Outputs: repository_url = "us-central1-docker.pkg.dev/my-gcp-project-123/app-container-repo"

