Skip to content
container-registry-management logo

Container Registry Management

container-registry-management

Manage container registries (Docker Hub, ECR, GCR) with image scanning, retention policies, and access control.

SKILL.md

Full skill instructions

Container Registry Management

Overview

Implement comprehensive container registry management including image scanning, vulnerability detection, retention policies, access control, and multi-region replication.

When to Use

  • Container image storage and distribution
  • Security scanning and compliance
  • Image retention and cleanup
  • Registry access control
  • Multi-region deployments
  • Image signing and verification
  • Cost optimization

Implementation Examples

1. AWS ECR Setup and Management

# ecr-setup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ecr-management
  namespace: operations
data:
  setup-ecr.sh: |
    #!/​bin/​bash
    set -euo pipefail

    REGISTRY_NAME="myapp"
    REGION="us-east-1"
    ACCOUNT_ID="123456789012"

    echo "Setting up ECR repository..."

    # Create ECR repository
    aws ecr create-repository \
      --repository-name "$REGISTRY_NAME" \
      --region "$REGION" \
      --encryption-configuration encryptionType=KMS,kmsKey=arn:aws:kms:$REGION:$ACCOUNT_ID:key/​12345678-1234-1234-1234-123456789012 \
      --image-tag-mutability IMMUTABLE \
      --image-scanning-configuration scanOnPush=true || true

    echo "Repository: $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/​$REGISTRY_NAME"

    # Set lifecycle policy
    aws ecr put-lifecycle-policy \
      --repository-name "$REGISTRY_NAME" \
      --region "$REGION" \
      --lifecycle-policy-text '{
        "rules": [
          {
            "rulePriority": 1,
            "description": "Keep last 20 images tagged with release",
            "selection": {
              "tagStatus": "tagged",
              "tagPrefixList": ["release"],
              "countType": "imageCountMoreThan",
              "countNumber": 20
            },
            "action": {
              "type": "expire"
            }
          },
          {
            "rulePriority": 2,
            "description": "Remove untagged images older than 7 days",
            "selection": {
              "tagStatus": "untagged",
              "countType": "sinceImagePushed",
              "countUnit": "days",
              "countNumber": 7
            },
            "action": {
              "type": "expire"
            }
          },
          {
            "rulePriority": 3,
            "description": "Keep all development images for 30 days",
            "selection": {
              "tagStatus": "tagged",
              "tagPrefixList": ["dev"],
              "countType": "sinceImagePushed",
              "countUnit": "days",
              "countNumber": 30
            },
            "action": {
              "type": "expire"
            }
          }
        ]
      }'

    # Enable cross-region replication
    aws ecr create-registry \
      --region "$REGION" \
      --replication-configuration '{
        "rules": [
          {
            "destinations": [
              {
                "region": "eu-west-1",
                "registryId": "'$ACCOUNT_ID'"
              },
              {
                "region": "ap-northeast-1",
                "registryId": "'$ACCOUNT_ID'"
              }
            ],
            "repositoryFilters": [
              {
                "filter": "'$REGISTRY_NAME'",
                "filterType": "PREFIX_MATCH"
              }
            ]
          }
        ]
      }' || true

    echo "ECR setup complete"

  scan-images.sh: |
    #!/​bin/​bash
    set -euo pipefail

    REGISTRY_NAME="myapp"
    REGION="us-east-1"

    echo "Scanning all images in $REGISTRY_NAME"

    # Get all image IDs
    IMAGE_IDS=$(aws ecr list-images \
      --repository-name "$REGISTRY_NAME" \
      --region "$REGION" \
      --query 'imageIds[*]' \
      --output json)

    # Scan each image
    echo "$IMAGE_IDS" | jq -r '.[] | @base64' | while read image; do
      IMAGE=$(echo "$image" | base64 -d | jq -r '.imageTag')
      DIGEST=$(echo "$image" | base64 -d | jq -r '.imageDigest')

      echo "Scanning image: $IMAGE ($DIGEST)"

      # Start scan
      aws ecr start-image-scan \
        --repository-name "$REGISTRY_NAME" \
        --image-id imageTag="$IMAGE" \
        --region "$REGION" || true

      # Get scan results
      sleep 5
      RESULTS=$(aws ecr describe-image-scan-findings \
        --repository-name "$REGISTRY_NAME" \
        --image-id imageTag="$IMAGE" \
        --region "$REGION")

      CRITICAL=$(echo "$RESULTS" | jq '.imageScanFindings.findingSeverityCounts.CRITICAL // 0')
      HIGH=$(echo "$RESULTS" | jq '.imageScanFindings.findingSeverityCounts.HIGH // 0')

      if [ "$CRITICAL" -gt 0 ]; then
        echo "WARNING: Image has $CRITICAL critical vulnerabilities"
      fi

      if [ "$HIGH" -gt 0 ]; then
        echo "WARNING: Image has $HIGH high vulnerabilities"
      fi
    done

    echo "Image scanning complete"

---
# Terraform ECR configuration
resource "aws_ecr_repository" "myapp" {
  name                 = "myapp"
  image_tag_mutability = "IMMUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }

  encryption_configuration {
    encryption_type = "KMS"
    kms_key         = aws_kms_key.ecr.arn
  }

  tags = {
    Name = "myapp-registry"
  }
}

resource "aws_ecr_lifecycle_policy" "myapp" {
  repository = aws_ecr_repository.myapp.name

  policy = jsonencode({
    rules = [
      {
        rulePriority = 1
        description  = "Keep last 20 production images"
        selection = {
          tagStatus       = "tagged"
          tagPrefixList   = ["release"]
          countType       = "imageCountMoreThan"
          countNumber     = 20
        }
        action = {
          type = "expire"
        }
      },
      {
        rulePriority = 2
        description  = "Remove untagged images after 7 days"
        selection = {
          tagStatus     = "untagged"
          countType     = "sinceImagePushed"
          countUnit     = "days"
          countNumber   = 7
        }
        action = {
          type = "expire"
        }
      }
    ]
  })
}

resource "aws_ecr_repository_policy" "myapp" {
  repository = aws_ecr_repository.myapp.name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/​EcsTaskExecutionRole"
        }
        Action = [
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "ecr:GetImage"
        ]
      }
    ]
  })
}

2. Container Image Build and Push

#!/​bin/​bash
# build-and-push.sh - Build and push container images

set -euo pipefail

REGISTRY="${1:-123456789012.dkr.ecr.us-east-1.amazonaws.com}"
IMAGE_NAME="${2:-myapp}"
VERSION="${3:-latest}"
DOCKERFILE="${4:-Dockerfile}"

echo "Building and pushing container image..."

# Set full image path
FULL_IMAGE="$REGISTRY/​$IMAGE_NAME:$VERSION"

# Login to ECR
echo "Authenticating to ECR..."
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin "$REGISTRY"

# Build image
echo "Building image: $FULL_IMAGE"
docker build \
  -f "$DOCKERFILE" \
  -t "$FULL_IMAGE" \
  -t "$REGISTRY/​$IMAGE_NAME:latest" \
  --build-arg BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
  --build-arg VCS_REF="$(git rev-parse --short HEAD)" \
  --build-arg VERSION="$VERSION" \
  .

# Scan with trivy before push
echo "Scanning image with Trivy..."
trivy image --severity HIGH,CRITICAL "$FULL_IMAGE"

# Push image
echo "Pushing image to ECR..."
docker push "$FULL_IMAGE"
docker push "$REGISTRY/​$IMAGE_NAME:latest"

# Get image digest
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$FULL_IMAGE" | cut -d@ -f2)

echo "Image pushed successfully"
echo "Image: $FULL_IMAGE"
echo "Digest: $DIGEST"

3. Image Signing with Notary

#!/​bin/​bash
# sign-image.sh - Sign container images with Notary

set -euo pipefail

IMAGE="${1}"
NOTATION_KEY="${2:-mykey}"

echo "Signing image: $IMAGE"

# Initialize Notary
notary key list

# Sign image
notation sign \
  --key "$NOTATION_KEY" \
  --allow-missing \
  "$IMAGE"

echo "Image signed successfully"

# Verify signature
notation verify "$IMAGE"

4. Registry Access Control

# registry-access-control.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ecr-pull-secret
  namespace: production
type: kubernetes.io/​dockercfg
stringData:
  .dockercfg: |
    {
      "123456789012.dkr.ecr.us-east-1.amazonaws.com": {
        "auth": "base64-encoded-credentials",
        "email": "[email protected]"
      }
    }

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ecr-pull-sa
  namespace: production
imagePullSecrets:
  - name: ecr-pull-secret

---
apiVersion: v1
kind: Pod
metadata:
  name: myapp
  namespace: production
spec:
  serviceAccountName: ecr-pull-sa
  containers:
    - name: app
      image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/​myapp:latest
      imagePullPolicy: Always

---
# IAM policy for ECR access
apiVersion: iam.aws.amazon.com/​v1
kind: IAMPolicy
metadata:
  name: ecr-read-only
spec:
  policyDocument:
    Version: '2012-10-17'
    Statement:
      - Effect: Allow
        Action:
          - ecr:GetDownloadUrlForLayer
          - ecr:BatchGetImage
          - ecr:GetImage
          - ecr:DescribeImages
        Resource: arn:aws:ecr:*:123456789012:repository/​myapp
      - Effect: Allow
        Action:
          - ecr:GetAuthorizationToken
        Resource: '*'

5. Registry Monitoring

# registry-monitoring.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: registry-monitoring
  namespace: monitoring
data:
  dashboards.json: |
    {
      "dashboard": {
        "title": "Container Registry",
        "panels": [
          {
            "title": "Images by Repository",
            "targets": [
              {
                "expr": "count by (repository) (aws_ecr_repository_images)"
              }
            ]
          },
          {
            "title": "Images with Vulnerabilities",
            "targets": [
              {
                "expr": "sum(aws_ecr_image_scan_findings{severity=~\"HIGH|CRITICAL\"})"
              }
            ]
          },
          {
            "title": "Registry Storage",
            "targets": [
              {
                "expr": "aws_ecr_repository_size_bytes"
              }
            ]
          }
        ]
      }
    }

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: registry-alerts
  namespace: monitoring
data:
  alerts.yaml: |
    groups:
      - name: registry_alerts
        rules:
          - alert: ImageWithCriticalVulnerabilities
            expr: aws_ecr_image_scan_findings{severity="CRITICAL"} > 0
            for: 5m
            labels:
              severity: critical
            annotations:
              summary: "Image has critical vulnerabilities"

          - alert: ImagePushFailure
            expr: aws_ecr_push_failures_total > 0
            for: 1m
            labels:
              severity: warning
            annotations:
              summary: "Image push failed"

          - alert: RegistryStorageHigh
            expr: aws_ecr_repository_size_bytes / 1024 / 1024 / 1024 > 100
            labels:
              severity: warning
            annotations:
              summary: "Registry storage usage is high"

Best Practices

✅ DO

  • Scan images before deployment
  • Use image tag immutability
  • Implement retention policies
  • Control registry access with IAM
  • Sign images for verification
  • Replicate across regions
  • Monitor registry storage
  • Use private registries

❌ DON'T

  • Push to public registries
  • Use latest tag in production
  • Allow anonymous pulls
  • Store secrets in images
  • Keep old images indefinitely
  • Push without scanning
  • Use default credentials
  • Share registry credentials

Registry Options

  • Docker Hub: Public registry
  • AWS ECR: AWS-managed
  • Google GCR: Google Cloud
  • Azure ACR: Azure-managed
  • Artifactory: Self-hosted
  • Harbor: Open-source

Image Naming Convention

[registry]/[organization]/[repository]:[tag]
123456789012.dkr.ecr.us-east-1.amazonaws.com/​myapp:v1.2.3

Resources

More DevOps & CI/CD skills

Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.

6K 472.6K
View

Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.

6K 472.6K
View

Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.

1.5K 454.3K
View
azure-kubernetes logo
DevOps & CI/CD

azure-kubernetes

Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.

1.5K 447.1K
View

Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.

92.7K 354.9K
View
just-scrape logo
DevOps & CI/CD

just-scrape

Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.

69 245K
View

Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.

462 159.7K
View

Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.

462 159.1K
View
deploy-to-vercel logo
DevOps & CI/CD

deploy-to-vercel

Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".

31.9K 146.6K
View
programmatic-seo logo
DevOps & CI/CD

programmatic-seo

Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.

53.3K 140.1K
View

Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.

63 123.5K
View

Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".

31.9K 116.1K
View

Coding & apps AI tools

Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View
I
Coding & apps

Imagica

Build a no-code AI app in minutes.

Freemium
View
E
Coding & apps

Emergent.sh

An IDE for code migration from legacy to modern frameworks through coding agents.

Freemium
View
Wonder Dynamics logo
Coding & apps

Wonder Dynamics

Automate CGI animation in live-action scenes

Paid
View
M
Coding & apps

Mixo

Launch a website in seconds with AI.

Paid
View
AI Code Convert logo
Coding & apps

AI Code Convert

Streamline Your Coding Experience with AI Code Helper

Free
View