Using LocalStack with Docker Compose to mock AWS services

Mauro
3 min readSep 19, 2023

I’m working on a serverless architecture, using some basic AWS services like SES (Simple Email Service), SQS (Simple Queue Service) and S3 buckets for file storage. I also use Docker Compose, which is the easiest way to define and spin up my whole environment’s project for local development.

In order to work with AWS services, I could just use the real AWS services with my account. But this comes with a few drawbacks, like speed, or having to set up the services per developer if you are working with other people. Speed is for me an important aspect specially when running tests (I tend to work mainly with integration tests).

Now the other option is to mock AWS services, and for that you can use LocalStack. It provides working APIs that mock AWS for many services that you can run locally, and it comes as a Docker container that you can just add in your docker compose environment.

1. Adding LocalStack to docker-compose.yml

Let me show you an example configuration:

version: '3.9'
services:
api: # This is your service
build:
...
environment:
# Set an env var to use later in the code
AWS_ENDPOINT: http://localstack:4566
localstack: # LocalStack container
image: localstack/localstack:latest
ports:
# Map the port so you can access the API from the host machine
- 4566:4566
volumes:
# Here you mount your setup file so it will be executed
# when the container starts
- ./localstack-setup.sh:/etc/localstack/init/ready.d/script.sh

2. Set up services

In order to set up services in LocalStack, you need to call the API/execute aws-cli commands as you would with the real AWS. To automate this process, you can write a bash script for that. This is an example of that localstack-setup.sh file:

#!/bin/sh
echo "Initializing localstack s3"

awslocal s3 mb s3://incircl
awslocal sqs create-queue --queue-name my-app-queue
awslocal ses verify-email-identity --email-address app@demo.com

As you see in the docker-compose.yml example, that file is mounted to /etc/localstack/init/ready.d/script.sh.LocalStack will execute it once the services are ready. In that example, I create an SQS queue and I also validate an email address so I can send emails using SES.

3. Configure AWS SDK

Once your setup is ready, you can start using it by configuring your AWS SDK when you are using a service. Let’s see how that looks for SES:

import { SES } from '@aws-sdk/client-ses'

protected ses: SES = new SES({ endpoint: process.env.AWS_ENDPOINT })

As you see, I’m using the environment variable AWS_ENDPOINT that I defined in the docker-compose.yml that points to the LocalStack service and its port. When running this on production, I leave that environment variable undefined, so it will use the real AWS service endpoint. You can do the same for every AWS service.

TIP: For getting the emails that were sent using SES, use Postman to make a GET request to http://localhost:4566/_localstack/ses

That’s it, now you can use (most) AWS services in your local development without needing to use the real AWS resources.

A caveat, while using the free version, nothing gets persisted. So for S3 files, if you stop and start again the container, the created files will be gone. But I think that for local development and testing, it’s not very important.

Check out my latest product: InCircl — An internal communications platform for medium/large organizations.

--

--