Skip to content
Get Started for Free
To improve reliability, we’ve moved to a single, authenticated LocalStack for AWS image that requires an auth token. For more details on plans and pricing, see our pricing page.

CircleCI

CircleCI is a continuous integration and continuous delivery (CI/CD) platform which uses a configuration file (usually named .circleci/config.yml) to define the build, test, and deployment workflows. This guide shows how to run LocalStack in CircleCI using the LocalStack Docker image and the LocalStack CLI.

version: '2.1'
orbs:
python: circleci/python@4.0.0
jobs:
localstack-test:
machine:
image: ubuntu-2204:current
steps:
- checkout
- run:
name: Install LocalStack CLI and awslocal
command: |
python3 -m pip install --user --upgrade pip
python3 -m pip install --user localstack awscli-local[ver1]
echo 'export PATH=$HOME/.local/bin:$PATH' >> "$BASH_ENV"
- run:
name: Start LocalStack
command: |
source "$BASH_ENV"
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
- run:
name: Test LocalStack
command: |
awslocal s3 mb s3://test-bucket
awslocal s3 ls
workflows:
localstack-test:
jobs:
- localstack-test
version: '2.1'
orbs:
python: circleci/python@4.0.0
jobs:
localstack-test:
machine:
image: ubuntu-2204:current
steps:
- checkout
- run:
name: Install LocalStack CLI and awslocal
command: |
python3 -m pip install --user --upgrade pip
python3 -m pip install --user localstack awscli-local[ver1]
echo 'export PATH=$HOME/.local/bin:$PATH' >> "$BASH_ENV"
- run:
name: Start LocalStack in background
command: |
source "$BASH_ENV"
docker pull localstack/localstack:latest
localstack start -d
- run:
name: Execute setup and tests
command: |
source "$BASH_ENV"
localstack wait -t 60
awslocal sqs create-queue --queue-name test-queue
awslocal sqs list-queues
workflows:
localstack-test:
jobs:
- localstack-test

To configure LocalStack use the environment key on the job level or a shell command, where the latter takes higher precedence.

Read more about the configuration options of LocalStack.

...
jobs:
localstack-test:
machine:
image: ubuntu-2204:current
environment:
DEBUG: 1
LS_LOG: trace
steps:
...
- run: localstack start -d
...
...
jobs:
localstack-test:
machine:
image: ubuntu-2204:current
steps:
- run:
name: Configure LocalStack
command: |
echo 'export DEBUG=1' >> "$BASH_ENV"
echo 'export LS_LOG=trace' >> "$BASH_ENV"
...

To enable LocalStack for AWS, you need to add your LocalStack CI Auth Token to the project’s environment variables. The LocalStack container will automatically pick it up and activate the licensed features.

Go to the CI Auth Token page and copy your CI Auth Token. To add the CI Auth Token to your CircleCI project, follow these steps:

  • Click on Project Settings.
  • Select Environment Variables from the left side menu.
  • Click Add Environment Variable.
  • Name your environment variable LOCALSTACK_AUTH_TOKEN.
  • Paste your CI Auth Token into the input field.

After adding the variable, CircleCI injects LOCALSTACK_AUTH_TOKEN into your job environment.

version: '2.1'
orbs:
python: circleci/python@4.0.0
jobs:
localstack-test:
machine:
image: ubuntu-2204:current
steps:
- checkout
- run:
name: Install LocalStack CLI and awslocal
command: |
python3 -m pip install --user --upgrade pip
python3 -m pip install --user localstack awscli-local[ver1]
echo 'export PATH=$HOME/.local/bin:$PATH' >> "$BASH_ENV"
- run:
name: Start LocalStack
command: |
source "$BASH_ENV"
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
- run:
name: Verify LocalStack setup
command: localstack logs | rg "activated|auth token|ready"
workflows:
localstack-test:
jobs:
- localstack-test
...
jobs:
localstack-test:
machine:
image: ubuntu-2204:current
steps:
...
- run:
name: Dump LocalStack logs
command: localstack logs | tee localstack.log
- store_artifacts:
path: localstack.log
name: localstack-logs
...

You can preserve your AWS infrastructure with LocalStack in various ways. To be able to use any of the below samples, you must set a valid CI Auth Token.

Note: For best result we recommend to use a combination of the below techniques, and you should familiarize yourself with CircleCI’s data persistence approach, see their official documentation.

Cloud Pods providing an easy solution to persist LocalStack’s state, even between workflows or projects.

Find more information about Cloud Pods.

Update or create the Cloud Pod in it’s own project (ie in a separate Infrastructure as Code repo), this would create a base Cloud Pod, which you can use in the future without any configuration or deployment.

Note: If there is a previously created Cloud Pod which doesn’t need updating this step can be skipped.

...
jobs:
localstack-update-cloud-pod:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
- run:
name: Load state if exists
command: localstack pod load <POD_NAME> || true
...
# Deploy infrastructure changes
...
- run:
name: Save Cloud Pod
command: localstack pod save <POD_NAME>
workflows:
localstack-build:
jobs:
- localstack-update-cloud-pod

In a separate project use the previously created base Cloud Pod as below:

...
jobs:
localstack-use-cloud-pod:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
- run:
name: Load Cloud Pod
command: localstack pod load <POD_NAME>
...
# Run some tests
workflows:
localstack-build:
jobs:
- localstack-use-cloud-pod

To use a dynamically updated Cloud Pod in multiple workflows but in the same project, you must eliminate the race conditions between the update workflow and the others.

Before you are able to use any stored artifacts in your pipeline, you must provide either a valid project API token or a personal API token to CircleCI.

...
parameters:
run_workflow_build:
default: true
type: boolean
run_workflow_test1:
default: false
type: boolean
run_workflow_test2:
default: false
type: boolean
...
jobs:
localstack-update-state:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
- run:
name: Load Cloud Pod
command: localstack pod load <POD_NAME> || true
...
# Deploy infrastructure
...
- run:
name: Save Cloud Pod
command: localstack pod save <POD_NAME>
- run:
name: Trigger other workflows
# Replace placeholders with right values
command: |
curl --request POST \
--url https://circleci.com/api/v2/project/<vcs-slug>/<org-name>/<repo-name>/pipeline
--header 'Circle-Token: $CIRCLECI_TOKEN' \
--header 'content-type: application/json' \
--data '{"parameters":{"run_workflow_build":false, "run_workflow_test1":true, "run_workflow_test2":true}}'
localstack-use-state:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
- run:
name: Load state if exists
command: localstack pod load <POD_NAME> || true
...
# Example workflows
workflows:
localstack-build:
when: << pipeline.parameters.run_workflow_build >>
jobs:
- localstack-update-state
localstack-test1:
when: << pipeline.parameters.run_workflow_test1 >>
- localstack-use-state
...
localstack-test2:
when: << pipeline.parameters.run_workflow_test2 >>
jobs:
- localstack-use-state
...

Find out more about Ephemeral Instances.

...
jobs:
do-work:
machine:
image: ubuntu-2204:current
steps:
- run:
name: Create Ephemeral Instance
command: |
response=$(curl -X POST \
-H "ls-api-key: $LOCALSTACK_AUTH_TOKEN" \
-H "authorization: token $LOCALSTACK_AUTH_TOKEN" \
-H "content-type: application/json" \
-d '{"auto_load_pod":"false"}' \
https://api.localstack.cloud/v1/previews/my-circleci-state)
endpoint_url=$(echo "$response" | jq -r '.endpointUrl')
if [ -z "$endpoint_url" ] || [ "$endpoint_url" = "null" ]; then
echo "Unable to create preview environment. API response: $response"
exit 1
fi
echo "export AWS_ENDPOINT_URL=$endpoint_url" >> "$BASH_ENV"
- run:
name: Output the ephemeral instance address
command: echo "$AWS_ENDPOINT_URL"
...
workflows:
use-ephemeral-instance:
jobs:
- do-work
...
...
jobs:
setup-instance:
machine:
image: ubuntu-2204:current
steps:
- run:
name: Create Ephemeral Instance
command: |
response=$(curl -X POST \
-H "ls-api-key: $LOCALSTACK_AUTH_TOKEN" \
-H "authorization: token $LOCALSTACK_AUTH_TOKEN" \
-H "content-type: application/json" \
-d '{"auto_load_pod":"false"}' \
https://api.localstack.cloud/v1/previews/my-circleci-state)
endpoint_url=$(echo "$response" | jq -r '.endpointUrl')
if [ -z "$endpoint_url" ] || [ "$endpoint_url" = "null" ]; then
echo "Unable to create preview environment. API response: $response"
exit 1
fi
echo "export AWS_ENDPOINT_URL=$endpoint_url" >> ls-env-vars
- run:
name: Persist AWS Endpoint URL
command: cat ls-env-vars
- persist_to_workspace:
root: .
paths:
- ls-env-vars
run-test:
machine:
image: ubuntu-2204:current
steps:
- attach_workspace:
at: .
- run:
name: Set up LS env variables
command: cat ./ls-env-vars >> $BASH_ENV
- run:
name: Output the ephemeral instance address
command: echo "$AWS_ENDPOINT_URL"
...
# Run any logic against the Ephemeral Instance,
# then stop when not needed anymore
- run:
name: Stop Ephemeral Instance
command: |
# Replace <PREVIEW_ID> with the id returned by the API in setup-instance.
curl -X DELETE \
-H "ls-api-key: $LOCALSTACK_AUTH_TOKEN" \
-H "authorization: token $LOCALSTACK_AUTH_TOKEN" \
https://api.localstack.cloud/v1/previews/<PREVIEW_ID>
...
workflows:
use-ephemeral-instance:
jobs:
- setup-instance
- run-test
...

This strategy persist LocalStack’s state between jobs for the current workflow.

...
jobs:
localstack-save-state:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
# LocalStack already running and deployed infrastructure
- run:
name: Export state
command: localstack state export ls-state.zip
- persist_to_workspace:
paths:
- ls-state.zip
# Store state as artifact for local debugging
- store_artifact:
key: ls-state
paths: ls-state.zip
...
localstack-load-state:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
# LocalStack already running
- attach_workspace:
at: .
- run:
name: Import state
command: |
test -f ls-state.zip && localstack state import ls-state.zip
...
workflows:
localstack-build:
jobs:
- localstack-save-state
- localstack-load-state

More information about Localstack’s state import/export.

To preserve state between workflow runs, you can take leverage of CircleCI’s caching too. This strategy will persist LocalStack’s state for every workflow re-runs, but not for different workflows.

...
jobs:
localstack-update-state:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
...
# LocalStack already running
# Let's restore previous workflow run's LocalStack state
- restore_cache:
# Use latest "ls-state" prefixed cache
key: ls-state-
- run:
name: Import state
command: test -f ls-state.zip && localstack state import ls-state.zip
...
# Infrastructure had been updated
# Let's update cached LocalStack state
- run:
name: Export state
command: localstack state export ls-state.zip
- save_cache:
key: ls-state-{{checksum ls-state.zip}}
paths: ls-state.zip
...
localstack-do-work:
machine:
image: ubuntu-2204:current
steps:
- run: python3 -m pip install localstack awscli-local[ver1]
- run: |
docker pull localstack/localstack:latest
localstack start -d
localstack wait -t 60
# LocalStack already running
- restore_cache:
# Use latest "ls-state" prefixed cache
key: ls-state-
- run:
name: Import state
command: test -f ls-state.zip && localstack state import ls-state.zip
...
# Example workflows
workflows:
localstack-build:
jobs:
- localstack-update-state
- localstack-do-work
...

More information about state management.

Was this page helpful?