Help us learn about your current experience with the documentation. Take the survey.

教程:将容器镜像从 Amazon ECR 迁移到 GitLab

手动在注册表之间迁移容器镜像可能很耗时。本教程介绍如何设置 CI/CD 管道,以自动化将容器镜像从 Amazon Elastic Container Registry (ECR) 批量迁移到 GitLab 容器注册表。

要将容器镜像从 ECR 迁移:

  1. 配置 AWS 权限
  2. 在 UI 中将 AWS 凭证添加为变量
  3. 创建迁移管道
  4. 运行并验证迁移

当您完成所有设置后,您的 .gitlab-ci.yml 文件应该与本教程末尾提供的示例配置相似。

开始之前

您必须具备:

  • 在 GitLab 项目中拥有 Maintainer 角色或更高权限
  • 能够创建 IAM 用户的 AWS 账户访问权限
  • 您的 AWS 账户 ID
  • ECR 仓库所在的 AWS 区域
  • GitLab 容器注册表中有足够的存储空间

配置 AWS 权限

在 AWS IAM 中,创建一个具有 ECR 只读访问权限的新策略和用户:

  1. 在 AWS 管理控制台中,转到 IAM。

  2. 创建一个新策略:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "ecr:GetAuthorizationToken",
                    "ecr:BatchCheckLayerAvailability",
                    "ecr:GetDownloadUrlForLayer",
                    "ecr:DescribeRepositories",
                    "ecr:ListImages",
                    "ecr:DescribeImages",
                    "ecr:BatchGetImage"
                ],
                "Resource": "*"
            }
        ]
    }
  3. 创建一个新的 IAM 用户并附加该策略。

  4. 为 IAM 用户生成并保存访问密钥。

在 UI 中将 AWS 凭证添加为变量

在 GitLab 项目中将所需的 AWS 凭证配置为变量:

  1. 在左侧边栏,选择 搜索或转到 并找到您的项目。
  2. 选择 设置 > CI/CD
  3. 展开 变量
  4. 选择 添加变量 并添加:
    • AWS_ACCOUNT_ID:您的 AWS 账户号。
    • AWS_DEFAULT_REGION:您的 ECR 区域。例如,us-east-1
    • AWS_ACCESS_KEY_ID:来自您的 IAM 用户的访问密钥 ID。
      • 选择 屏蔽变量
    • AWS_SECRET_ACCESS_KEY:来自您的 IAM 用户的秘密访问密钥。
      • 选择 屏蔽变量

创建迁移管道

在您的仓库中创建一个新的 .gitlab-ci.yml 文件,并包含以下配置:

设置镜像和服务

使用 Docker-in-Docker 处理容器操作:

image: docker:20.10
services:
  - docker:20.10-dind

定义管道变量

为管道设置所需的变量:

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""
  BULK_MIGRATE: "true"

配置迁移作业

创建处理传输的迁移作业:

migration:
  stage: deploy
  script:
    # 安装所需工具
    - apk add --no-cache aws-cli jq

    # 验证 AWS 凭证
    - aws sts get-caller-identity

    # 登录注册表
    - aws ecr get-login-password | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
    - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}

    # 获取 ECR 仓库列表
    - REPOS=$(aws ecr describe-repositories --query 'repositories[*].repositoryName' --output text)

    # 处理每个仓库
    - |
      for repo in $REPOS; do
        echo "Processing repository: $repo"

        # 获取此仓库的所有标签
        TAGS=$(aws ecr describe-images --repository-name $repo --query 'imageDetails[*].imageTags[]' --output text)

        # 处理每个标签
        for tag in $TAGS; do
          echo "Processing tag: $tag"

          # 从 ECR 拉取镜像
          docker pull ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag}

          # 标记为 GitLab 注册表
          docker tag ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag} ${CI_REGISTRY_IMAGE}/${repo}:${tag}

          # 推送到 GitLab
          docker push ${CI_REGISTRY_IMAGE}/${repo}:${tag}
        done
      done

运行并验证迁移

设置管道后:

  1. 提交并推送 .gitlab-ci.yml 文件到您的仓库。
  2. 转到 CI/CD > 管道 以监控迁移进度。
  3. 完成后,验证迁移:
    • 转到 软件包和注册表 > 容器注册表
    • 验证所有仓库和标签是否存在。
    • 测试拉取一些已迁移的镜像。

示例 .gitlab-ci.yml 配置

当您遵循前面的所有步骤时,.gitlab-ci.yml 文件应该如下所示:

image: docker:20.10
services:
  - docker:20.10-dind

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""
  BULK_MIGRATE: "true"

migration:
  stage: deploy
  script:
    # 安装所需工具
    - apk add --no-cache aws-cli jq

    # 验证 AWS 凭证
    - aws sts get-caller-identity

    # 登录注册表
    - aws ecr get-login-password | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
    - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}

    # 获取 ECR 仓库列表
    - REPOS=$(aws ecr describe-repositories --query 'repositories[*].repositoryName' --output text)

    # 处理每个仓库
    - |
      for repo in $REPOS; do
        echo "Processing repository: $repo"

        # 获取此仓库的所有标签
        TAGS=$(aws ecr describe-images --repository-name $repo --query 'imageDetails[*].imageTags[]' --output text)

        # 处理每个标签
        for tag in $TAGS; do
          echo "Processing tag: $tag"

          # 从 ECR 拉取镜像
          docker pull ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag}

          # 标记为 GitLab 注册表
          docker tag ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag} ${CI_REGISTRY_IMAGE}/${repo}:${tag}

          # 推送到 GitLab
          docker push ${CI_REGISTRY_IMAGE}/${repo}:${tag}
        done
      done
  rules:
    - if: $BULK_MIGRATE == "true"