5. Container Registry#
flowchart LR
Dev[Developer] -->|docker push| CI[CI Pipeline]
CI -->|build & scan| Registry[(Container Registry)]
Registry -->|docker pull| K8s[Kubernetes Cluster]
CI -->|sign| Cosign[Cosign / Notary]
CI -->|scan| Trivy[Trivy / Snyk]
Cosign --> Registry
Registry Options#
Registry |
Type |
Features |
|---|---|---|
Docker Hub |
Public SaaS |
Free public repos, rate limits |
Harbor |
Self-hosted |
Vulnerability scanning, RBAC, replication |
AWS ECR |
Cloud |
IAM integration, lifecycle policies |
GCR / Artifact Registry |
Cloud |
GCP integration, multi-region |
GitHub Container Registry |
SaaS |
GitHub Actions integration |
Azure ACR |
Cloud |
Azure AD, geo-replication |
Image Tagging Strategies#
# Semantic versioning (recommended for releases)
docker tag myapp:latest registry.example.com/myapp:1.2.3
docker tag myapp:latest registry.example.com/myapp:1.2
docker tag myapp:latest registry.example.com/myapp:1
# Git SHA (recommended for CI/CD)
docker tag myapp:latest registry.example.com/myapp:$(git rev-parse --short HEAD)
# Branch + timestamp
docker tag myapp:latest registry.example.com/myapp:main-20260317
# Never use :latest in production
Docker Hub#
# Login
docker login
# Push
docker tag myapp:1.0 myuser/myapp:1.0
docker push myuser/myapp:1.0
# Pull
docker pull myuser/myapp:1.0
Self-hosted Registry (Docker)#
# Quick start
docker run -d -p 5000:5000 --name registry \
-v registry_data:/var/lib/registry \
registry:2
# Push to local registry
docker tag myapp:1.0 localhost:5000/myapp:1.0
docker push localhost:5000/myapp:1.0
# List repositories
curl http://localhost:5000/v2/_catalog
Harbor Setup#
# docker-compose.yml for Harbor (simplified)
# Download full installer from https://goharbor.io
services:
harbor-core:
image: goharbor/harbor-core:v2.10
environment:
- CONFIG_PATH=/etc/core/app.conf
volumes:
- ./config/core:/etc/core
depends_on:
- harbor-db
- redis
harbor-db:
image: goharbor/harbor-db:v2.10
volumes:
- harbor_db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: root123
redis:
image: goharbor/redis-photon:v2.10
volumes:
- harbor_redis:/var/lib/redis
registry:
image: goharbor/registry-photon:v2.10
volumes:
- harbor_registry:/storage
nginx:
image: goharbor/nginx-photon:v2.10
ports:
- "80:8080"
- "443:8443"
volumes:
harbor_db:
harbor_redis:
harbor_registry:
# Harbor installation (recommended way)
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-online-installer-v2.10.0.tgz
tar xzf harbor-online-installer-v2.10.0.tgz
cd harbor
# Edit harbor.yml
# Set hostname, https certificate, admin password
cp harbor.yml.tmpl harbor.yml
vim harbor.yml
# Install
./install.sh --with-trivy
Image Scanning#
Trivy#
# Scan an image
trivy image myapp:1.0
# Scan with severity filter
trivy image --severity HIGH,CRITICAL myapp:1.0
# Output as JSON
trivy image -f json -o results.json myapp:1.0
# Scan in CI (fail on critical)
trivy image --exit-code 1 --severity CRITICAL myapp:1.0
Snyk#
snyk container test myapp:1.0
snyk container monitor myapp:1.0
Image Signing (Cosign)#
# Install cosign
brew install cosign
# Generate key pair
cosign generate-key-pair
# Sign an image
cosign sign --key cosign.key registry.example.com/myapp:1.0
# Verify signature
cosign verify --key cosign.pub registry.example.com/myapp:1.0
# Keyless signing (with OIDC)
cosign sign registry.example.com/myapp:1.0
cosign verify --certificate-identity=user@example.com \
--certificate-oidc-issuer=https://accounts.google.com \
registry.example.com/myapp:1.0
AWS ECR#
# Login
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
# Push
docker tag myapp:1.0 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:1.0
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:1.0
# Lifecycle policy (keep last 10 images)
aws ecr put-lifecycle-policy --repository-name myapp \
--lifecycle-policy-text '{"rules":[{"rulePriority":1,"selection":{"tagStatus":"any","countType":"imageCountMoreThan","countNumber":10},"action":{"type":"expire"}}]}'
GitHub Container Registry#
# Login
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# Push
docker tag myapp:1.0 ghcr.io/myuser/myapp:1.0
docker push ghcr.io/myuser/myapp:1.0