容器注册表管理Skill container-registry-management

提供全面的容器注册表管理解决方案,包括镜像扫描、漏洞检测、保留策略、访问控制和多区域复制,以提高安全性和效率。

DevOps 0 次安装 0 次浏览 更新于 3/3/2026

name: container-registry-management description: 管理容器注册表(Docker Hub、ECR、GCR)包括镜像扫描、漏洞检测、保留策略、访问控制和多区域复制。

容器注册表管理

概览

实现全面的容器注册表管理,包括镜像扫描、漏洞检测、保留策略、访问控制和多区域复制。

何时使用

  • 容器镜像存储和分发
  • 安全扫描和合规性
  • 镜像保留和清理
  • 注册表访问控制
  • 多区域部署
  • 镜像签名和验证
  • 成本优化

实施示例

1. AWS ECR 设置和管理

# ecr-setup.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ecr-management
  namespace: operations
data:
  setup-ecr.sh: |
    #!/bin/bash
    set -euo pipefail

    REGISTRY_NAME="myapp"
    REGION="us-east-1"
    ACCOUNT_ID="123456789012"

    echo "设置ECR仓库..."

    # 创建ECR仓库
    aws ecr create-repository \
      --repository-name "$REGISTRY_NAME" \
      --region "$REGION" \
      --encryption-configuration encryptionType=KMS,kmsKey=arn:aws:kms:$REGION:$ACCOUNT_ID:key/12345678-1234-1234-1234-123456789012 \
      --image-tag-mutability IMMUTABLE \
      --image-scanning-configuration scanOnPush=true || true

    echo "仓库:$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REGISTRY_NAME"

    # 设置生命周期策略
    aws ecr put-lifecycle-policy \
      --repository-name "$REGISTRY_NAME" \
      --region "$REGION" \
      --lifecycle-policy-text '{
        "rules": [
          {
            "rulePriority": 1,
            "description": "保留最后20个标记为发布的镜像",
            "selection": {
              "tagStatus": "tagged",
              "tagPrefixList": ["release"],
              "countType": "imageCountMoreThan",
              "countNumber": 20
            },
            "action": {
              "type": "expire"
            }
          },
          {
            "rulePriority": 2,
            "description": "移除7天前未标记的镜像",
            "selection": {
              "tagStatus": "untagged",
              "countType": "sinceImagePushed",
              "countUnit": "days",
              "countNumber": 7
            },
            "action": {
              "type": "expire"
            }
          },
          {
            "rulePriority": 3,
            "description": "保留所有开发镜像30天",
            "selection": {
              "tagStatus": "tagged",
              "tagPrefixList": ["dev"],
              "countType": "sinceImagePushed",
              "countUnit": "days",
              "countNumber": 30
            },
            "action": {
              "type": "expire"
            }
          }
        ]
      }'

    # 启用跨区域复制
    aws ecr create-registry \
      --region "$REGION" \
      --replication-configuration '{
        "rules": [
          {
            "destinations": [
              {
                "region": "eu-west-1",
                "registryId": "'$ACCOUNT_ID'"
              },
              {
                "region": "ap-northeast-1",
                "registryId": "'$ACCOUNT_ID'"
              }
            ],
            "repositoryFilters": [
              {
                "filter": "'$REGISTRY_NAME'",
                "filterType": "PREFIX_MATCH"
              }
            ]
          }
        ]
      }' || true

    echo "ECR设置完成"

  scan-images.sh: |
    #!/bin/bash
    set -euo pipefail

    REGISTRY_NAME="myapp"
    REGION="us-east-1"

    echo "扫描$REGISTRY_NAME中的所有镜像"

    # 获取所有镜像ID
    IMAGE_IDS=$(aws ecr list-images \
      --repository-name "$REGISTRY_NAME" \
      --region "$REGION" \
      --query 'imageIds[*]' \
      --output json)

    # 扫描每个镜像
    echo "$IMAGE_IDS" | jq -r '.[] | @base64' | while read image; do
      IMAGE=$(echo "$image" | base64 -d | jq -r '.imageTag')
      DIGEST=$(echo "$image" | base64 -d | jq -r '.imageDigest')

      echo "扫描镜像:$IMAGE ($DIGEST)"

      # 开始扫描
      aws ecr start-image-scan \
        --repository-name "$REGISTRY_NAME" \
        --image-id imageTag="$IMAGE" \
        --region "$REGION" || true

      # 获取扫描结果
      sleep 5
      RESULTS=$(aws ecr describe-image-scan-findings \
        --repository-name "$REGISTRY_NAME" \
        --image-id imageTag="$IMAGE" \
        --region "$REGION")

      CRITICAL=$(echo "$RESULTS" | jq '.imageScanFindings.findingSeverityCounts.CRITICAL // 0')
      HIGH=$(echo "$RESULTS" | jq '.imageScanFindings.findingSeverityCounts.HIGH // 0')

      if [ "$CRITICAL" -gt 0 ]; then
        echo "警告:镜像有$CRITICAL个严重漏洞"
      fi

      if [ "$HIGH" -gt 0 ]; then
        echo "警告:镜像有$HIGH个高漏洞"
      fi
    done

    echo "镜像扫描完成"

---
# Terraform ECR配置
resource "aws_ecr_repository" "myapp" {
  name                 = "myapp"
  image_tag_mutability = "IMMUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }

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

  tags = {
    Name = "myapp-registry"
  }
}

resource "aws_ecr_lifecycle_policy" "myapp" {
  repository = aws_ecr_repository.myapp.name

  policy = jsonencode({
    rules = [
      {
        rulePriority = 1
        description  = "保留最后20个生产镜像"
        selection = {
          tagStatus       = "tagged"
          tagPrefixList   = ["release"]
          countType       = "imageCountMoreThan"
          countNumber     = 20
        }
        action = {
          type = "expire"
        }
      },
      {
        rulePriority = 2
        description  = "7天后移除未标记的镜像"
        selection = {
          tagStatus     = "untagged"
          countType     = "sinceImagePushed"
          countUnit     = "days"
          countNumber   = 7
        }
        action = {
          type = "expire"
        }
      }
    ]
  })
}

resource "aws_ecr_repository_policy" "myapp" {
  repository = aws_ecr_repository.myapp.name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/EcsTaskExecutionRole"
        }
        Action = [
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage",
          "ecr:GetImage"
        ]
      }
    ]
  })
}

2. 容器镜像构建和推送

#!/bin/bash
# build-and-push.sh - 构建和推送容器镜像

set -euo pipefail

REGISTRY="${1:-123456789012.dkr.ecr.us-east-1.amazonaws.com}"
IMAGE_NAME="${2:-myapp}"
VERSION="${3:-latest}"
DOCKERFILE="${4:-Dockerfile}"

echo "构建和推送容器镜像..."

# 设置完整镜像路径
FULL_IMAGE="$REGISTRY/$IMAGE_NAME:$VERSION"

# 登录到ECR
echo "认证到ECR..."
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin "$REGISTRY"

# 构建镜像
echo "构建镜像:$FULL_IMAGE"
docker build \
  -f "$DOCKERFILE" \
  -t "$FULL_IMAGE" \
  -t "$REGISTRY/$IMAGE_NAME:latest" \
  --build-arg BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
  --build-arg VCS_REF="$(git rev-parse --short HEAD)" \
  --build-arg VERSION="$VERSION" \
  .

# 推送前用trivy扫描
echo "用Trivy扫描镜像..."
trivy image --severity HIGH,CRITICAL "$FULL_IMAGE"

# 推送镜像
echo "推送镜像到ECR..."
docker push "$FULL_IMAGE"
docker push "$REGISTRY/$IMAGE_NAME:latest"

# 获取镜像摘要
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$FULL_IMAGE" | cut -d@ -f2)

echo "镜像推送成功"
echo "镜像:$FULL_IMAGE"
echo "摘要:$DIGEST"

3. 用Notary签名镜像

#!/bin/bash
# sign-image.sh - 用Notary签名容器镜像

set -euo pipefail

IMAGE="${1}"
NOTATION_KEY="${2:-mykey}"

echo "签名镜像:$IMAGE"

# 初始化Notary
notary key list

# 签名镜像
notation sign \
  --key "$NOTATION_KEY" \
  --allow-missing \
  "$IMAGE"

echo "镜像签名成功"

# 验证签名
notation verify "$IMAGE"

4. 注册表访问控制

# registry-access-control.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ecr-pull-secret
  namespace: production
type: kubernetes.io/dockercfg
stringData:
  .dockercfg: |
    {
      "123456789012.dkr.ecr.us-east-1.amazonaws.com": {
        "auth": "base64-encoded-credentials",
        "email": "service-account@mycompany.com"
      }
    }

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ecr-pull-sa
  namespace: production
imagePullSecrets:
  - name: ecr-pull-secret

---
apiVersion: v1
kind: Pod
metadata:
  name: myapp
  namespace: production
spec:
  serviceAccountName: ecr-pull-sa
  containers:
    - name: app
      image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
      imagePullPolicy: Always

---
# IAM策略用于ECR访问
apiVersion: iam.aws.amazon.com/v1
kind: IAMPolicy
metadata:
  name: ecr-read-only
spec:
  policyDocument:
    Version: '2012-10-17'
    Statement:
      - Effect: Allow
        Action:
          - ecr:GetDownloadUrlForLayer
          - ecr:BatchGetImage
          - ecr:GetImage
          - ecr:DescribeImages
        Resource: arn:aws:ecr:*:123456789012:repository/myapp
      - Effect: Allow
        Action:
          - ecr:GetAuthorizationToken
        Resource: '*'

5. 注册表监控

# registry-monitoring.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: registry-monitoring
  namespace: monitoring
data:
  dashboards.json: |
    {
      "dashboard": {
        "title": "容器注册表",
        "panels": [
          {
            "title": "按仓库的镜像",
            "targets": [
              {
                "expr": "count by (repository) (aws_ecr_repository_images)"
              }
            ]
          },
          {
            "title": "有漏洞的镜像",
            "targets": [
              {
                "expr": "sum(aws_ecr_image_scan_findings{severity=~\"HIGH|CRITICAL\"})"
              }
            ]
          },
          {
            "title": "注册表存储",
            "targets": [
              {
                "expr": "aws_ecr_repository_size_bytes"
              }
            ]
          }
        ]
      }
    }

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: registry-alerts
  namespace: monitoring
data:
  alerts.yaml: |
    groups:
      - name: registry_alerts
        rules:
          - alert: ImageWithCriticalVulnerabilities
            expr: aws_ecr_image_scan_findings{severity="CRITICAL"} > 0
            for: 5m
            labels:
              severity: critical
            annotations:
              summary: "镜像有严重漏洞"

          - alert: ImagePushFailure
            expr: aws_ecr_push_failures_total > 0
            for: 1m
            labels:
              severity: warning
            annotations:
              summary: "镜像推送失败"

          - alert: RegistryStorageHigh
            expr: aws_ecr_repository_size_bytes / 1024 / 1024 / 1024 > 100
            labels:
              severity: warning
            annotations:
              summary: "注册表存储使用率高"

最佳实践

✅ DO

  • 部署前扫描镜像
  • 使用镜像标签不变性
  • 实施保留策略
  • 用IAM控制注册表访问
  • 签名镜像以供验证
  • 跨区域复制
  • 监控注册表存储
  • 使用私有注册表

❌ DON’T

  • 推送到公共注册表
  • 在生产中使用latest标签
  • 允许匿名拉取
  • 在镜像中存储秘密
  • 无限期保留旧镜像
  • 未扫描即推送
  • 使用默认凭据
  • 共享注册表凭据

注册表选项

  • Docker Hub: 公共注册表
  • AWS ECR: AWS管理
  • Google GCR: Google云
  • Azure ACR: Azure管理
  • Artifactory: 自托管
  • Harbor: 开源

镜像命名约定

[registry]/[organization]/[repository]:[tag]
123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:v1.2.3

资源