

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 从第三方注册表迁移容器镜像
<a name="migrate-from-third-party"></a>

使用本指南将容器映像从外部注册表一次性复制到不支持 ECR Pull Through Cache 的 Amazon ECR 私有注册表中。

如果您的源[是支持的上游注册表](https://docs.amazonaws.cn/AmazonECR/latest/userguide/pull-through-cache-creating-rule.html)，则无需执行一次性复制。[将上游注册表与 Amazon ECR 私有注册表同步](pull-through-cache.md)要配置自动缓存，请参阅。

**注意**  
Amazon ECR 会存储您复制的图像版本。不会自动从源注册表中提取较新的版本。要更新映像，请将新版本推送到您的 Amazon ECR 存储库。

## 迁移概述
<a name="migrate-overview"></a>

迁移容器镜像涉及以下六个步骤：

1. 在构建和部署文件中识别外部图像引用。

1. 规划您的 Amazon ECR 存储库结构。

1. 将图像复制到 Amazon ECR。

1. 验证镜像完整性。

1. 更新您的部署配置。

1. 监控和验证。

## 先决条件
<a name="migrate-prerequisites"></a>

在开始之前，请验证以下几点：
+ 安装和配置 Amazon CLI 版本 2. 有关更多信息，请参阅 [Install or update to the latest version of the Amazon CLI](https://docs.amazonaws.cn/cli/latest/userguide/getting-started-install.html)。
+ 安装 Docker Engine 或 Docker 桌面版 20.10 或更高版本。有关更多信息，请参阅 [Docker 文档中的安装 Docker 引擎](https://docs.docker.com/engine/install/)。
+ （可选）Install`skopeo`，这是一款开源工具，用于在没有本地 Docker 守护程序的情况下在注册表之间复制容器镜像。有关安装说明，请参阅上的 [Skopeo](https://github.com/containers/skopeo)。 GitHub
+ 验证您的 IAM 身份是否有权对您的注册表进行身份验证、创建存储库和推送映像。将`AmazonEC2ContainerRegistryFullAccess`托管策略附加到您用来运行这些命令的 IAM 用户或角色。有关更多信息，请参阅 [Amazon 亚马逊弹性容器注册表的托管策略](security-iam-awsmanpol.md)。

## 步骤 1：识别外部图像引用
<a name="migrate-identify-references"></a>

搜索用于构建和部署容器映像的文件，以获取对第三方注册表的引用。

以下命令使用 Linux 和 macOS 外壳语法。在 Windows 上，使用适用于 Linux 的 Windows 子系统 (WSL) 或 Git Bash。

### 识别部署清单中的参考文献
<a name="migrate-identify-manifests"></a>

在您的 Amazon ECS 任务定义或 Amazon EKS 清单中搜索非 ECR 图片引用。

**对于 Kubernetes 清单：**

```
grep -rnH --include="*.yaml" --include="*.yml" "image:" . | grep -iv "dkr.ecr"
```

**要运行 Amazon EKS 工作负载：**

```
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{range .spec.initContainers[*]}{.image}{"\n"}{end}{end}' | sort -u | grep -iv "dkr.ecr"
```

**对于 Amazon ECS 任务定义：**

```
aws ecs list-task-definitions --status ACTIVE --query 'taskDefinitionArns' --output text | \
  tr '\t' '\n' | \
  xargs -I {} aws ecs describe-task-definition --task-definition {} \
  --query 'taskDefinition.containerDefinitions[].image' --output text | \
  tr '\t' '\n' | sort -u | grep -iv "dkr.ecr"
```

### 识别 Dockerfiles 中的参考文献
<a name="migrate-identify-dockerfiles"></a>

要查找在构建目录中引用外部注册表的`FROM`指令，请执行以下操作：

```
grep -rnH --include="Dockerfile*" "FROM" . | grep -iv "dkr.ecr"
```

输出显示了引用 Amazon ECR 之外的图像的文件和行号。例如：

```
./app/Dockerfile:1:FROM python:3.11-slim
./service/Dockerfile:1:FROM nginx:1.25
./worker/Dockerfile:3:FROM redis:7-alpine
```

### 识别拉动频率（可选）
<a name="migrate-identify-pull-frequency"></a>

要了解您的工作负载从第三方注册表提取的频率，请查看上游注册表的使用情况分析（例如，Docker Hub 在账户控制面板中提供提取率数据）。高拉频率会增加达到速率限制的风险。有关 Docker Hub 速率限制，请参阅 [Docker 文档中的 Docker Hub 速率限制](https://docs.docker.com/docker-hub/download-rate-limit/)。

## 第 2 步：规划存储库结构
<a name="migrate-plan-structure"></a>

在复制图像之前，请决定如何在 Amazon ECR 中对其进行整理。

**存储库命名**-Amazon ECR 支持带有正斜杠的命名空间前缀。使用命名空间按团队、环境或应用程序对相关图像进行分组。命名空间还为每个前缀启用限定范围的 IAM 策略。例如：

```
base-images/python
base-images/nginx
team-a/web-app
team-b/api-service
```

**标签不可变性**-对于生产映像，启用标签不可变性以防止图像标签被覆盖。有关更多信息，请参阅 [防止映像标签在 Amazon ECR 中被覆盖](image-tag-mutability.md)。

**加密**-在创建存储库之前选择您的加密配置。存储库创建后，您无法更改加密配置。有关更多信息，请参阅 [静态加密](encryption-at-rest.md)。

**存储成本**-Amazon ECR 会对每个存储库中的图像层进行重复数据消除。如果多个图像共享相同的基础图层，则每个存储库只需要为这些图层支付一次费用。在计划迁移哪些图像时，请将其考虑在成本估算中。

**存储库创建模板**-如果您要迁移许多映像，请使用您的首选设置（标签不可变性、加密、生命周期策略）为推送时创建操作配置存储库创建模板。Amazon ECR 在第一次推送期间代表您创建存储库时会应用模板设置。有关更多信息，请参阅 [用于控制在缓存拉取、推送时创建或复制操作期间创建的存储库的模板](repository-creation-templates.md)。

**托管签名**-如果您计划使用托管签名对图像进行签名，请在推送图像之前配置您的签名规则。签名仅在推送时发生。有关更多信息，请参阅 [在亚马逊 ECR 中签名图片](image-signing.md)。

**Cross-Region 复制**-如果您的工作负载在多个 Amazon 区域运行，请在推送映像之前配置复制规则。复制仅复制配置规则后推送的图像。有关更多信息，请参阅 [Amazon ECR 中的私有映像复制](replication.md)。

**注意**  
Multi-architecture 除了清单列表之外，图片（清单列表）还要求您复制所有平台特定的清单。如果您使用 Docker，则**docker pull**和**docker push**命令仅处理与您的本地架构相匹配的平台。**skopeo copy --all**用于复制所有平台完好无损的多架构映像。

## 第 3 步：将图像复制到 Amazon ECR
<a name="migrate-copy-images"></a>

在复制图像之前，请对您的 Amazon ECR 私有注册表进行身份验证。您的注册表 URL 遵循以下格式`{{account-id}}.dkr.ecr.{{region}}.amazonaws.com`。在以下示例中，请`us-east-1`使用您的 Amazon 账户 ID 和您的地区替换`111122223333`。在`aws-cn`分区中，注册表 URL 后缀为`.amazonaws.com.cn`。在所有其他分区 (`aws`,`aws-us-gov`) 中，后缀为`.amazonaws.com`。

**要查找您的账户 ID，请运行：**

```
aws sts get-caller-identity --query Account --output text
```

有关身份验证方法的更多信息，请参阅[Amazon ECR 中的私有注册表身份验证](registry_auth.md)。

**如果您使用 Docker（选项 A）**，请使用以下方式进行身份验证：

```
aws ecr get-login-password --region {{us-east-1}} | \
docker login --username AWS --password-stdin {{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com
```

**如果您使用 skopeo（选项 B）**，请改为使用进行**skopeo login**身份验证。Skopeo 与 Docker 分开维护自己的凭证存储：

```
aws ecr get-login-password --region {{us-east-1}} | \
skopeo login {{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com --username AWS --password-stdin
```

选择以下方法之一来复制您的图像。

### 选项 A：使用 Docker CLI 进行复制
<a name="migrate-copy-docker"></a>

对*极*少数单平台图像使用此方法。有关推送工作流程的详细介绍，请参阅。[在 Amazon ECR 中移动映像的整个生命周期](getting-started-cli.md)

1. 创建目标存储库（如果存储库已存在，则跳过此步骤）：

   ```
   aws ecr create-repository \
     --repository-name {{base-images/nginx}} \
     --region {{us-east-1}} \
     --image-tag-mutability IMMUTABLE \
     --encryption-configuration encryptionType=AES256
   ```

1. 如果您使用经过身份验证的帐户从 Docker Hub 提取，以避免速率限制，请**docker login docker.io**先运行。从第三方注册表中提取镜像：

   ```
   docker pull nginx:1.25
   ```

1. 为你的 Amazon ECR 存储库的图片添加标签：

   ```
   docker tag nginx:1.25 {{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25
   ```

1. 将图片推送到 Amazon ECR：

   ```
   docker push {{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25
   ```

1. 要在存储库创建后检索存储库 URI，请运行：

   ```
   aws ecr describe-repositories --repository-names {{base-images/nginx}} --query 'repositories[0].repositoryUri' --output text
   ```

**注意**  
Docker CLI 仅复制与您的本地计算机匹配的平台。要复制多架构映像，请使用选项 B 和。**skopeo**

### 选项 B：使用 skopeo 进行复制（建议用于批量迁移）
<a name="migrate-copy-skopeo"></a>

该**skopeo**工具直接在注册表之间复制图像，无需将其拉到本地计算机。这种方法可以更快地执行批量操作，并且支持多架构映像。Skopeo 使用传输前缀来识别图像位置。`docker://`用于远程注册表。

1. 如果需要，请向源注册表进行身份验证。例如，对于 Docker Hub 来说：

   ```
   echo YOUR_TOKEN | skopeo login docker.io --username YOUR_USERNAME --password-stdin
   ```

1. 创建目标存储库：

   ```
   aws ecr create-repository \
     --repository-name {{base-images/nginx}} \
     --region {{us-east-1}}
   ```

1. 复制镜像（单一平台）：

   ```
   skopeo copy docker://docker.io/library/nginx:1.25 \
     docker://{{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25
   ```

1. 要在所有平台上复制多架构映像，请添加标`--all`志：

   ```
   skopeo copy --all docker://docker.io/library/nginx:1.25 \
     docker://{{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25
   ```

**注意**  
**skopeo copy**不复制与图像关联的 OCI 反向链接对象（签名、SBOM、证明）。如果您的源图片有关联的反向链接对象，请单独复制它们，或者在迁移后使用托管签名对图片进行重新签名。

**使用脚本进行批量复制**

要迁移多张图像，请创建一个列出源和目标对的文本文件，然后使用脚本复制它们。

创建一个名为 `images-to-migrate.txt` 的文件：

```
docker.io/library/nginx:1.25 base-images/nginx:1.25
docker.io/library/python:3.11-slim base-images/python:3.11-slim
docker.io/library/redis:7-alpine base-images/redis:7-alpine
ghcr.io/org/custom-app:v2.1.0 team-a/custom-app:v2.1.0
```

运行以下脚本：

```
#!/usr/bin/env bash
set -euo pipefail
ACCOUNT_ID="{{111122223333}}"
REGION="{{us-east-1}}"
REGISTRY="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com"

aws ecr get-login-password --region ${REGION} | \
  skopeo login ${REGISTRY} --username AWS --password-stdin

while IFS=' ' read -r SOURCE DEST; do
  REPO_NAME=$(echo "${DEST}" | cut -d: -f1)

  # Create repository if it does not exist
  aws ecr create-repository \
    --repository-name "${REPO_NAME}" \
    --region "${REGION}" 2>/dev/null || true

  echo "Copying ${SOURCE} to ${REGISTRY}/${DEST}"
  skopeo copy --all "docker://${SOURCE}" "docker://${REGISTRY}/${DEST}"
done < images-to-migrate.txt
```

**注意**  
Amazon ECR 对推送操作强制执行 API 速率限制。对于大型迁移，如果遇到限制，请添加带有指数退避的重试逻辑。授权令牌将在 12 小时后过期。如果您的迁移需要更长的时间，请在继续之前重新运行身份验证命令。

## 步骤 4：验证镜像完整性
<a name="migrate-verify-integrity"></a>

复制图像后，验证 Amazon ECR 中的图像摘要是否与来源相匹配。

1. 在 Amazon ECR 中获取图片摘要：

   ```
   aws ecr describe-images \
     --repository-name {{base-images/nginx}} \
     --image-ids imageTag={{1.25}} \
     --query 'imageDetails[0].imageDigest' \
     --output text
   ```
**注意**  
对于单平台图像，请直接比较摘要。对于使用复制的多架构映像`--all`，Amazon ECR `imageDigest` 中的表示清单列表。改用**skopeo inspect --raw**（如下所示）比较清单列表内容。

1. 将摘要与源注册表进行比较。**skopeo**用于检查来源：

   ```
   skopeo inspect docker://docker.io/library/nginx:1.25 | grep Digest
   ```

1. 摘要必须与复制的单平台图像相匹配。**skopeo**如果它们不匹配，则表示复制未成功完成。重试复制操作。如果您使用 Docker（选项 A），则摘要可能会有所不同，因为 Docker 可以在拉取和推送期间重新处理图层。要精确保存摘要，请使用**skopeo**。

1. 对于多架构映像，**aws ecr describe-images**返回清单列表和单个平台清单。要直接比较清单列表摘要，请在源和目标**skopeo inspect --raw**上使用：

   ```
   skopeo inspect --raw docker://{{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25
   ```

1. （可选）对迁移的映像运行映像扫描以识别漏洞。有关更多信息，请参阅 [在 Amazon ECR 中扫描映像是否存在软件漏洞](image-scanning.md)。

## 步骤 5：更新部署配置
<a name="migrate-update-deployments"></a>

验证映像后，更新您的部署配置以从 Amazon ECR 中提取，并更新您的 CI/CD 构建管道以将新构建的映像推送到 ECR。这可确保将来的映像版本无需额外的手动副本即可使用。

### Amazon ECS 任务定义
<a name="migrate-update-ecs"></a>

使用更新的图片 URI 创建任务定义的新版本：

```
{
  "containerDefinitions": [
    {
      "name": "web",
      "image": "{{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25"
    }
  ]
}
```

有关更多信息，请参阅 *Amazon ECS 开发人员指南*中的[更新任务定义](https://docs.amazonaws.cn/AmazonECS/latest/developerguide/update-task-definition.html)。

### 亚马逊 EKS 或 Kubernetes 清单
<a name="migrate-update-eks"></a>

更新 pod 规格中的`image`字段：

```
spec:
  containers:
    - name: web
      image: {{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/nginx}}:1.25
```

验证您的节点是否可以向 Amazon ECR 进行身份验证。如果`AmazonEC2ContainerRegistryReadOnly`托管策略已附加到节点 IAM 角色，则 Amazon EKS 节点默认使用 Amazon ECR 凭证帮助程序。

### Dockerfiles
<a name="migrate-update-dockerfiles"></a>

更新你的 Dockerfiles 中的`FROM`指令：

```
FROM {{111122223333}}.dkr.ecr.{{us-east-1}}.amazonaws.com/{{base-images/python}}:3.11-slim
```

## 步骤 6：监控和验证
<a name="migrate-monitor"></a>

重新部署工作负载后，请验证所有图像现在是否都来自 Amazon ECR。
+ 检查仓库的 CloudWatch 指标。该`RepositoryPullCount`指标确认拉动正在发生。有关更多信息，请参阅 [Amazon ECR 存储库指标](ecr-repository-metrics.md)。
+ 查看 CloudTrail `BatchGetImage`和`GetDownloadUrlForLayer`事件，确认您的工作负载是否来自预期的存储库。
+ （可选）设置生命周期策略以自动清理旧映像版本。有关更多信息，请参阅 。

## 注意事项
<a name="migrate-considerations"></a>
+ **不支持的上游注册表**-Pull Through Cache 支持一组特定的上游注册表。对于不在该列表中的注册表（例如 jFrog Artifactory、Harbor 或 Sonatype Nexus），请使用 Docker CLI 或直接复制映像。**skopeo**
+ **Large-scale 或跨分区传输**-有关跨 Amazon 分区迁移（例如，`aws`到`aws-cn`）或涉及数千张图像的传输，请参阅上的《[数据传输中心指南](https://www.amazonaws.cn/solutions/guidance/data-transfer-hub-on-aws/)》。 Amazon
+ **Lambda-** Lambda 要求容器镜像存储在 Amazon ECR 中，并且不能直接从第三方注册表中提取。在配置 Lambda 函数之前，使用选项 A 或选项 B 将图像复制到 ECR。

## 相关方法
<a name="migrate-related-approaches"></a>

P@@ **ull Through Cache**-如果您的源注册表是支持的上游注册表之一，并且您希望 Amazon ECR 自动提取和缓存图像而不是执行一次性复制，请参阅。[将上游注册表与 Amazon ECR 私有注册表同步](pull-through-cache.md)