| name | container-registry |
| description | Container registry management patterns covering tagging strategy, immutability, retention policies, vulnerability scanning, multi-arch builds, and CI/CD integration. Internal reference for agents managing infrastructure. |
| allowed-tools | ["Read","Grep","Glob"] |
Knowledge Pack: Container Registry Management
Purpose
Provide production-grade container registry management patterns for tagging, security scanning, retention, and CI/CD integration across major registry providers.
1. Tagging Strategy
Primary Pattern
{registry}/{namespace}/{service}:{semver}-{git-sha-short}
Tag Types
| Tag Type | Pattern | Example | Use Case |
|---|
| Release | {semver}-{sha} | 1.2.3-abc1234 | Production deployments |
| Branch | {branch}-{sha} | main-abc1234 | Pre-release / staging |
| PR | pr-{number}-{sha} | pr-42-abc1234 | Pull request previews |
| Latest | latest | latest | Dev only (never in prod) |
Tagging Rules
- Every image MUST include the short Git SHA for traceability.
- Semantic version tags MUST be immutable (never re-push the same tag).
- The
latest tag is mutable and MUST NOT be used in production manifests.
- Branch tags are mutable within a branch lifecycle and suitable for staging.
- Use OCI annotations for metadata rather than encoding all info in the tag.
Example CI Tag Generation
#!/usr/bin/env bash
set -euo pipefail
REGISTRY="registry.example.com"
SERVICE="my-service"
SHA_SHORT="$(git rev-parse --short=7 HEAD)"
if [[ "${GITHUB_REF}" =~ ^refs/tags/v ]]; then
VERSION="${GITHUB_REF#refs/tags/v}"
IMAGE="${REGISTRY}/${SERVICE}:${VERSION}-${SHA_SHORT}"
docker tag "${SERVICE}:build" "${IMAGE}"
docker push "${IMAGE}"
fi
if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
IMAGE="${REGISTRY}/${SERVICE}:main-${SHA_SHORT}"
docker tag "${SERVICE}:build" "${IMAGE}"
docker push "${IMAGE}"
fi
if [[ "${GITHUB_REF}" =~ ^refs/pull/ ]]; then
PR_NUMBER="${GITHUB_REF#refs/pull/}"
PR_NUMBER="${PR_NUMBER%/merge}"
IMAGE="/:pr--"
docker tag
docker push
2. Immutability
Configuration per Registry
Amazon ECR
aws ecr put-image-tag-mutability \
--repository-name my-service \
--image-tag-mutability IMMUTABLE
resource "aws_ecr_repository" "my_service" {
name = "my-service"
image_tag_mutability = "IMMUTABLE"
image_scanning_configuration {
scan_on_push = true
}
encryption_configuration {
encryption_type = "AES256"
}
}
Azure Container Registry (ACR)
az acr repository update \
--name myregistry \
--image my-service:1.0.0-abc1234 \
--write-enabled false
# Terraform
resource "azurerm_container_registry" "main" {
name = "myregistry"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
sku = "Premium"
admin_enabled = false
retention_policy {
days = 30
enabled = true
}
}
Google Artifact Registry (GAR)
gcloud artifacts repositories create my-repo \
--repository-format=docker \
--location=us-central1 \
--description="Production images"
Harbor
3. Retention Policies
Standard Policy
| Rule | Value | Rationale |
|---|
| Keep last N tagged images | 10 | Rollback window for production |
| Auto-delete untagged manifests | After 7 days | Clean up intermediate builds |
| Keep release tags | Indefinitely | Audit trail for versioned releases |
| Delete PR tags | After 14 days | Short-lived preview environments |
Amazon ECR Lifecycle Policy
{
"rules": [
{
"rulePriority": 1,
"description": "Remove untagged images after 7 days",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 7
},
"action": {
"type": "expire"
}
},
{
"rulePriority": 2,
"description": "Remove PR images after 14 days",
"selection": {
"tagStatus":
# Terraform
resource "aws_ecr_lifecycle_policy" "my_service" {
repository = aws_ecr_repository.my_service.name
policy = file("${path.module}/ecr-lifecycle-policy.json")
}
Azure ACR Retention
az acr run --cmd "acr purge \
--filter 'my-service:.*' \
--untagged \
--ago 7d" \
--registry myregistry /dev/null
az acr task create \
--name purge-untagged \
--registry myregistry \
--cmd "acr purge --filter '.*:.*' --untagged --ago 7d" \
--schedule "0 2 * * *" \
--context /dev/null
Google Artifact Registry Cleanup
gcloud artifacts repositories set-cleanup-policies my-repo \
--location=us-central1 \
--policy=policy.json
{
"cleanupPolicies": [
{
"id": "delete-untagged",
"action": { "type": "Delete" },
"condition": {
"tagState": "UNTAGGED",
"olderThan": "604800s"
}
},
{
"id": "keep-minimum-versions",
"action": { "type": "Keep" },
"mostRecentVersions": {
"keepCount": 10
}
}
]
}
4. Vulnerability Scanning
Trivy Integration
name: Container Scan
on:
push:
branches: [main]
pull_request:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t my-service:scan .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: my-service:scan
format: table
exit-code: 1
severity: CRITICAL,HIGH
ignore-unfixed: true
vuln-type: os,library
- name: Run
Blocking Policy for Critical CVEs
CVE-2024-XXXXX
CI Gate Decision Table
| Severity | PR Build | Main Branch | Release Tag |
|---|
| Critical | Block | Block | Block |
| High | Warn | Block | Block |
| Medium | Info | Warn | Warn |
| Low | Ignore | Info | Info |
5. Multi-Arch Builds
Docker Buildx Setup
docker buildx create --name multiarch --driver docker-container --use
docker buildx inspect --bootstrap
Build and Push Multi-Arch Image
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag registry.example.com/my-service:1.0.0-abc1234 \
--push \
--cache-from type=registry,ref=registry.example.com/my-service:cache \
--cache-to type=registry,ref=registry.example.com/my-service:cache,mode=max \
.
GitHub Actions Multi-Arch Build
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: registry.example.com
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
registry.example.com/my-service:${{ github.sha }}
registry.example.com/my-service:latest
cache-from: type=gha
cache-to: type=gha,mode=max
6. CI/CD Integration
Complete Pipeline: Build, Scan, Push, Deploy
name: Build and Deploy
on:
push:
branches: [main]
tags: ["v*"]
env:
REGISTRY: registry.example.com
SERVICE: my-service
jobs:
build:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
-
[, ]
Pipeline Flow Diagram
[Push / Tag] --> [Build Image] --> [Scan with Trivy] --> [Push to Registry]
|
Block if CRITICAL
|
[Update Manifests] --> [GitOps Sync]
|
ArgoCD / Flux deploys