You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Lambda函数在同账号同区域复制ECR镜像标签?

解决ECR跨仓库镜像复制的LayersNotFoundException问题

问题背景

需要通过Lambda函数将同账号同区域下两个ECR仓库的指定镜像标签复制:dev-repo(开发测试用)到release-repo(发布用),要做成WebAPI因此不使用命令行的PULL/TAG/PUSH流程。尝试用AWS.ECR的putImage() API实现,但执行时抛出LayersNotFoundException,提示目标仓库缺少镜像所需的层。

原错误代码片段:

const ecr = new AWS.ECR({
        apiVersion: '2015-09-21',
        region: 'ap-northeast-1'
    });
var params3 = {
 imageIds: [
    {
   imageTag: "latest"
  }
 ], 
 repositoryName: "dev-repo"
};
await ecr.batchGetImage(params3, function(err, data) {
    console.log(`[log] batchGetImage ----`);
    console.log(data.images[0].imageId);
  if (err) console.log(err, err.stack);
  else {
      console.log(data);
      _imageManifest = data.images[0].imageManifest;
      _imageDigest = data.images[0].imageId.imageDigest;
      _imageTag = data.images[0].imageId.imageTag;
      _imageManifestMediaType = data.images[0].imageManifestMediaType;
      _registryId = data.images[0].registryId;
  }
}).promise();

var params4 = {
  imageManifest: _imageManifest,
  repositoryName: 'release-repo',
  imageDigest: _imageDigest,
  imageManifestMediaType: _imageManifestMediaType,
  imageTag: _imageTag,
  registryId: _registryId
};
await ecr.putImage(params4, function(err, data) {
    console.log(`[log] putImage ----`);
  if (err) console.log(err, err.stack);
  else     console.log(data);
}).promise();

错误信息:

{
  "errorType": "LayersNotFoundException",
  "errorMessage": "Layers with digests '[sha256:bf06eb87a616c35c96a20d27e321d128c8ffa3d3043be450e4cde55c40ae1234,sha256:b06e123492282da4881988d86ce029772688c184c8e3d4be8ca57324c132d914,...]' required for pushing image into repository with name 'release-repo' in the registry with id 'xxxxxxx' do not exist",
  "trace": [...]
}

错误原因

putImage() API的设计目标是向目标仓库上传镜像清单(manifest),但要求镜像的所有层已经存在于目标仓库中。当前场景下,镜像层仅存在于源仓库dev-repo,目标仓库release-repo无对应层,因此触发该错误。正确的做法是使用ECR专门提供的**copyImage() API**,它会自动处理镜像层的跨仓库复制,无需手动处理清单。


修正后的Lambda代码

const AWS = require('aws-sdk');
const ecr = new AWS.ECR({
    apiVersion: '2015-09-21',
    region: 'ap-northeast-1'
});

exports.handler = async (event) => {
    try {
        const copyParams = {
            sourceImageTag: "latest", // 源镜像标签
            sourceRepositoryName: "dev-repo", // 源仓库名称
            destinationRepositoryName: "release-repo", // 目标仓库名称
            registryId: "你的AWS账号ID", // 同账号场景可省略,跨账号需填写源账号ID
            destinationImageTag: "latest" // 目标镜像标签,可自定义
        };

        const copyResult = await ecr.copyImage(copyParams).promise();
        console.log("镜像复制成功:", copyResult);
        return {
            statusCode: 200,
            body: JSON.stringify({message: "镜像复制成功", image: copyResult.imageId})
        };
    } catch (err) {
        console.error("镜像复制失败:", err);
        return {
            statusCode: 500,
            body: JSON.stringify({error: err.message})
        };
    }
};

权限配置

确保Lambda执行角色拥有以下权限(添加到角色的IAM策略中):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:CopyImage",
                "ecr:BatchGetImage",
                "ecr:GetDownloadUrlForLayer"
            ],
            "Resource": [
                "arn:aws:ecr:ap-northeast-1:你的账号ID:repository/dev-repo",
                "arn:aws:ecr:ap-northeast-1:你的账号ID:repository/release-repo"
            ]
        }
    ]
}

补充说明

  • copyImage()支持同账号/跨账号、同区域/跨区域的镜像复制,参数配置灵活。
  • 如果需要复制特定镜像摘要(digest)而非标签,可以将sourceImageTag替换为sourceImageDigest。
  • 原代码中同时混用了回调函数和async/await,会导致变量赋值时机异常,修正后的代码统一使用async/await处理异步操作,避免逻辑冲突。

内容的提问来源于stack exchange,提问作者Ray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:24:13