Docker Image Registry
This chapter will详细介绍 Docker 镜像仓库的使用和管理,包括公共仓库、私有仓库的搭建、镜像分发策略以及仓库安全配置。
Registry Overview
What is a Docker Registry?
Docker 镜像仓库是存储和分发 Docker 镜像的服务。它类似于代码仓库,但专门用于管理容器镜像的版本和分发。
Registry Architecture
Registry (仓库服务)
├── Repository (镜像仓库)
│ ├── Tag 1 (标签/版本)
│ ├── Tag 2
│ └── Tag 3
└── Repository
├── Tag 1
└── Tag 2Registry Types
| Type | Description | Use Cases | Example |
|---|---|---|---|
| Public | Open access image registry | Open source projects, base images | Docker Hub |
| Private | Restricted access image registry | Enterprise internal applications | Harbor, Nexus |
| Cloud | Cloud provider registry | Cloud-native applications | ECR, ACR, GCR |
| Local | Locally deployed registry service | Development and testing | Registry |
Docker Hub
Docker Hub Basic Usage
bash
# Register and login
docker login
# Search images
docker search nginx
docker search --limit 10 --filter stars=100 nginx
# Pull images
docker pull nginx:latest
docker pull nginx:1.21.6-alpine
# Push images
docker tag myapp:latest username/myapp:latest
docker push username/myapp:latest
# Logout
docker logoutImage Naming Conventions
bash
# Docker Hub image naming format
[registry_host[:port]/]username/repository[:tag]
# Official images (omit username)
nginx:latest
ubuntu:20.04
postgres:13
# User images
myuser/myapp:v1.0
company/backend:latest
# Private registry images
registry.company.com:5000/team/app:v1.0Automated Builds
yaml
# .github/workflows/docker-hub.yml
name: Build and Push to Docker Hub
on:
push:
branches: [ main ]
tags: [ 'v*' ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v3
with:
images: username/myapp
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}Private Registry Setup
Using Official Registry
bash
# Run a simple private registry
docker run -d \
-p 5000:5000 \
--name registry \
registry:2
# Push image to private registry
docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest
# Pull from private registry
docker pull localhost:5000/myapp:latestPersistent Storage Configuration
bash
# Use data volume for persistence
docker run -d \
-p 5000:5000 \
--name registry \
-v registry-data:/var/lib/registry \
registry:2
# Use host directory
docker run -d \
-p 5000:5000 \
--name registry \
-v /opt/registry:/var/lib/registry \
registry:2Registry Configuration File
yaml
# config.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3bash
# Use custom configuration
docker run -d \
-p 5000:5000 \
--name registry \
-v $(pwd)/config.yml:/etc/docker/registry/config.yml \
-v registry-data:/var/lib/registry \
registry:2Harbor Enterprise Registry
Harbor Deployment
yaml
# docker-compose.yml
version: '3.8'
services:
registry:
image: goharbor/registry-photon:v2.5.0
container_name: registry
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registry"
registryctl:
image: goharbor/harbor-registryctl:v2.5.0
container_name: registryctl
env_file:
- ./common/config/registryctl/env
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
- ./common/config/registryctl/config.yml:/etc/registryctl/config.yml:z
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registryctl"
postgresql:
image: goharbor/harbor-db:v2.5.0
container_name: harbor-db
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- SETGID
- SETUID
volumes:
- /data/database:/var/lib/postgresql/data:z
networks:
- harbor
env_file:
- ./common/config/db/env
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "postgresql"
core:
image: goharbor/harbor-core:v2.5.0
container_name: harbor-core
env_file:
- ./common/config/core/env
restart: always
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
volumes:
- /data/ca_download/:/etc/core/ca/:z
- /data/:/data/:z
- ./common/config/core/certificates/:/etc/core/certificates/:z
- ./common/config/core/app.conf:/etc/core/app.conf:z
- ./common/config/core/private_key.pem:/etc/core/private_key.pem:z
- ./common/config/core/key:/etc/core/key:z
networks:
- harbor
depends_on:
- log
- registry
- redis
- postgresql
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "core"
networks:
harbor:
external: falseHarbor Configuration
yaml
# harbor.yml
hostname: harbor.company.com
http:
port: 80
https:
port: 443
certificate: /your/certificate/path
private_key: /your/private/key/path
harbor_admin_password: Harbor12345
database:
password: root123
max_idle_conns: 100
max_open_conns: 900
data_volume: /data
trivy:
ignore_unfixed: false
skip_update: false
offline_scan: false
security_check: vuln
insecure: false
jobservice:
max_job_workers: 10
notification:
webhook_job_max_retry: 10
chart:
absolute_url: disabled
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
_version: 2.5.0
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivyCloud Registry Services
Amazon ECR
bash
# Install AWS CLI
pip install awscli
# Configure AWS credentials
aws configure
# Get login token
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-west-2.amazonaws.com
# Create repository
aws ecr create-repository --repository-name myapp
# Push image
docker tag myapp:latest 123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp:latest
docker push 123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp:latestAzure Container Registry
bash
# Install Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Login to Azure
az login
# Create resource group
az group create --name myResourceGroup --location eastus
# Create ACR
az acr create --resource-group myResourceGroup --name myregistry --sku Basic
# Login to ACR
az acr login --name myregistry
# Push image
docker tag myapp:latest myregistry.azurecr.io/myapp:latest
docker push myregistry.azurecr.io/myapp:latestGoogle Container Registry
bash
# Install Google Cloud SDK
curl https://sdk.cloud.google.com | bash
# Initialize gcloud
gcloud init
# Configure Docker authentication
gcloud auth configure-docker
# Push image
docker tag myapp:latest gcr.io/project-id/myapp:latest
docker push gcr.io/project-id/myapp:latestRegistry Security Configuration
HTTPS Configuration
bash
# Generate self-signed certificate
mkdir -p certs
openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt \
-subj "/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost"
# Run registry with HTTPS
docker run -d \
--name registry \
-p 5000:5000 \
-v $(pwd)/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2Basic Authentication
bash
# Create password file
mkdir auth
docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > auth/htpasswd
# Run registry with authentication
docker run -d \
--name registry \
-p 5000:5000 \
-v $(pwd)/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry:2
# Login to private registry
docker login localhost:5000Token Authentication
yaml
# config.yml
version: 0.1
log:
level: debug
storage:
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
auth:
token:
realm: https://auth.company.com/token
service: registry.company.com
issuer: auth.company.com
rootcertbundle: /etc/docker/registry/auth.crtImage Distribution Strategy
Image Tagging Strategy
bash
# Semantic version tags
docker tag myapp:latest myapp:1.0.0
docker tag myapp:latest myapp:1.0
docker tag myapp:latest myapp:1
# Environment tags
docker tag myapp:latest myapp:dev
docker tag myapp:latest myapp:staging
docker tag myapp:latest myapp:prod
# Git commit tags
docker tag myapp:latest myapp:$(git rev-parse --short HEAD)
docker tag myapp:latest myapp:$(git describe --tags)
# Timestamp tags
docker tag myapp:latest myapp:$(date +%Y%m%d-%H%M%S)Multi-Architecture Images
bash
# Create multi-architecture builder
docker buildx create --name multiarch --use
# Build multi-architecture image
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
--tag myregistry/myapp:latest \
--push .
# View image manifest
docker buildx imagetools inspect myregistry/myapp:latestImage Synchronization
bash
#!/bin/bash
# sync-images.sh
SOURCE_REGISTRY="source.registry.com"
TARGET_REGISTRY="target.registry.com"
IMAGES=(
"myapp:latest"
"myapp:v1.0.0"
"database:latest"
)
for image in "${IMAGES[@]}"; do
echo "Syncing image: $image"
# Pull source image
docker pull $SOURCE_REGISTRY/$image
# Retag
docker tag $SOURCE_REGISTRY/$image $TARGET_REGISTRY/$image
# Push to target registry
docker push $TARGET_REGISTRY/$image
# Clean up local images
docker rmi $SOURCE_REGISTRY/$image $TARGET_REGISTRY/$image
doneRegistry Management
Image Cleanup
bash
# Registry garbage collection
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
# Delete untagged images
docker exec registry bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml
# Automatic cleanup script
#!/bin/bash
# cleanup-registry.sh
REGISTRY_CONTAINER="registry"
DAYS_TO_KEEP=30
# Stop registry service
docker stop $REGISTRY_CONTAINER
# Execute garbage collection
docker run --rm \
-v registry-data:/var/lib/registry \
registry:2 \
bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml
# Restart registry service
docker start $REGISTRY_CONTAINER
echo "Cleanup completed"Registry Backup
bash
#!/bin/bash
# backup-registry.sh
BACKUP_DIR="/backup/registry"
DATE=$(date +%Y%m%d-%H%M%S)
REGISTRY_DATA="/var/lib/docker/volumes/registry-data/_data"
# Create backup directory
mkdir -p $BACKUP_DIR
# Stop registry service
docker stop registry
# Backup data
tar czf $BACKUP_DIR/registry-backup-$DATE.tar.gz -C $REGISTRY_DATA .
# Restart registry service
docker start registry
# Keep backups from last 7 days
find $BACKUP_DIR -name "registry-backup-*.tar.gz" -mtime +7 -delete
echo "Backup completed: registry-backup-$DATE.tar.gz"Registry Monitoring
yaml
# docker-compose.monitoring.yml
version: '3.8'
services:
registry:
image: registry:2
ports:
- "5000:5000"
volumes:
- registry-data:/var/lib/registry
environment:
- REGISTRY_HTTP_DEBUG_ADDR=0.0.0.0:5001
- REGISTRY_HTTP_DEBUG_PROMETHEUS_ENABLED=true
networks:
- registry-network
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- registry-network
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
networks:
- registry-network
volumes:
registry-data:
grafana-data:
networks:
registry-network:
driver: bridgeAPI Operations
Registry API v2
bash
# List repositories
curl -X GET http://localhost:5000/v2/_catalog
# List tags
curl -X GET http://localhost:5000/v2/myapp/tags/list
# Get image manifest
curl -X GET \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
http://localhost:5000/v2/myapp/manifests/latest
# Delete image
curl -X DELETE http://localhost:5000/v2/myapp/manifests/sha256:digestAutomation Scripts
bash
#!/bin/bash
# registry-api.sh
REGISTRY_URL="http://localhost:5000"
list_repositories() {
curl -s "$REGISTRY_URL/v2/_catalog" | jq -r '.repositories[]'
}
list_tags() {
local repo=$1
curl -s "$REGISTRY_URL/v2/$repo/tags/list" | jq -r '.tags[]'
}
get_manifest() {
local repo=$1
local tag=$2
curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"$REGISTRY_URL/v2/$repo/manifests/$tag"
}
delete_image() {
local repo=$1
local digest=$2
curl -X DELETE "$REGISTRY_URL/v2/$repo/manifests/$digest"
}
# Usage examples
case "$1" in
"list-repos")
list_repositories
;;
"list-tags")
list_tags "$2"
;;
"get-manifest")
get_manifest "$2" "$3"
;;
"delete")
delete_image "$2" "$3"
;;
*)
echo "Usage: $0 {list-repos|list-tags|get-manifest|delete} [args...]"
exit 1
;;
esacBest Practices
Registry Design Principles
- Naming Conventions: Use consistent naming conventions
- Version Management: Implement semantic version control
- Security Configuration: Enable HTTPS and authentication
- Access Control: Implement fine-grained permission management
- Monitoring and Alerting: Monitor registry health status
Image Management Strategy
bash
# Image lifecycle management
#!/bin/bash
# image-lifecycle.sh
# Development stage
docker build -t myapp:dev-$(git rev-parse --short HEAD) .
docker push myregistry/myapp:dev-$(git rev-parse --short HEAD)
# Testing stage
docker tag myapp:dev-$(git rev-parse --short HEAD) myapp:test-$(date +%Y%m%d)
docker push myregistry/myapp:test-$(date +%Y%m%d)
# Production release
docker tag myapp:test-$(date +%Y%m%d) myapp:v1.0.0
docker tag myapp:v1.0.0 myapp:latest
docker push myregistry/myapp:v1.0.0
docker push myregistry/myapp:latestSecurity Checklist
- [ ] Enable HTTPS encryption
- [ ] Configure user authentication
- [ ] Implement access control
- [ ] Regularly scan for vulnerabilities
- [ ] Monitor access logs
- [ ] Backup important data
- [ ] Update registry software
Chapter Summary
This chapter comprehensively introduced all aspects of Docker image registries:
Key Points:
- Registry Types: Characteristics and usage of public, private, and cloud registries
- Private Registries: Solutions like Registry, Harbor
- Security Configuration: HTTPS, authentication, access control
- Image Management: Tagging strategies, multi-architecture, synchronization
- Operations Management: Monitoring, backup, cleanup
Best Practices:
- Choose appropriate registry solutions
- Implement security configuration and access control
- Establish image lifecycle management
- Monitor registry health status
- Regular backup and cleanup
Application Scenarios:
- Enterprise internal image management
- CI/CD pipeline integration
- Multi-environment image distribution
- Large-scale container deployment
Mastering registry management skills is crucial for containerized application development and deployment.