Skip to content

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 2

Registry Types

TypeDescriptionUse CasesExample
PublicOpen access image registryOpen source projects, base imagesDocker Hub
PrivateRestricted access image registryEnterprise internal applicationsHarbor, Nexus
CloudCloud provider registryCloud-native applicationsECR, ACR, GCR
LocalLocally deployed registry serviceDevelopment and testingRegistry

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 logout

Image 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.0

Automated 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:latest

Persistent 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:2

Registry 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: 3
bash
# 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:2

Harbor 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: false

Harbor 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
    - trivy

Cloud 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:latest

Azure 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:latest

Google 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:latest

Registry 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:2

Basic 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:5000

Token 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.crt

Image 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:latest

Image 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
done

Registry 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: bridge

API 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:digest

Automation 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
        ;;
esac

Best Practices

Registry Design Principles

  1. Naming Conventions: Use consistent naming conventions
  2. Version Management: Implement semantic version control
  3. Security Configuration: Enable HTTPS and authentication
  4. Access Control: Implement fine-grained permission management
  5. 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:latest

Security 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.

Further Reading

Content is for learning and research only.