I really like the declarative nature of CloudFormation - you describe an end-state, and it computes the diffs. CDK gives me even more flexibility in creating complex apps.
Recently I built a CDK web application that could provision other CDK apps. React app sends a message to API GW, which invokes a lambda, which triggers a CDK deployment.
The default Lambda runtime cannot deploy CDK. You have to use a custom Docker image. There are plenty of online guides on how to do this, so I am only covering the highlights.
Deployer Stack
It takes a while to build the docker container, so you should define a deployer stack separate from your web app.
It is also handy to add the following script to your package.json:
"cdk:deployer": "npm run cdk -- --app=\"npx ts-node --prefer-ts-exts bin/deployer.ts\""
1 | import { StackProps, Stack, Duration, CfnOutput, Aws } from 'aws-cdk-lib'; |
Notice the deployer-function-arn
export. You will want to import this into your other app.
Dockerfile
This docker file will copy your entire application, and set the lambda entry point.
1 | FROM public.ecr.aws/lambda/nodejs:20 |
Note: I found a few examples online which use a different base image (node:18-bookworm
), which require additional steps including installing aws-lambda-ric
, but I ran into some issues.
- After a certain amount of pulls from the Docker registry, you will have to sign up. For AWS work, ECR is fast and automatic.
- The
public.ecr.aws/lambda/nodejs:20
image is already configured for running node apps. Total build time dropped from ~15 to 4.5 minutes.
Deployer Lambda
Here is the lambda entry point. Notice the handler accepts stack props. Since my app uses API GW with a 15 second timeout, I trigger the trigger this second lambda.
1 | import { randomUUID } from 'crypto'; |
Limitations
- Lambda has a 15 minute timeout. If you expect your app to take longer to run, you can use CodeBuild.
- Alternatively, once CloudFormation has started deploying the changeset, you can kill the process and exit the lambda.
- You should add SNS notifications to the CloudFormation stack so that you can update your provisioning app with success/failure.
Using Codebuild to Build the Deployer
Building a Docker container on a MacBook Pro is crazy slow. The following CodeBuild took ~5 minutes to build the deployer image and deploy it.
1 | import { Stack, StackProps } from 'aws-cdk-lib'; |