skip to Main Content

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:

  1. 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).
  2. Use Github actions to upload a real docker image to the ECR repository created in step #1
  3. 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?

2

Answers


  1. 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)
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search