Amazon ECR 目前不支持镜像存储库的自动创建。当开发人员向 Amazon ECR 推送一个新进项,如果与其对应的存储库不存在,推送就会失败。Amazon ECR 相比起其他公有云,他的镜像是必须要求 dockerhub.io/test/nginx:version, 这里 nginx 才会被是为一个镜像存储库,而 GCP 的 Artifact registry 是 test (Project )才会被视为一个镜像存储库。这样对于存储仓库就不需要额外创建了。

下文阐述 Amazon ECR创建仓库的方法

方法1:awscli

awscli 中有 create-repository 子命令,允许用户创建一个仓库

bash
1
aws ecr create-repository --repository-name ${REPO_NAME}

可以使用脚本来检测仓库是否存在 [1]

bash
1
2
3
4
5
6
7
8
9
output=$(aws ecr describe-repositories --repository-names ${REPO_NAME} 2>&1)

if [ $? -ne 0 ]; then
  if echo ${output} | grep -q RepositoryNotFoundException; then
    aws ecr create-repository --repository-name ${REPO_NAME}
  else
    >&2 echo ${output}
  fi
fi

[1]

bash
1
2
3
4
5
6
7
#!/bin/bash

aws ecr describe-repositories --repository-names $1 2>&1 > /dev/null
status=$?
if [[ ! "${status}" -eq 0 ]]; then
    aws ecr create-repository --repository-name $1
fi

方法2:Lambda + EventBridge

Lambda 是 AWS 中的 serverless computing service, 他的名字来源于数学中的 Lambda Calculus(λ演算),在计算机科学中,他称为 lambda functions (anonymous functions)。在 AWS 中就是,程序执行不需要部署服务器,工作负载等程序,只需要提供代码就可以了。

EventBridge 是一个使用事件连接不同应用的 serverless service,可以很容易的构建出基于事件驱动 ( event-driven ) 的应用程序。EventBridge 包含两个组件,“事件总线” 和 “管道”。“事件总线” 接收事件,并将其传送到零个或多个目标的路由器。管道是源和目标之间的点到点继承管道,用于处理和传递单个目标。[2]

前提准备

创建 Lambda 执行角色

给 Amazon Lambda 函数创建一个执行角色(例如:ecr-repo-auto-create),让 Amazon Lambda 可以创建 Amazon ECR 映像库并将日志发送给 Amazon CloudTrail。这个执行角色至少需要拥有以下权限:

  • AWSCloudTrail_FullAccess 将日志发送给 Amazon CloudTrail

  • AmazonEC2ContainerRegistryFullAccess ECR所有访问权限

  • AWSLambda_FullAccess Lambda的所有权限

  • AmazonEventBridgeFullAccess EventBridge的所有权限

  • AmazonS3FullAccess S3 的所有权限

  • IAMReadOnlyAccess IAM 只读权限

最终创建出的角色如下图所示

image-20250503205559371

图:cr-repo-auto-create所需权限

创建 Amazon Lambda

步骤1:在 Amazon Lambda 服务中选择创建函数

image-20250504232903216

图:创建Amazon Lambda步骤1

步骤2:输入函数的名字(这里为:ecr-repo-auto-create),并选择 Python 3.13 作为运行环境

image-20250504233029332

图:创建Amazon Lambda步骤2

步骤3:点击权限下方的“更改默认执行角色”,选择“使用现有角色”,使用在前提条件当中创建 Amazon Lambda 的执行角色(这里选择上面创建的 ecr-repo-auto-create 用户)

image-20250504233218453

图:创建Amazon Lambda步骤3

步骤4:点击“创建函数”

image-20250505000702451

图:创建Amazon Lambda步骤4

步骤5:在 “代码” 部分创建文件 lambda_function.py,并将下面代码复制进入

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import boto3
import json

def lambda_handler(event, context):
    ecr_client = boto3.client('ecr')
    repo_name = event['detail']['requestParameters']['repositoryName']
    
    try:
        # 创建 ECR 仓库
        ecr_client.create_repository(repositoryName=repo_name)
        print(f"Repository {repo_name} created successfully.")
        
        # 定义生命周期策略:保留最新的 10 个镜像版本,删除较旧的
        lifecycle_policy = {
            "rules": [
                {
                    "rulePriority": 1,
                    "description": "Keep only the last 10 images",
                    "selection": {
                        # 适用于所有镜像(无论是否有标签)
                        "tagStatus": "any",
                        "countType": "imageCountMoreThan",
                        # 超过 10 个镜像时触发清理
                        "countNumber": 10
                    },
                    "action": {
                        # 删除超出的镜像
                        "type": "expire"
                    }
                }
            ]
        }
        
        # 将生命周期策略应用到仓库
        ecr_client.put_lifecycle_policy(
            repositoryName=repo_name,
            lifecyclePolicyText=json.dumps(lifecycle_policy)
        )
        print(f"Lifecycle policy applied to {repo_name}: keep last 10 images.")
        
    except Exception as e:
        print(f"Error: {str(e)}")
        return {
            'statusCode': 500,
            'body': json.dumps(f"Failed to process repository {repo_name}: {str(e)}")
        }
    
    return {
        'statusCode': 200,
        'body': json.dumps('Repository creation and lifecycle policy applied successfully')
    }

步骤6:在 “配置”部分,选择 “环境变量”,添加 IMAGE_TAG_MUTABILITYREPO_SCAN_ON_PUSHREPO_TAGS 三个环境变量,并根据实际需求给环境变量赋值。

环境变量
IMAGE_TAG_MUTABILITYMUTABLE
REPO_SCAN_ON_PUSHfalse
REPO_TAGS`

image-20250505001259236

图:创建Amazon Lambda步骤6

创建 Amazon EventBridge 事件

步骤1:在 Amazon EventBridge 服务中选择“创建规则”

image-20250505002158909

图:创建 Amazon EventBridge 事件步骤1

步骤2:填写规则的名字(这里使用:ecr-repo-auto-create),并点击“下一步”

image-20250505002318372

图:创建 Amazon EventBridge 事件步骤2

image-20250505002503367

图:创建 Amazon EventBridge 事件步骤3

步骤3:选择“编辑模式”,将下面内容复制粘贴到空白处。选择下一步

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "source": ["aws.ecr"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    // 修改你的区域
    "awsRegion": ["ap-southeast-1"],
    "eventSource": ["ecr.amazonaws.com"],
    "eventName": ["InitiateLayerUpload"],
    "errorCode": ["RepositoryNotFoundException"]
  }
}

步骤4:将目标设置为“创建 Amazon Lambda” 中创建的 Amazon Lambda 函数 (ecr-repo-auto-create)

image-20250505002757522

图:创建 Amazon EventBridge 事件步骤4

最后可以在 “规则” 中的监控查看函数自动执行的情况,或者报错。

image-20250505003027109

图:创建 Amazon EventBridge 事件步骤5

下图展示了 Amazon EventBridge 执行的一些日志

image-20250505003536416

图:Amazon EventBridge 事件日志1

上图展示了仓库已存在的日志报错。

image-20250505003809541

图:Amazon EventBridge 事件日志2

上图展示了代码错误的日志

image-20250505004020292

图:Amazon EventBridge 事件日志3

上图展示了成功创建仓库的日志。

通过这些日志可以很好的去对你的脚本进行错误排查

Reference

[1] Create AWS ECR repository if it doesn’t exist

[2] 什么是亚马逊 EventBridge?

[3] 实现 Amazon ECR 映像存储库的自动创建

[4] create-repository

[5] Dynamically create repositories upon image push to Amazon ECR