感觉就像是先有鸡还是先有蛋的问题。 我正在尝试构建一个 Docker 映像,将其添加到我的 ECR 存储库,并在使用 CDK V2 的 Lambda 函数中使用它。
这是我的代码:
const repository = new ecr.Repository(this, `WorkerHelloRepository`, {
repositoryName: `worker-hello`,
imageTagMutability: ecr.TagMutability.IMMUTABLE,
imageScanOnPush: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
lifecycleRules: [
{
description: 'Keeps a maximum number of images to minimize storage',
maxImageCount: 10,
},
],
});
const asset = new DockerImageAsset(this, `WorkerHelloDockerImageAsset`, {
directory: path.join(__dirname, `../../../workers/hello`),
buildArgs: {},
});
const destinationImageName = `${repository.repositoryUri}:${asset.assetHash}`;
new ecrdeploy.ECRDeployment(this, 'EcrDeployment', {
src: new ecrdeploy.DockerImageName(asset.imageUri),
dest: new ecrdeploy.DockerImageName(destinationImageName),
});
const lambdaFunction = new lambda.DockerImageFunction(this, `WorkerHelloFunction`, {
code: lambda.DockerImageCode.fromEcr(repository, {
tagOrDigest: asset.assetHash,
cmd: ['index.newEntry'],
}),
});
repository.grantPull(lambdaFunction);
lambdaFunction.addToRolePolicy(
new cdk.aws_iam.PolicyStatement({
actions: ['ecr:BatchGetImage', 'ecr:GetDownloadUrlForLayer'],
resources: [repository.repositoryArn],
effect: cdk.aws_iam.Effect.ALLOW,
}),
);
CloudFormation 返回的错误说该图片不存在:
4:05:35 AM | CREATE_FAILED | AWS::Lambda::Function | workers-stack/work...orkerHelloFunction
Resource handler returned message: "Source image ***********.dkr.ecr.us-west-2.amazonaws.com/worker-hello:55106229314a459e2cf7fbfa14c2c03b728ffd20a70dad
3cf25ff51d7664abce does not exist. Provide a valid source image. (Service: Lambda, Status Code: 400, Request ID: 6ef7e839-ddb3-43c1-9170-c50865f6af70)" (Reques
tToken: be9bf05b-47e6-5239-da32-46cbe422853d, HandlerErrorCode: InvalidRequest)
但是当我检查 ECR 存储库时(CloudFormation 无法删除,因为它不为空),我可以看到图像并且其 uri 是正确的。
我尝试通过执行以下操作手动将 Lambda 函数的依赖项添加到创建的资产:
lambdaFunction.node.addDependency(asset);
我很确定 CDK 足够聪明,能够实际检测到这种依赖关系,但它并没有解决问题。
我真的想避免为 ECR 建立一个单独的堆栈,但我想这可以解决问题。我没有尝试的是将 ECR 内容和 Lambda 资源移动到两个不同的嵌套堆栈中,并从一个堆栈添加到另一个堆栈的依赖项,但我不明白为什么它会工作得更好。
有什么想法吗?或者甚至有关于如何解决先有鸡还是先有蛋的问题的指导吗?
您的依赖项应该依赖于 ECR 部署,而不是原始资产(因为 lambda 不直接使用该资产)。
你已经完成了大部分工作,这应该可行:
const deployment = new ecrdeploy.ECRDeployment(this, 'EcrDeployment', {
src: new ecrdeploy.DockerImageName(asset.imageUri),
dest: new ecrdeploy.DockerImageName(destinationImageName),
});
const lambdaFunction = new lambda.DockerImageFunction(this, `WorkerHelloFunction`, {
code: lambda.DockerImageCode.fromEcr(repository, {
tagOrDigest: asset.assetHash,
cmd: ['index.newEntry'],
}),
});
// Dependency on the deployment, not the asset
lambdaFunction.node.addDependency(deployment);