container-registry-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Container Registry Setup Expert

容器注册表配置专家

Эксперт по настройке и управлению container registries.
专注于容器注册表的配置与管理专家。

Типы Registry

注册表类型

Cloud-Managed

云托管

RegistryProviderFeatures
ECRAWSIAM integration, scanning
Artifact RegistryGCPMulti-format, regional
ACRAzureAD integration, geo-rep
Docker HubDockerPublic/private, CI/CD
注册表提供商特性
ECRAWSIAM集成、镜像扫描
Artifact RegistryGCP多格式支持、区域化部署
ACRAzureAD集成、地理复制
Docker HubDocker公有/私有仓库、CI/CD集成

Self-Hosted

自托管

RegistryBest ForFeatures
HarborEnterpriseRBAC, scanning, replication
NexusMulti-artifactMaven, npm, Docker
ArtifactoryEnterpriseUniversal, HA
DistributionSimpleOfficial Docker registry
注册表适用场景特性
Harbor企业级RBAC权限控制、镜像扫描、仓库复制
Nexus多制品管理支持Maven、npm、Docker等多种格式
Artifactory企业级全制品支持、高可用部署
Distribution轻量场景Docker官方轻量注册表

AWS ECR Setup

AWS ECR配置

Terraform Configuration

Terraform配置

hcl
resource "aws_ecr_repository" "app" {
  name                 = "my-application"
  image_tag_mutability = "IMMUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }

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

  tags = {
    Environment = "production"
    Team        = "platform"
  }
}

resource "aws_ecr_lifecycle_policy" "cleanup" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
    rules = [
      {
        rulePriority = 1
        description  = "Keep last 10 images"
        selection = {
          tagStatus     = "tagged"
          tagPrefixList = ["v"]
          countType     = "imageCountMoreThan"
          countNumber   = 10
        }
        action = {
          type = "expire"
        }
      },
      {
        rulePriority = 2
        description  = "Remove untagged after 7 days"
        selection = {
          tagStatus   = "untagged"
          countType   = "sinceImagePushed"
          countUnit   = "days"
          countNumber = 7
        }
        action = {
          type = "expire"
        }
      }
    ]
  })
}
hcl
resource "aws_ecr_repository" "app" {
  name                 = "my-application"
  image_tag_mutability = "IMMUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }

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

  tags = {
    Environment = "production"
    Team        = "platform"
  }
}

resource "aws_ecr_lifecycle_policy" "cleanup" {
  repository = aws_ecr_repository.app.name

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

ECR Authentication

ECR身份验证

bash
undefined
bash
undefined

Login to ECR

登录ECR

aws ecr get-login-password --region us-east-1 |
docker login --username AWS --password-stdin
123456789.dkr.ecr.us-east-1.amazonaws.com
aws ecr get-login-password --region us-east-1 |
docker login --username AWS --password-stdin
123456789.dkr.ecr.us-east-1.amazonaws.com

Push image

推送镜像

docker tag myapp:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:latest docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
undefined
docker tag myapp:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:latest docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
undefined

Harbor Self-Hosted

Harbor自托管部署

Docker Compose Setup

Docker Compose配置

yaml
version: '3'
services:
  harbor-core:
    image: goharbor/harbor-core:v2.9.0
    container_name: harbor-core
    env_file:
      - ./common/config/core/env
    volumes:
      - ./common/config/core/certificates:/etc/core/certificates
      - ./common/config/core/key:/etc/core/key
    depends_on:
      - registry
      - redis
      - postgresql
    networks:
      - harbor

  registry:
    image: goharbor/registry-photon:v2.9.0
    container_name: registry
    volumes:
      - registry_data:/storage
      - ./common/config/registry:/etc/registry
    networks:
      - harbor

  postgresql:
    image: goharbor/harbor-db:v2.9.0
    container_name: harbor-db
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    networks:
      - harbor

  redis:
    image: goharbor/redis-photon:v2.9.0
    container_name: harbor-redis
    volumes:
      - redis:/var/lib/redis
    networks:
      - harbor

  nginx:
    image: goharbor/nginx-photon:v2.9.0
    container_name: nginx
    ports:
      - "80:8080"
      - "443:8443"
    volumes:
      - ./common/config/nginx:/etc/nginx
    depends_on:
      - harbor-core
    networks:
      - harbor

volumes:
  registry_data:
  database:
  redis:

networks:
  harbor:
    driver: bridge
yaml
version: '3'
services:
  harbor-core:
    image: goharbor/harbor-core:v2.9.0
    container_name: harbor-core
    env_file:
      - ./common/config/core/env
    volumes:
      - ./common/config/core/certificates:/etc/core/certificates
      - ./common/config/core/key:/etc/core/key
    depends_on:
      - registry
      - redis
      - postgresql
    networks:
      - harbor

  registry:
    image: goharbor/registry-photon:v2.9.0
    container_name: registry
    volumes:
      - registry_data:/storage
      - ./common/config/registry:/etc/registry
    networks:
      - harbor

  postgresql:
    image: goharbor/harbor-db:v2.9.0
    container_name: harbor-db
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    networks:
      - harbor

  redis:
    image: goharbor/redis-photon:v2.9.0
    container_name: harbor-redis
    volumes:
      - redis:/var/lib/redis
    networks:
      - harbor

  nginx:
    image: goharbor/nginx-photon:v2.9.0
    container_name: nginx
    ports:
      - "80:8080"
      - "443:8443"
    volumes:
      - ./common/config/nginx:/etc/nginx
    depends_on:
      - harbor-core
    networks:
      - harbor

volumes:
  registry_data:
  database:
  redis:

networks:
  harbor:
    driver: bridge

Image Security

镜像安全

Vulnerability Scanning

漏洞扫描

bash
undefined
bash
undefined

Trivy scan

Trivy扫描

trivy image myapp:latest
trivy image myapp:latest

Grype scan

Grype扫描

grype myapp:latest
grype myapp:latest

ECR scan results

ECR扫描结果查看

aws ecr describe-image-scan-findings
--repository-name myapp
--image-id imageTag=latest
undefined
aws ecr describe-image-scan-findings
--repository-name myapp
--image-id imageTag=latest
undefined

Image Signing with Cosign

使用Cosign进行镜像签名

bash
undefined
bash
undefined

Generate key pair

生成密钥对

cosign generate-key-pair
cosign generate-key-pair

Sign image

签名镜像

cosign sign --key cosign.key myregistry/myapp:latest
cosign sign --key cosign.key myregistry/myapp:latest

Verify signature

验证签名

cosign verify --key cosign.pub myregistry/myapp:latest
undefined
cosign verify --key cosign.pub myregistry/myapp:latest
undefined

Content Trust (Docker)

Docker内容信任

bash
undefined
bash
undefined

Enable content trust

启用内容信任

export DOCKER_CONTENT_TRUST=1
export DOCKER_CONTENT_TRUST=1

Sign and push

签名并推送镜像

docker push myregistry/myapp:latest
docker push myregistry/myapp:latest

Verify on pull

拉取时验证

docker pull myregistry/myapp:latest
undefined
docker pull myregistry/myapp:latest
undefined

Kubernetes Integration

Kubernetes集成

Image Pull Secret

镜像拉取密钥

yaml
apiVersion: v1
kind: Secret
metadata:
  name: registry-credentials
  namespace: default
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: |
    eyJhdXRocyI6eyJteXJlZ2lzdHJ5LmNvbSI6eyJ1c2VybmFtZSI6InVzZXIi
    LCJwYXNzd29yZCI6InBhc3MiLCJhdXRoIjoiZFhObGNqcHdZWE56In19fQ==
yaml
apiVersion: v1
kind: Secret
metadata:
  name: registry-credentials
  namespace: default
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: |
    eyJhdXRocyI6eyJteXJlZ2lzdHJ5LmNvbSI6eyJ1c2VybmFtZSI6InVzZXIi
    LCJwYXNzd29yZCI6InBhc3MiLCJhdXRoIjoiZFhObGNqcHdZWE56In19fQ==

Deployment with Pull Secret

配置拉取密钥的Deployment

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myregistry.com/myapp:v1.0.0
          imagePullPolicy: Always
      imagePullSecrets:
        - name: registry-credentials
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: myregistry.com/myapp:v1.0.0
          imagePullPolicy: Always
      imagePullSecrets:
        - name: registry-credentials

ServiceAccount Configuration

ServiceAccount配置

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: default
imagePullSecrets:
  - name: registry-credentials
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: default
imagePullSecrets:
  - name: registry-credentials

CI/CD Integration

CI/CD集成

GitHub Actions

GitHub Actions

yaml
name: Build and Push

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to ECR
        uses: aws-actions/amazon-ecr-login@v2

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:${{ github.sha }}
            myuser/myapp:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
yaml
name: Build and Push

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to ECR
        uses: aws-actions/amazon-ecr-login@v2

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:${{ github.sha }}
            myuser/myapp:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

GitLab CI

GitLab CI

yaml
stages:
  - build
  - push

variables:
  IMAGE_NAME: $CI_REGISTRY_IMAGE

build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
    - docker push $IMAGE_NAME:$CI_COMMIT_SHA
  only:
    - main
yaml
stages:
  - build
  - push

variables:
  IMAGE_NAME: $CI_REGISTRY_IMAGE

build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
    - docker push $IMAGE_NAME:$CI_COMMIT_SHA
  only:
    - main

Cleanup Scripts

清理脚本

ECR Cleanup

ECR清理

python
import boto3
from datetime import datetime, timedelta

def cleanup_untagged_images(repository: str, days_old: int = 7):
    """Remove untagged images older than specified days."""
    ecr = boto3.client('ecr')

    response = ecr.describe_images(
        repositoryName=repository,
        filter={'tagStatus': 'UNTAGGED'}
    )

    cutoff = datetime.now() - timedelta(days=days_old)

    images_to_delete = []
    for image in response['imageDetails']:
        if image['imagePushedAt'].replace(tzinfo=None) < cutoff:
            images_to_delete.append({
                'imageDigest': image['imageDigest']
            })

    if images_to_delete:
        ecr.batch_delete_image(
            repositoryName=repository,
            imageIds=images_to_delete
        )
        print(f"Deleted {len(images_to_delete)} images")
python
import boto3
from datetime import datetime, timedelta

def cleanup_untagged_images(repository: str, days_old: int = 7):
    """Remove untagged images older than specified days."""
    ecr = boto3.client('ecr')

    response = ecr.describe_images(
        repositoryName=repository,
        filter={'tagStatus': 'UNTAGGED'}
    )

    cutoff = datetime.now() - timedelta(days=days_old)

    images_to_delete = []
    for image in response['imageDetails']:
        if image['imagePushedAt'].replace(tzinfo=None) < cutoff:
            images_to_delete.append({
                'imageDigest': image['imageDigest']
            })

    if images_to_delete:
        ecr.batch_delete_image(
            repositoryName=repository,
            imageIds=images_to_delete
        )
        print(f"Deleted {len(images_to_delete)} images")

Usage

Usage

cleanup_untagged_images('my-app', days_old=7)
undefined
cleanup_untagged_images('my-app', days_old=7)
undefined

Performance Optimization

性能优化

Registry Caching

注册表缓存

yaml
undefined
yaml
undefined

Docker daemon.json

Docker daemon.json

{ "registry-mirrors": ["https://mirror.gcr.io"], "insecure-registries": [], "max-concurrent-downloads": 10, "max-concurrent-uploads": 5 }
undefined
{ "registry-mirrors": ["https://mirror.gcr.io"], "insecure-registries": [], "max-concurrent-downloads": 10, "max-concurrent-uploads": 5 }
undefined

Pull-Through Cache (Harbor)

Harbor拉取缓存

yaml
undefined
yaml
undefined

Harbor project config

Harbor项目配置

replication:
undefined
replication:
undefined

Troubleshooting

故障排查

bash
undefined
bash
undefined

Test connectivity

测试连通性

Check authentication

检查身份验证

docker login myregistry.com
docker login myregistry.com

Verify TLS

验证TLS证书

openssl s_client -connect myregistry.com:443 -servername myregistry.com
openssl s_client -connect myregistry.com:443 -servername myregistry.com

Clear credentials

清除凭证

docker logout myregistry.com rm ~/.docker/config.json
docker logout myregistry.com rm ~/.docker/config.json

Debug pull issues

调试镜像拉取问题

docker pull myregistry.com/myapp:latest --debug
undefined
docker pull myregistry.com/myapp:latest --debug
undefined

Лучшие практики

最佳实践

  1. Image immutability — используйте immutable tags
  2. Vulnerability scanning — scan on push обязателен
  3. Lifecycle policies — автоматическая очистка старых images
  4. Content trust — подписывайте production images
  5. Geo-replication — для global deployments
  6. Access control — минимальные права через RBAC
  7. Monitoring — алерты на failed pushes и pulls
  1. 镜像不可变性 — 使用不可变标签
  2. 漏洞扫描 — 强制开启推送时扫描
  3. 生命周期策略 — 自动清理旧镜像
  4. 内容信任 — 对生产环境镜像进行签名
  5. 地理复制 — 适用于全球部署场景
  6. 访问控制 — 通过RBAC配置最小权限
  7. 监控告警 — 针对推送/拉取失败设置告警