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

CDK部署Lambda遇ECR镜像不存在问题求助

解决CDK部署Docker镜像Lambda时首次部署失败的问题

问题描述

我用CDK编写的代码能正常构建Docker镜像并推送到ECR,但首次部署Lambda时会失败,报错提示镜像不存在。第二次执行cdk deploy则一切正常,可修改Docker镜像触发重新构建推送后,问题会再次出现。

错误信息

AppStack | 8:39:53 PM | CREATE_FAILED | AWS::Lambda::Function | xxx_lambda (xxxlambda9C8872F5) Resource handler returned message: "Source image xxxxxxxxxxxxx.dkr.ecr.eu-west-1.amazonaws.com/xxx-uber-docker-img-repo:5e0b247c90c24e68403f249749b74ca94828ccf405300d7984438fd10f1ea7ca does not exist. Provide a valid source image. (Service: Lambda, Status Code: 400, Request ID: xxxxxxxxxx)" (RequestToken: xxxxxxxxx, HandlerErrorCode: InvalidRequest)

我的CDK代码

import * as cdk from 'aws-cdk-lib';
import { aws_s3 as s3, 
  aws_lambda as lambda, 
  aws_apigateway as apigateway, 
  aws_ecr_assets as ecr_assets, 
  aws_ecr as ecr,
  aws_ec2 as ec2,
  aws_efs as efs,
  aws_iam as iam,
  aws_elasticbeanstalk as ebs,
  aws_codecommit as cc,
  aws_codebuild as cb,
  aws_codestarconnections as csc,
  aws_codepipeline as cpl,
  aws_codepipeline_actions as cpla,
  aws_s3_assets as s3assets,
  aws_dynamodb as db
 } from 'aws-cdk-lib';
import * as ecrdeploy from 'cdk-ecr-deployment';

function docker_img_asset(scope: Construct, id: string, props: ecr_assets.DockerImageAssetProps):ecr_assets.DockerImageAsset{
  const img_dir = 'docker_images/' + id + '/';
  const p:ecr_assets.DockerImageAssetProps = {
    ...props,
    exclude:excludes_for(id).concat((props.exclude??[]).map(x=>img_dir+x)),
    file: img_dir + (props.file ?? 'Dockerfile'),
  };
  return new ecr_assets.DockerImageAsset(scope, id+'_img', p);
}


const xxx_uber_ecr_repo = new ecr.Repository(this, 'xxx-uber-docker-img-repo', {
  repositoryName: 'xxx-uber-docker-img-repo',
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  lifecycleRules: [{
      description: "Keeps a maximum number of images to minimize storage",
      maxImageCount: 1
  }],
});

const xxx_ecr_img = docker_img_asset(this, 'xxx', {
  directory: ROOT_DIR,
  exclude:[],
  invalidation: {
    buildArgs: false,
    buildSecrets: false
  },
});
const xxx_uber_ecr_deployment = new ecrdeploy.ECRDeployment(this, 'xxxUberEcrDeployment', {
    src: new ecrdeploy.DockerImageName(xxx_ecr_img.imageUri),
    dest: new ecrdeploy.DockerImageName(`${xxx_uber_ecr_repo.repositoryUri}:${xxx_ecr_img.assetHash}`),
});

const xxx_lambda = new lambda.DockerImageFunction(this, "xxx_lambda", {
  code: lambda.DockerImageCode.fromEcr(xxx_uber_ecr_repo, {
    tagOrDigest: xxx_ecr_img.imageTag
  }),
  environment: {
    // 'BUCKET': packaged_blender_files.bucketName
  },
  memorySize: 2048,
  // ephemeralStorageSize: cdk.Size.mebibytes(10240),
  timeout: cdk.Duration.minutes(15)
});

问题原因

核心问题是资源依赖顺序缺失:CDK默认会根据资源引用自动推断依赖关系,但这里Lambda仅关联了ECR仓库和镜像标签,CDK无法识别它需要等待xxx_uber_ecr_deployment完成镜像推送后再创建。首次部署时,Lambda与ECRDeployment并行启动,此时目标ECR仓库中还没有推送完成的镜像,因此报错;第二次部署时镜像已存在,所以能成功;修改镜像后新镜像未完成推送,问题再次出现。

解决方案

给Lambda添加显式依赖,确保它在ECR镜像推送完成后再创建。同时统一镜像标签的引用,避免不一致:

// ... 保留原有代码不变 ...

const xxx_uber_ecr_deployment = new ecrdeploy.ECRDeployment(this, 'xxxUberEcrDeployment', {
    src: new ecrdeploy.DockerImageName(xxx_ecr_img.imageUri),
    dest: new ecrdeploy.DockerImageName(`${xxx_uber_ecr_repo.repositoryUri}:${xxx_ecr_img.assetHash}`),
});

const xxx_lambda = new lambda.DockerImageFunction(this, "xxx_lambda", {
  code: lambda.DockerImageCode.fromEcr(xxx_uber_ecr_repo, {
    tagOrDigest: xxx_ecr_img.assetHash // 与推送时的标签保持一致
  }),
  environment: {
    // 'BUCKET': packaged_blender_files.bucketName
  },
  memorySize: 2048,
  timeout: cdk.Duration.minutes(15)
});

// 添加显式依赖,强制Lambda等待镜像推送完成
xxx_lambda.node.addDependency(xxx_uber_ecr_deployment);

这样修改后,CDK会严格按照「构建镜像 → 推送到ECR → 创建Lambda」的顺序执行部署,彻底解决首次部署失败的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:07:26