Skip to main content
Technology & EngineeringContainerization188 lines

Container Registries

Container registry setup, authentication, and image management for ECR, GCR, GHCR, and Docker Hub

Quick Summary30 lines
You are an expert in container registries for containerized application development and deployment.

## Key Points

- **Git SHA**: `myapp:sha-abc1234` — immutable, traceable to exact commit
- **Semantic version**: `myapp:v2.1.0` — human-readable releases
- **Branch**: `myapp:main` — mutable, useful for dev environments
- Enable image scanning on push (ECR, Artifact Registry) to catch vulnerabilities before deployment.
- Use lifecycle or cleanup policies to automatically remove old untagged images and control storage costs.
- Prefer immutable tags (git SHA or digest) over mutable tags (`latest`) for production deployments.
- Forgetting to refresh short-lived ECR authentication tokens (they expire after 12 hours), which causes CI builds to fail with authorization errors.
- Pushing images without a cleanup policy, leading to unbounded storage growth and unexpected registry costs over time.

## Quick Example

```
docker.io/library/nginx:1.25-alpine
123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v2.1.0
ghcr.io/myorg/myapp:sha-abc1234
us-docker.pkg.dev/my-project/repo/myapp:latest
```

```bash
# ECR pull-through cache
aws ecr create-pull-through-cache-rule \
  --ecr-repository-prefix docker-hub \
  --upstream-registry-url registry-1.docker.io
```
skilldb get containerization-skills/Container RegistriesFull skill: 188 lines
Paste into your CLAUDE.md or agent config

Container Registries — Containerization

You are an expert in container registries for containerized application development and deployment.

Overview

Container registries store and distribute OCI/Docker images. Choosing the right registry depends on your cloud provider, access control needs, and CI/CD integration. The major options are Amazon ECR, Google Artifact Registry, GitHub Container Registry (GHCR), and Docker Hub, each with different authentication, pricing, and feature sets.

Core Concepts

Image Naming and Tagging

Registry URLs follow the pattern <registry>/<repository>:<tag>:

docker.io/library/nginx:1.25-alpine
123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v2.1.0
ghcr.io/myorg/myapp:sha-abc1234
us-docker.pkg.dev/my-project/repo/myapp:latest

Tag strategies:

  • Git SHA: myapp:sha-abc1234 — immutable, traceable to exact commit
  • Semantic version: myapp:v2.1.0 — human-readable releases
  • Branch: myapp:main — mutable, useful for dev environments

Amazon ECR

# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com

# Create repository
aws ecr create-repository --repository-name myapp --image-scanning-configuration scanOnPush=true

# Push
docker tag myapp:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0.0
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.0.0

ECR lifecycle policies clean up old images automatically:

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "Keep last 10 tagged images",
      "selection": {
        "tagStatus": "tagged",
        "tagPrefixList": ["v"],
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": { "type": "expire" }
    },
    {
      "rulePriority": 2,
      "description": "Expire untagged after 7 days",
      "selection": {
        "tagStatus": "untagged",
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 7
      },
      "action": { "type": "expire" }
    }
  ]
}

Google Artifact Registry

# Authenticate
gcloud auth configure-docker us-docker.pkg.dev

# Create repository
gcloud artifacts repositories create myrepo \
  --repository-format=docker \
  --location=us \
  --description="Application images"

# Push
docker tag myapp:latest us-docker.pkg.dev/my-project/myrepo/myapp:v1.0.0
docker push us-docker.pkg.dev/my-project/myrepo/myapp:v1.0.0

GitHub Container Registry (GHCR)

# Authenticate with a personal access token
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# Push
docker tag myapp:latest ghcr.io/myorg/myapp:v1.0.0
docker push ghcr.io/myorg/myapp:v1.0.0

GHCR integrates natively with GitHub Actions:

# .github/workflows/publish.yaml
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}

Implementation Patterns

Multi-Architecture Builds

# Create and use a buildx builder
docker buildx create --name multiarch --use

# Build and push for multiple platforms
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --tag ghcr.io/myorg/myapp:v1.0.0 \
  --push .

Pull-Through Cache

Configure a registry mirror to cache frequently pulled public images and reduce external bandwidth:

# ECR pull-through cache
aws ecr create-pull-through-cache-rule \
  --ecr-repository-prefix docker-hub \
  --upstream-registry-url registry-1.docker.io

Best Practices

  • Enable image scanning on push (ECR, Artifact Registry) to catch vulnerabilities before deployment.
  • Use lifecycle or cleanup policies to automatically remove old untagged images and control storage costs.
  • Prefer immutable tags (git SHA or digest) over mutable tags (latest) for production deployments.

Core Philosophy

A container registry is not just a storage bucket for images; it is the critical link between your build pipeline and your production runtime. Every image that runs in production passes through the registry, making it a natural enforcement point for security scanning, access control, and lifecycle management. Treating the registry as infrastructure rather than a convenience service is essential for production-grade container workflows.

Immutability and traceability are the two properties that matter most for production images. A tag like v2.1.0 or sha-abc1234 should always resolve to the same image layers. Mutable tags like latest or main undermine auditability because you cannot determine after the fact which exact image was running during an incident. Pin production deployments to immutable references (git SHA tags or digests) and reserve mutable tags for development convenience.

Lifecycle management prevents registries from becoming expensive, unmanageable dumps of historical images. Every push adds layers, and without cleanup policies, storage grows unbounded. Automate expiration of untagged images and old tagged versions so that the registry contains only images that are actively deployed or recently built. Combine lifecycle policies with vulnerability scanning to ensure that the images you keep are both relevant and safe.

Anti-Patterns

  • Using latest as the production deployment tag. The latest tag is mutable and tells you nothing about which version of the code is running. If two builds push to latest in quick succession, the second silently replaces the first with no audit trail. Use immutable tags tied to git SHAs or semantic versions.

  • No image cleanup policy. Pushing images on every CI build without expiration rules leads to thousands of orphaned images consuming storage and inflating costs. Configure lifecycle policies from the start to automatically expire untagged images and keep only a bounded number of tagged versions.

  • Sharing a single registry repository across unrelated services. Putting images for the API, worker, and frontend into the same repository makes access control impossible and tag namespaces confusing. Use one repository per service or component.

  • Long-lived static credentials for CI authentication. Using permanent access keys or tokens for CI pipelines means a leaked credential grants indefinite push/pull access. Use short-lived tokens (ECR's 12-hour tokens, OIDC federation, or workload identity) and rotate any static credentials regularly.

  • Skipping vulnerability scanning at push time. Pushing images to the registry without automated scanning means vulnerable images sit undetected until (or unless) someone manually checks. Enable scan-on-push and gate deployments on scan results.

Common Pitfalls

  • Forgetting to refresh short-lived ECR authentication tokens (they expire after 12 hours), which causes CI builds to fail with authorization errors.
  • Pushing images without a cleanup policy, leading to unbounded storage growth and unexpected registry costs over time.

Install this skill directly: skilldb add containerization-skills

Get CLI access →