Goal
I want to be able to create a lambda function with CDK, but then manage the docker image that the lambda uses with a CI/CD pipeline (github actions)
What I have done
I have the following code:
this.repository =
this.config.repository ??
new ecr.Repository(this, 'Repository', {
repositoryName: this.config.repositoryName,
});
this.lambda = new lambda.DockerImageFunction(this, 'DockerLambda', {
code: lambda.DockerImageCode.fromImageAsset(
path.join(__dirname, '../docker/minimal'),
{ cmd: this.config.cmd, entrypoint: this.config.entrypoint },
),
functionName: config.functionName ?? this.node.id,
environment: config.environment,
timeout: Duration.seconds(config.timeout ?? 600),
memorySize: config.memorySize ?? 1024,
vpc: config.vpc,
vpcSubnets: config.vpcSubnets ?? {
subnets: config.vpc?.privateSubnets,
},
});
I am doing it this way because there doesn't appear to be a way to create a lambda without specifying where the code will come from. The 'minimal' docker is just a generic placeholder, it will eventually get replaced by the real code. That code does not live in the repository where we have our CDK code, so CDK does not have access to build the real docker image.
So, the steps that we follow are:
- Use this generic
DockerImageLambda
construct to create both an ECR repository, and a lambda with a placeholder docker image. This ECR repository is where github will be uploading the real images, but until then, it will be empty (since it was just created). - Use Github actions to upload a real docker image to the ECR repository created in step #1
- Use Github actions to update the lambda function with the new image from step #2
The Problem
This method works until you change something in the lambda CDK code. At that point, it will try to reconfigure the lambda to use the placeholder docker image, which essentially "breaks" what was working there.
The question
How can I make it use the placeholder docker image only the first time the lambda is created? OR, is there a better way to do this?
CodePudding user response:
You can decouple uploading the asset to ECR from the lambda definition.
To upload to the repository you created, use the cdk-ecr-deployment
construct. Then create the lambda with the correct ECR repository from the beginning. You will not need to edit the lambda to change the source ECR repository.
You also need to make your Lambda construct depend on the deployment, so that when the lambda is created, the repository contains your dummy image.
It would look like this:
this.repository =
this.config.repository ??
new ecr.Repository(this, 'Repository', {
repositoryName: this.config.repositoryName,
});
const dummyImage = DockerImageAsset(
path.join(__dirname, '../docker/minimal')
)
const dummyDeployment = new ECRDeployment(this, 'DummyImage',
{ src: new DockerImageName(dummyImage.imageUri),
dest: new DockerImageName(this.repository.repositoryUriForTagOrDigest('latest')
})
this.lambda = new lambda.DockerImageFunction(this, 'DockerLambda', {
code: lambda.DockerImageCode.fromEcr(
this.repository,
{ cmd: this.config.cmd, entrypoint: this.config.entrypoint },
),
functionName: config.functionName ?? this.node.id,
environment: config.environment,
timeout: Duration.seconds(config.timeout ?? 600),
memorySize: config.memorySize ?? 1024,
vpc: config.vpc,
vpcSubnets: config.vpcSubnets ?? {
subnets: config.vpc?.privateSubnets,
},
});
this.lambda.node.addDependency(dummyDeployment)
CodePudding user response:
You could import the real ECR into your CDK stack with the fromXXXXX help methods.