registry-migration
Skill0 starsChanged 6 months agoApache-2.0View on GitHub
Migrate container images from Amazon ECR to Google Artifact Registry. Plans the AR repo layout, mirrors images (skopeo or pull-through), updates build pipelines, sets up vulnerability scanning, and produces an image-map.json mapping every old image reference to its new one. Use when "migrate ECR to Artifact Registry", "set up image registries on GCP", or as Phase 3 of a Portage migration.
1 other project uses a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- GoogleCloudPlatform/cloud-solutionsedited, first seen Nov 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- GoogleCloudPlatform/cloud-solutions★ 13939% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository13 other files it gives its agents.
- data-migrationSkill
- eks-discoverySkill
- gke-landing-zoneSkill
- identity-translationSkill
- migration-assessmentSkill
- network-translationSkill
- observability-translationSkill
- portage-orchestratorSkill
- post-migration-opsSkill
- rollback-playbookSkill
- storage-translationSkill
- traffic-cutoverSkill
- workload-translationSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Every container image referenced from any Kubernetes workload has to be reachable from GKE — preferably from a regional Artifact Registry — …
- Very specific: line 130
GitHub Actions: add a google-github-actions/auth@v2 step (using Workload Identity Federation), then google-github-actions/setup-gcloud@v2, …
- Distinctive: line 131
CodeBuild / CodePipeline: add a parallel push step that pushes to AR using a service account key OR (preferred) federated identity into GCP.
- Very specific: line 133
Tekton: add a second image-push task targeting AR.
- Distinctive: line 175
After cutover and soak, EKS push step retired, then ECR repos retired (separate decommission).
- Distinctive: line 213
Every image referenced by any translated workload exists in AR with matching digest.
- Distinctive: line 230
Pipelines that hardcode AWS region in image refs: When the dual-push goes live, those pipelines break in non-obvious ways.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Registry Migration
You move container images from ECR to Artifact Registry, set up vulnerability scanning, update build pipelines, and produce a mapping file the rest of Portage uses to rewrite image references.
Purpose
Every container image referenced from any Kubernetes workload has to be reachable from GKE — preferably from a regional Artifact Registry — at low latency, with vulnerability scanning, and (when in scope) with Binary Authorization attestations.
When to use this skill
- Phase 3 of a Portage migration.
- The user asks to "set up Artifact Registry", "mirror ECR to GCP", "migrate images".
Prerequisites
01-discovery/inventory.jsonECR section.03-landing-zone/plan.mdwith theartifact-registryshared project provisioned.gcloud,aws,skopeoCLIs.- Either skopeo with credentials for both registries OR a CI/CD runner with both credentials.
Procedure
Step 1 — Plan the AR repo layout
Default layout:
projects/artifact-registry/locations/<region>/repositories/<repo-name>Naming: one AR repository per ECR repository, same name. Multi-region repos for global distribution if cross-region pulls matter.
Decide repo format:
- Standard repository: contains images directly. One per (env × team) is the typical shape, OR mirror ECR's existing per-app structure 1:1 to keep image references close to identical.
- Virtual repository: aggregates upstream registries (Docker Hub, public ECR Public). Use to standardize where pull-through caching is needed.
- Remote repository: mirrors a single upstream (Docker Hub, NPM). Use for bringing public images on-cluster without depending on Docker Hub directly.
For this migration:
- Plan a standard AR repo per ECR repo, in the user's primary region (e.g.,
us-central1). - For repos with very high cross-region pull rates, plan an additional repo in the second region with replication.
- Plan a remote repo for
docker.ioandquay.ioif the workloads pull public images directly.
Step 2 — Provision AR repos
Terraform per repo:
resource "google_artifact_registry_repository" "payments_api" {
project = var.ar_project
location = var.region
repository_id = "payments-api"
format = "DOCKER"
docker_config { immutable_tags = false } # tighten later if desired
cleanup_policies {
id = "keep-recent-100"
action = "KEEP"
most_recent_versions { keep_count = 100 }
}
cleanup_policies {
id = "delete-untagged-after-30d"
action = "DELETE"
condition {
tag_state = "UNTAGGED"
older_than = "2592000s"
}
}
cleanup_policy_dry_run = true # flip to false after one cleanup cycle of review
}For pull-through cache:
resource "google_artifact_registry_repository" "docker_hub_remote" {
project = var.ar_project
location = var.region
repository_id = "docker-hub"
format = "DOCKER"
mode = "REMOTE_REPOSITORY"
remote_repository_config {
docker_repository { public_repository = "DOCKER_HUB" }
}
}Step 3 — Mirror images
For each ECR repo + tag/digest in scope:
SRC=123456789012.dkr.ecr.us-east-1.amazonaws.com/payments/api:1.4.2
DST=us-central1-docker.pkg.dev/artifact-registry-prod/payments-api:1.4.2
aws ecr get-login-password --region us-east-1 \
| skopeo login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
gcloud auth print-access-token \
| skopeo login --username oauth2accesstoken --password-stdin us-central1-docker.pkg.dev
skopeo copy --multi-arch=all --preserve-digests \
docker://${SRC} \
docker://${DST}For the bulk move, drive a parallel job:
jq -r '.[] | select(.kind=="image") | "\(.src)|\(.dst)"' image-plan.json \
| xargs -P 8 -I{} bash -c 'IFS="|" read SRC DST <<< "$1"; \
skopeo copy --multi-arch=all --preserve-digests docker://$SRC docker://$DST' _ {}--preserve-digests ensures digests survive the copy, which is critical if any deployment pins by digest (it should).
Step 4 — Update build pipelines
For each upstream pipeline:
- GitHub Actions: add a
google-github-actions/auth@v2step (using Workload Identity Federation), thengoogle-github-actions/setup-gcloud@v2, then push to*.pkg.dev/.... Keep ECR push for a co-existence period. - CodeBuild / CodePipeline: add a parallel push step that pushes to AR using a service account key OR (preferred) federated identity into GCP.
- Cloud Build / Cloud Deploy: native push to AR.
- Tekton: add a second
image-pushtask targeting AR.
Produce a checklist 08-registry-migration/pipelines.md listing every pipeline, the change to make, and the verification step.
Step 5 — Build the image-map
Produce 08-registry-migration/image-map.json:
[
{
"src": "123456789012.dkr.ecr.us-east-1.amazonaws.com/payments/api:1.4.2",
"dst": "us-central1-docker.pkg.dev/artifact-registry-prod/payments-api:1.4.2",
"src_digest": "sha256:abc...",
"dst_digest": "sha256:abc...",
"consumed_by": ["payments/payments-api"]
}
]workload-translation consumes this to rewrite image refs.
Step 6 — Vulnerability scanning + Binary Authorization
Enable Artifact Analysis (formerly Container Analysis) on the AR project. New images push automatically scan. Surface findings in 08-registry-migration/vuln-baseline.md so the team has a starting state.
For Binary Authorization (when in scope):
- Plan an attestor:
gcloud container binauthz attestors create …. - Plan an attestation policy on the cluster (start in
EVALUATIONmode, switch toENFORCEafter a review window). - Wire CI to attest on push (Cloud Build has built-in support; for GitHub Actions, use
google-github-actions/attest-build-provenanceorcosign sign).
Step 7 — Cutover plan for image references
The image references in workloads should be rewritten in the same change that deploys to GKE. Until cutover, EKS continues to pull from ECR.
Sequence:
- AR repos exist.
- Initial mirror done; ongoing mirror automated (a Cloud Scheduler + Cloud Run job, or CI step).
- Pipelines push to both ECR and AR.
- GKE workloads reference AR.
- After cutover and soak, EKS push step retired, then ECR repos retired (separate decommission).
Step 8 — Decommission plan for ECR
Produce 08-registry-migration/ecr-decommission.md:
- Per-repo decommission date (default: 30 days post final cutover for that workload).
- Final image archive: tag
archive-YYYYMMDDand copy to a long-term Cloud Storage bucket if compliance requires. - IAM cleanup: scoped IAM roles, lifecycle policies.
Decision points
| Decision | Default | When to deviate |
| AR repo structure | One AR repo per ECR repo, same name | Restructure if ECR layout was historically painful |
| Region | Same region as primary GKE cluster | Multi-region replication for >2 regions |
| Pull-through caches | One for docker.io, one for quay.io (if used) | Skip if you mirror everything explicitly |
| Cleanup policy | Keep 100 most recent + delete untagged > 30d | Tighter (10 most recent) for non-prod |
| Binary Authorization | Enabled in EVALUATION mode initially | ENFORCE mode only after attestation pipeline runs cleanly for >2 weeks |
Outputs / Deliverables
08-registry-migration/
├── repos.md # Per-AR-repo plan
├── terraform/
│ └── artifact-registry.tf
├── mirror-plan.json # Source images, target images, mirror command
├── image-map.json # Used by workload-translation
├── pipelines.md # Per-pipeline change list
├── vuln-baseline.md # Initial Artifact Analysis findings
├── binauthz/ # Attestor + policy YAMLs (optional)
├── ecr-decommission.md
└── escalations.mdValidation
- Every image referenced by any translated workload exists in AR with matching digest.
gcloud container images describe <full-ref>succeeds for every image inimage-map.json.- A test pod on GKE successfully pulls a representative image without auth issues (KSA → GSA with
roles/artifactregistry.readeron the AR project). - New CI runs push to AR and the image appears with the new tag within 5 minutes.
- (If BinAuthz enabled)
EVALUATIONmode logs show every push attestation event.
Escalation triggers
- ECR images in repos using lifecycle rules whose retention exceeds AR cleanup policies the user is willing to set. Surface for re-decision.
- Images larger than AR's per-image / per-layer limits (rare). Surface and discuss split.
- Cross-cloud egress costs from initial mirror exceed the user's per-month tolerance. Surface plan: throttled mirror, region-by-region.
- ECR repos referenced by workloads in another AWS account (cross-account pulls). Discovery should have flagged; if not, surface here.
Common pitfalls
- Pushing without
--preserve-digests. Re-built images get new digests and break digest-pinned deployments. - Forgetting Workload Identity → AR reader. GSAs that pull from AR need
roles/artifactregistry.readeron the AR project, not just on the cluster project. - Pipelines that hardcode AWS region in image refs. When the dual-push goes live, those pipelines break in non-obvious ways.
- Pull-through caches that tag-pin. A pull-through cache pinning
latestfrom Docker Hub returns whatever the cache last fetched, not the reallatest. - Not seeding the cache. The first cluster pull of every cached upstream image is slow. Pre-warm before cutover.
References
- Canonical sources: reference/sources.md.
- Artifact Registry overview.
- Artifact Analysis (vulnerability scanning).
- Binary Authorization.
- Sigstore + Binary Authorization on GKE.
- SLSA framework.
- docs/glossary.md — registry mapping.
- workload-translation — consumes image-map.json.
- identity-translation — KSA needs
artifactregistry.reader.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

