SAM Local with Localstack
Tags: sam, localstack
Published: 2020-03-19 16:00:08

As a developer, I look for making local dev experience as smooth as possible. In the same vein, one thing that bothers most of us working with aws cloud is to test it locally. Good thing is that we have [localstack](https://github.com/localstack/localstack) to our rescue. This post will focus on how you can have AWS SAM working with Localstack.

## Table Of Contents
* [Tools](#tools)
* [Project Setup](#project-setup)
* [Setting up Localstack](#localstack)
* [Hooking it up](#hooking)

### Tools <a name="tools"></a>
* NodeJs 12.x
* Docker
* [aws-cli](https://aws.amazon.com/cli/)
* [awscli-local](https://github.com/localstack/awscli-local)

### Project Setup <a name="project-setup"></a>
For this post, we will use `sam init` to pull in the hello-world project with nodejs runtime. More information on [SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html). After following the prompts, you will get a sample hello world project setup running in node.

### Setting up Localstack <a name="localstack"></a>
In order to setup localstack in the project, we will first create a docker-compose.yml in the root of our project.
```yml
version: "3"
services:
  localstack:
    build: localstack
    container_name: localstack
    environment:
      - DATA_DIR=/tmp/localstack/data
      - SERVICES=s3 # this can be a comma separated list of services you want to start
      - TZ=America/New_York
    ports:
      - '4572:4572' # these ports will be different for different services.
```

Another thing that we will need to do is create a directory called `localstack` with following contents, 
```
.dockerignore
Dockerfile
recorded_api_calls.json
```
Let's see what each of these files will look like, `.dockerignore`
```
.dockerignore
Dockerfile
```

`Docekrfile`
```
FROM localstack/localstack

COPY /. /tmp/localstack/data
```
We will get to the contents of the json file later. Once we have this, we are ready to start the localstack in a docker container. You can do this by running,
`docker-compose up -d`. This will pull the localstack image and build it and start it.

#### S3 bucket
Now we will need to create a s3 bucket in our localstack container. For this we can just run this: `awslocal s3 mb s3://test-bucket`. This will create the bucket. Now bash into the container, `docker exec -it localstack /bin/bash` and then go to `vi /tmp/localstack/data/recorded_api_calls.json`. Copy the contents of this file and paste them in the file `recorded_api_calls.json` in the `localstack` directory we created earlier. We need to do this, so that we don't need to create the bucket every time we start the container.

### Hooking it up <a name="hooking"></a>
Now if you want to setup your project to use any AWS components like S3, IAM, STS etc. you can do so and test them without going to AWS directly.

In the code, you will need aws-sdk to initialize the s3 client, you can do this by,
```javascript
const s3 = AWS.S3({ endpoint: 'http://localhost:4572' });
```

Coming back to make `sam local invoke` work with localstack. For this, bare minimum you would need to do this:
```
sam local invoke --docker-network host
```
For more information on [sam local](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html)

Full working code can be found here: {% github vikasgarghb/sam-local-with-localstack %}