Deploy your AWS CDK App locally
If you are working with AWS, chances are you have come across AWS Cloud Development Kit (CDK) and Localstack.
AWS CDK is an open-source framework to define your infrastructure as code, developed by AWS. AWS CDK supports various programming languages. So, you will find it quite familiar.
On the other hand, Localstack is a service that emulate AWS services, running in a docker container. It enables developers to deploy and test their infrastructure locally. You can configure your AWS CLI to create AWS resources within Localstack instead of AWS Cloud.
You can write your own custom script to invoke AWS CLI to create and maintain the resources in Localstack. For this purpose, I leverage the initialization hooks to initialize the localstack instance running locally. This works pretty well for me.
However, when you update your resources in CDK App, you have to remember to also update your custom scripts to reflect the changes. The addition manual step could lead to several problems. First, you have to remember to update it. Developers are also human who tend to forget manual steps. Second, the changes made in CDK App might have unintended side effect i.e. dropping global secondary index, which cannot be easily caught.
Here comes cdklocal, which is a thin wrapper, developed by Localstack, to enable CDK to deploy to local services provided by Localstack. I recently came across this when looking for a way to not manually creating the resources within Localstack instance.
In this article I will show you how you can use cdklocal to improve your developer experience when working with your AWS infrastructure.
You can get the source code in my github: getting-started-with-cdklocal
Getting Started with cdklocal
We will use this simple infrastructure to demonstrate how to use cdklocal. It only has DynamoDB and S3 bucket.
Pre-requisites
Step by Step Walkthrough
Basic setup
Let's create a basic CDK App following the simple infrastructure example above.
mkdir getting-started-with-cdklocal
cd getting-started-with-cdklocal
npx cdk init app --language typescript
Replace the content of getting-started-with-cdklocal-stack.ts
with the code snippet below.
...
// Create DynamoDB table
const ddbTable = new Table(this, 'DynamoDBTable', {
partitionKey: { name: "pk", type: AttributeType.STRING },
sortKey: { name: "sk", type: AttributeType.STRING },
tableName: 'your-dynamodb',
billingMode: BillingMode.PAY_PER_REQUEST,
});
// Create S3 bucket
new Bucket(this, 'Bucket', {
bucketName: 'your-bucket',
});
...
Next, create a new docker-compose.yml
file to start Localstack.
version: "3.9"
services:
localstack:
image: localstack/localstack
environment:
- SERVICES=s3,dynamodb,cloudformation,sts,ssm,iam,kms,lambda
- AWS_DEFAULT_REGION=ap-southeast-2
- DEBUG=1
ports:
- 4566:4566
This is just a basic configuration required to start Localstack. You can read more about how to use Docker-Compose to run Localstack in their website.
You might be asking why do we need all other services while we are only using S3 and DynamoDB.
Let's start the container!
docker compose up
Install cdklocal
With your basic setup is now done, let's get our hands dirty with cdklocal.
npm i -D aws-cdk-local
Similar with using AWS CDK in the actual cloud environment, you need to bootstrap your Localstack instance to start using CDK. Instead of using the actual CDK, we will use cdklocal
to interact with Localstack.
npx cdklocal bootstrap --custom-permissions-boundary localstack-development-policy
💡 You need to set --custom-permissions-boundary flag with the name of custom policy. I am not sure why we need this. Without this flag, it failed to bootstrap our localstack instance due to name validation error in the permission boundary. It seems cdklocal doesn't generate permission boundary propertly.
You are now bootstrapped to use cdk locally.
Finally, we can see the magic. Let's deploy our infrastructure to Localstack.
npx cdklocal deploy
Let's check our deployed resources.
aws s3 --endpoint-url http://localhost:4566
aws dynamodb --endpoint-url http://localhost:4566 describe-table --table-name your-dynamodb
Summary
I have used both AWS CDK and Localstack, and have really enjoyed the experience so far. By adding cdklocal into my toolbelt, it will improve my developer experience tremendously.
As developer, I would like to be able to test my code locally before I commit it to remote source control. This is no different when writing an infrastructure-as-a-code to build the infrastructure required for my application. Using cdklocal, I can easily deploy my CDK App into Localstack to enable faster feedback loop and easily setup integration testing with my application.
Everytime you make changes to your CDK App, redeploy it locally and test.
Over to you, will you use cdklocal as part of your development?
See you! 👋