Skip to content

Local Setup

Cameron Pettit edited this page Mar 14, 2025 · 4 revisions

Local Setup with AWS CDK

This project uses AWS CDK to package and deploy code infrastructure.

After cloning this repository into the directory of choosing, ensure the the following are installed:

Quick Overview

Note: a handful of environment variables must be properly configured before running this API locally. Please review the environment setup instructions before running the API for the first time. To ensure the API will run with the proper offline configuration, set the env var IS_OFFLINE='true'.

export IS_OFFLINE='true'

Local API deployments can be run by constructing CDK assets, generating a SAM template file, and running sam local start-api against the generated template, which spins up the API within a Docker container.

With CDK, the entry point is the app file bin/reserve-rec-cdk.js. Generally, environment variables are declared for all CDK constructs here. The app file declares a stack generated from the stack file, lib/reserve-rec-cdk-stack.js. The stack file is the root for the setup of all CDK constructs within the stack.

When CDK assets are generated (by running cdk synth, for example), the generated code is output into the cdk-out directory, alongside a generated AWS SAM template ReserveRecCdkStack.template.json.

cdk synth

A local API can be spun up using this SAM template ReserveRecCdkStack.template.json and the SAM local start-api command:

sam local start-api -t ./cdk.out/ReserveRecCdkStack.template.json

Environment setup

When running the API locally, there are two environments to consider:

  • The local environment where the repository is stored. This is the environment CDK will use to generate CDK assets.
  • The Docker-contained environment that is created when running SAM with the generated template file. This is the environment the local API will operate in.

Environment variables that are used in the construction of CDK assets (ie: running cdk synth) can be stored in the local environment. They will be available in CDK code under process.env, but a cleaner way of suppling environment variables to stack constructs is by appending them to the existing env property in the app file, which is then passed to the stack.

new  ReserveRecCdkStack(app, 'ReserveRecCdkStack', {
	env: {
		// AWS account variables
		account:  process.env.CDK_DEFAULT_ACCOUNT,
		region:  process.env.CDK_DEFAULT_REGION,
		// List custom environment variables here
		IS_OFFLINE = process.env.IS_OFFLINE || 'false'
		myVar: process.env.MY_VAR || 'Default value',
		// ...
	}
});

These variables are available within the stack file as props.env.

Remember to set the environment variable IS_OFFLINE='true' if constructing and deploying the API locally. If this is not set, local environment variables in process.env will not be passed to the stack.

Importantly, your local environment variables will not be copied into the Docker container when you run the API locally, and therefore CDK-generated assets within the API will not have access to your local environment variables at runtime.

Environment variables that are used by CDK-generated constructs at runtime must be stored in env.json. These variables will be injected into the Docker container on API startup. These variables typically consist of values that are automatically generated and populated when deploying to a remote stack, but may require changes when running the API locally with SAM. For example, remote stacks are automatically configured to look for DynamoDB tables at the remote endpoint http://dynamodb.<AWS_REGION>.amazonaws.com, but when running locally, it may be preferred to point to a local DynamoDB server hosted at http://localhost:8000.

Edit env.json with any environment variables that will be consumed by your CDK-generated constructs at runtime.

{
	"Parameters": {
		"TABLE_NAME": "local-dynamodb-main-table-name" // Name of the target main DynamoDB table
		"AWS_REGION": "local-env" // AWS Region (only important if targeting a remote stack)
		"DYNAMODB_ENDPOINT_URL": "http://localhost:8000" // Location of DynamoDB instance
		"OPENSEARCH_DOMAIN_URL": "http://localhost:9200" // Location of OpenSearch instance
		"OPENSEARCH_MAIN_INDEX": "main-index-name" // Name of the target OpenSearch main index
		...
	}
}

For local deployments, it is advised to set up local DynamoDB and OpenSearch instances for your local CDK constructs to target, but env.json can also be configured to target remote instances in deployed stacks.

Deploy the API Locally with custom environment variables contained within env.json

sam local start-api -t ./cdk.out/ReserveRecCdkStack.template.json --env-vars env.json

Other arguments for deploying SAM API locally

sam local start-api -t ./cdk.out/ReserveRecCdkStack.template.json --env-vars env.json --warm-containers LAZY --skip-pull-image 2>&1 | tr '\r' '\n'
  • sam local start-api - Start the API locally
  • -t ./cdk.out/ReserveRecCdkStack.template.json - Look for the SAM template at this location
  • --env-vars env.json - Include the variables in env.json in the Docker containers that will run the API
  • --warm-containers LAZY - Only spin up Lambda Docker containers when the Lambda is invoked. This saves time by not deploying the whole API, but it does increase response time for the first call to each Lambda.
  • --skip-pull-image - Don't pull down the latest Docker image for the Lambda runtime. Saves time but sam local start-api must be run at least once without this argument to ensure a Docker image is downloaded, or to check/upgrade the Lambda runtime.
  • 2>&1 | tr '\r' '\n' - Lambda output formatting to be human-readable in a terminal window.

Invoke a single Lambda locally

To test Lambdas that will not be triggered by an API endpoint, they can be invoked locally using a similar tactic to local deployments with SAM.

sam local invoke <function-name> // OR
sam local invoke <function-name> --no-event -t ./cdk.out/ReserveRecCdkStack.template.json --env-vars env.json
  • --no-event - No event data from the trigger that invoked the lambda
  • --event event.json - Use event.json as a JSON file including information that will be passed into the Lambda as the event.

Using Yarn shortforms

Some yarn scripts have been included to combine frequently used commands:

yarn command script
yarn start `sam local start-api -t ./cdk.out/ReserveRecCdkStack.template.json --env-vars env.json --warm-containers LAZY --skip-pull-image 2>&1
yarn build cdk synth
yarn start-full yarn build && yarn start
yarn invoke-lambda <functionName> sam local invoke <functionName> --no-event -t ./cdk.out/ReserveRecCdkStack.template.json --env-vars env.json
yarn invoke-lambda-full <functionName> yarn build && yarn invoke-lambda <functionName>

Clone this wiki locally