5. 容器镜像仓库#

        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
    

镜像仓库选型#

镜像仓库

类型

特点

Docker Hub

公有 SaaS

免费公开仓库,有拉取频率限制

Harbor

自建部署

漏洞扫描、RBAC 权限控制、镜像复制

AWS ECR

云服务

与 IAM 集成,支持生命周期策略

GCR / Artifact Registry

云服务

与 GCP 深度集成,支持多区域部署

GitHub Container Registry

SaaS

与 GitHub Actions 无缝集成

Azure ACR

云服务

支持 Azure AD 认证和异地复制

镜像标签策略#

# 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

合理的标签策略对于镜像的版本管理至关重要:

  • 语义化版本号(Semantic Versioning)——推荐用于正式发布,便于回滚和版本追踪

  • Git 提交哈希(SHA)——推荐用于 CI/CD 流水线,确保每次构建可追溯

  • 分支名 + 时间戳——适用于开发和测试环境

  • 生产环境中切勿使用 :latest 标签,因为它指向不确定的版本

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

自建镜像仓库(Docker Registry)#

# 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 部署#

# 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

Harbor 是目前最流行的企业级开源镜像仓库,内置漏洞扫描、RBAC 权限管理、镜像复制等功能,推荐通过官方安装脚本进行部署。

镜像安全扫描#

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

建议在 CI/CD 流水线中集成镜像扫描步骤,对发现的高危(HIGH)和严重(CRITICAL)漏洞设置构建失败策略,从源头把控镜像安全。

镜像签名(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

镜像签名用于验证镜像的来源和完整性。Cosign 支持传统的密钥对签名方式,也支持基于 OIDC 的无密钥(Keyless)签名,后者无需管理密钥,更适合在 CI/CD 环境中使用。

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