AWS ECR镜像跨仓库复制时出现LayersNotFoundException但层实际存在
解决ECR同一注册表内镜像重标记复制的LayersNotFoundException问题
问题原因
同一ECR注册表下的不同仓库是层隔离的,你通过batch-get-image获取的镜像manifest中,层的引用仅指向原仓库的层资源。当执行put-image到目标仓库时,ECR会检查目标仓库是否存在这些层,不存在就会抛出LayersNotFoundException——哪怕层在同一注册表的其他仓库里。
解决思路
1. 使用官方跨仓库复制命令(推荐)
直接用AWS CLI提供的ecr copy-image命令,它会自动处理层的跨仓库复制,无需手动操作manifest:
aws ecr copy-image \ --source-image-repository-name REPO_NAME \ --source-image-tag THE_CURRENT_IMMAGE_TAG \ --destination-image-repository-name NEW_REPOSITORY_NAME \ --destination-image-tag NEW_IMAGE_TAG \ --region YOUR_REGION \ --profile MY_PROFILE
这个命令是AWS官方支持的,能确保所有依赖层被同步到目标仓库,同时创建新的镜像标签。
2. 手动验证并复制层(不推荐,仅用于特殊场景)
如果必须手动处理,需要先将原仓库的层逐一复制到目标仓库:
- 提取manifest中的所有层digest:
LAYER_DIGESTS=$(echo "$MANIFEST" | jq --raw-output '.layers[].digest') - 遍历每个digest,先从原仓库获取层的下载URL,再上传到目标仓库:
完成所有层复制后,再执行你原来的for DIGEST in $LAYER_DIGESTS; do # 获取层下载URL DOWNLOAD_URL=$(aws ecr get-download-url-for-layer \ --repository-name REPO_NAME \ --layer-digest $DIGEST \ --profile MY_PROFILE \ --output json | jq --raw-output '.downloadUrl') # 下载层文件 curl -o layer.tar $DOWNLOAD_URL # 初始化层上传 UPLOAD_RESPONSE=$(aws ecr initiate-layer-upload \ --repository-name NEW_REPOSITORY_NAME \ --profile MY_PROFILE \ --output json) UPLOAD_ID=$(echo $UPLOAD_RESPONSE | jq --raw-output '.uploadId') # 上传层 aws ecr upload-layer-part \ --repository-name NEW_REPOSITORY_NAME \ --upload-id $UPLOAD_ID \ --part-first-byte 0 \ --part-last-byte $(stat -c%s layer.tar) \ --layer-part-blob fileb://layer.tar \ --profile MY_PROFILE # 完成层上传 aws ecr complete-layer-upload \ --repository-name NEW_REPOSITORY_NAME \ --upload-id $UPLOAD_ID \ --layer-digests $DIGEST \ --profile MY_PROFILE # 清理临时文件 rm layer.tar doneput-image命令即可。
注意事项
- 确保执行命令的IAM用户/角色拥有
ecr:CopyImage(或对应手动操作的ecr:GetDownloadUrlForLayer、ecr:InitiateLayerUpload等)权限。 - 同一注册表内的复制不需要指定
source-registry-id,命令会自动识别当前注册表。
内容的提问来源于stack exchange,提问作者JBoy
相关产品推荐
相关产品推荐

