Skip to main content

Artifact Registry

Artifact Registry is GCP's fully managed package and container registry. It replaces Container Registry (GCR) and adds vulnerability scanning, IAM-based access control, and native integration with Cloud Build and Cloud Run. For ML workloads, it's where you store the Docker images that power your model servers.

Why Artifact Registry?

FeatureArtifact RegistryDocker HubGCR (Legacy)
Vulnerability scanningBuilt-inLimitedBasic
IAM access controlYesNoLimited
Regional replicationYesNoNo
Multiple formatsDocker, Maven, npm, PythonDocker onlyDocker only
CI/CD integrationNative GCPManualNative GCP
Pricing0.50 USD/GB/monthFree (public)Same

1. Create a Docker Repository

bash
# Set variables
export PROJECT_ID="your-project-id"
export REGION="us-central1"
export REPO_NAME="ml-images"

# Create a Docker-format repository
gcloud artifacts repositories create ${REPO_NAME} \
--repository-format=docker \
--location=${REGION} \
--description="Docker images for ML model servers" \
--project=${PROJECT_ID}

# Verify the repository
gcloud artifacts repositories describe ${REPO_NAME} \
--location=${REGION}

# List all repositories
gcloud artifacts repositories list --location=${REGION}

2. Authenticate Docker

Before pushing or pulling, configure Docker to authenticate with Artifact Registry:

bash
# One-time auth setup (valid for 4 hours)
gcloud auth configure-docker ${REGION}-docker.pkg.dev

# Verify auth
docker login ${REGION}-docker.pkg.dev

3. Push Docker Images

Build your ML container and push it to Artifact Registry:

bash
# Build and tag the image
export IMAGE_TAG="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor:v1.0.0"

docker build -t ${IMAGE_TAG} .

# Push the image
docker push ${IMAGE_TAG}

# List images in the repository
gcloud artifacts docker images list \
${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME} \
--include-tags

Tagging conventions

Use a consistent tagging strategy for ML images:

bash
# Semantic versioning for releases
docker tag ml-predictor:latest ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor:1.2.0

# Git SHA for traceability
docker tag ml-predictor:latest ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor:sha-abc1234

# Environment tags
docker tag ml-predictor:latest ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor:staging
docker tag ml-predictor:latest ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor:production
Tag TypeFormatUse Case
SemVer1.2.0Production releases
Git SHAsha-abc1234Traceability, rollback
Environmentstaging, productionDeployment targets
LatestlatestDevelopment only (never in prod)

4. Pushing from CI/CD (Cloud Build)

Automate image builds and pushes with Cloud Build:

yaml
# cloudbuild.yaml
steps:
# Step 1: Build the Docker image
- name: "gcr.io/cloud-builders/docker"
args:
[
"build",
"-t",
"${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor:${SHORT_SHA}",
"-t",
"${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor:latest",
".",
]

# Step 2: Push the image (both tags)
- name: "gcr.io/cloud-builders/docker"
args: ["push", "--all-tags", "${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor"]

# Step 3: Deploy to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
args:
[
"run",
"deploy",
"ml-predictor",
"--image=${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor:${SHORT_SHA}",
"--region=${_REGION}",
"--platform=managed",
]

substitutions:
_REGION: us-central1
_REPO: ml-images

images:
- "${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor:${SHORT_SHA}"
- "${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor:latest"
bash
# Trigger the build manually
gcloud builds submit --config=cloudbuild.yaml \
--substitutions=_REGION=us-central1,_REPO=ml-images

# Or set up a trigger from GitHub
gcloud builds triggers create github \
--repo-name=your-repo \
--repo-owner=your-org \
--branch-pattern="^main$" \
--build-config=cloudbuild.yaml

5. Vulnerability Scanning

Artifact Registry can automatically scan images for known security vulnerabilities (CVEs):

bash
# Enable vulnerability scanning on the repository
gcloud artifacts repositories update ${REPO_NAME} \
--location=${REGION} \
--enable-vulnerability-scanning

# Scan a specific image
gcloud artifacts docker images scan \
${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor:v1.0.0

# Get scan results
gcloud artifacts docker images list-vulnerabilities \
${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor@sha256:abc123...

Vulnerability severity levels

LevelAction
CRITICALMust fix before deploying. Block in CI/CD.
HIGHFix within 24 hours. Alert the team.
MEDIUMFix within 1 week. Track in backlog.
LOWFix opportunistically.

CI/CD vulnerability gate

yaml
# Add to cloudbuild.yaml — block deployment on critical vulnerabilities
steps:
- name: "gcr.io/cloud-builders/gcloud"
entrypoint: "bash"
args:
- "-c"
- |
SCAN_RESULT=$(gcloud artifacts docker images scan \
${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPO}/ml-predictor:${SHORT_SHA} \
--format="value(response.vulnerabilityCount)")
if [ "$SCAN_RESULT" -gt 0 ]; then
echo "Vulnerabilities found! Check scan results."
exit 1
fi

6. Image Versioning and Cleanup

Over time, old images accumulate and consume storage. Set up cleanup policies:

bash
# List all versions of an image
gcloud artifacts docker images list \
${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor \
--include-tags \
--format="table(version,metadata.tag,metadata.uploadTime)"

# Delete a specific version
gcloud artifacts docker images delete \
${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/ml-predictor@sha256:abc123... \
--delete-tags \
--quiet

# Set a cleanup policy (keep last 10 versions)
gcloud artifacts repositories set-cleanup-policies ${REPO_NAME} \
--location=${REGION} \
--policy=cleanup-policy.json
json
// cleanup-policy.json
[
{
"name": "keep-last-10",
"action": { "type": "KEEP", "mostRecentVersions": { "keepCount": 10 } },
"condition": { "packageName": "ml-predictor" }
},
{
"name": "delete-untagged-older-than-30d",
"action": { "type": "DELETE" },
"condition": {
"packageName": "ml-predictor",
"olderThan": "2592000s",
"tagState": "UNTAGGED"
}
}
]

7. IAM Access Control

Control who can push and pull images:

bash
# Grant read access to all developers
gcloud artifacts repositories add-iam-policy-binding ${REPO_NAME} \
--location=${REGION} \
--member="group:developers@company.com" \
--role="roles/artifactregistry.reader"

# Grant write access to CI/CD service account
gcloud artifacts repositories add-iam-policy-binding ${REPO_NAME} \
--location=${REGION} \
--member="serviceAccount:cloudbuild@your-project-id.iam.gserviceaccount.com" \
--role="roles/artifactregistry.writer"

# Grant admin access to ML platform team
gcloud artifacts repositories add-iam-policy-binding ${REPO_NAME} \
--location=${REGION} \
--member="group:ml-platform@company.com" \
--role="roles/artifactregistry.admin"

Artifact Registry Checklist

  • Create regional Docker repository for ML images
  • Use semantic versioning + git SHA tags
  • Enable vulnerability scanning on the repository
  • Set up CI/CD pipeline with Cloud Build
  • Add vulnerability gate to block critical CVEs
  • Configure cleanup policies to manage storage costs
  • Restrict push access to CI/CD service accounts only
  • Never use latest tag in production deployments