From b17a57b3dd5ba6783fbc6d09bf47dc1934de5085 Mon Sep 17 00:00:00 2001 From: Brian Rinaldi Date: Fri, 24 Apr 2026 14:06:47 -0400 Subject: [PATCH 1/4] Initial draft for revising getting started The concepts behind this draft: 1. Design paths for the main LocalStack use cases 2. Simplify the quickstart to get them to success faster 3. Have both an awslocal and a terraform quickstart 4. Bring AI and agent use cases up front [DOC-12](https://linear.app/localstack/issue/DOC-12/docs-quickstart-v2) --- .../docs/aws/getting-started/ai-workflows.mdx | 73 +++ .../docs/aws/getting-started/auth-token.mdx | 2 +- .../docs/aws/getting-started/ci-cd.mdx | 185 +++++++ src/content/docs/aws/getting-started/faq.mdx | 2 +- .../docs/aws/getting-started/help-support.md | 2 +- src/content/docs/aws/getting-started/index.md | 23 - .../docs/aws/getting-started/index.mdx | 48 ++ .../docs/aws/getting-started/installation.mdx | 85 ++- .../docs/aws/getting-started/quickstart.mdx | 501 ++++++++---------- 9 files changed, 588 insertions(+), 333 deletions(-) create mode 100644 src/content/docs/aws/getting-started/ai-workflows.mdx create mode 100644 src/content/docs/aws/getting-started/ci-cd.mdx delete mode 100644 src/content/docs/aws/getting-started/index.md create mode 100644 src/content/docs/aws/getting-started/index.mdx diff --git a/src/content/docs/aws/getting-started/ai-workflows.mdx b/src/content/docs/aws/getting-started/ai-workflows.mdx new file mode 100644 index 00000000..4746e4ff --- /dev/null +++ b/src/content/docs/aws/getting-started/ai-workflows.mdx @@ -0,0 +1,73 @@ +--- +title: AI & Agent Workflows +description: Use LocalStack with AI coding assistants, MCP servers, and agent-driven infrastructure automation. +template: doc +sidebar: + order: 6 +--- + +## Overview + +LocalStack is a natural fit for AI-assisted development workflows. +Whether you're using an AI coding assistant to generate infrastructure code, running an agent that deploys AWS resources, or validating AI-generated Terraform before applying it to real AWS — LocalStack gives you a safe, fast, cost-free environment to do it in. + +## Connect an AI coding assistant via MCP + +The [LocalStack MCP Server](https://github.com/localstack/localstack-mcp-server) exposes LocalStack's API as an MCP (Model Context Protocol) tool server. +This lets AI assistants like Claude, Cursor, Windsurf, or any MCP-compatible tool inspect and interact with your running LocalStack instance directly. + +With the MCP server connected, your AI assistant can: + +- List running AWS services and deployed resources +- Create, update, and delete resources in your local environment +- Query resource state to understand what's already deployed +- Help you debug issues by inspecting live infrastructure + +**Quick setup:** + +```bash +# Install the LocalStack MCP server +pip install localstack-mcp-server +``` + +Then add it to your AI tool's MCP configuration. +See the [localstack-mcp-server README](https://github.com/localstack/localstack-mcp-server) for tool-specific setup instructions for Claude, Cursor, and others. + +:::note +The MCP server connects to a running LocalStack instance — make sure LocalStack is started first with `lstk start` or `localstack start`. +::: + +## Deploy with agent-driven automation using Skills + +[LocalStack Skills](https://github.com/localstack/skills) are pre-built agent skill definitions for deploying common AWS architectures locally. +Instead of stepping through manual CLI commands, you describe what you want and an agent handles the deployment. + +Skills are useful when: + +- You want to scaffold a new local environment quickly without writing all the infrastructure code yourself +- You're using an agent-first workflow and want LocalStack to be a first-class deployment target +- You want to iterate rapidly on architecture without touching real AWS + +Browse the [skills repository](https://github.com/localstack/skills) for available skills and setup instructions. + +## Validate AI-generated IaC before applying to AWS + +A common pattern when using AI to generate Terraform, CDK, or CloudFormation is to deploy it to LocalStack first. +This catches configuration errors, missing permissions, and service interaction bugs before you spend time (and money) deploying to real AWS. + +The workflow is: + +1. Generate infrastructure code with your AI tool +2. Deploy to LocalStack with `tflocal apply` (Terraform), `cdklocal deploy` (CDK), or the AWS CLI +3. Run your integration tests against the local environment +4. When everything passes, deploy to real AWS with confidence + +See [Tooling](/aws/tooling/) for the full list of LocalStack-aware wrappers for common IaC tools. + +## Summary + +| Use case | Tool | +|---|---| +| AI assistant that can inspect & manage local resources | [LocalStack MCP Server](https://github.com/localstack/localstack-mcp-server) | +| Agent-driven infrastructure deployment | [LocalStack Skills](https://github.com/localstack/skills) | +| Validate AI-generated IaC safely | LocalStack + `tflocal` / `cdklocal` / `awslocal` | diff --git a/src/content/docs/aws/getting-started/auth-token.mdx b/src/content/docs/aws/getting-started/auth-token.mdx index b71c45a1..4f6446c0 100644 --- a/src/content/docs/aws/getting-started/auth-token.mdx +++ b/src/content/docs/aws/getting-started/auth-token.mdx @@ -3,7 +3,7 @@ title: Auth Token description: Configure your Auth Token to access and activate LocalStack. template: doc sidebar: - order: 3 + order: 4 --- import { Code, Tabs, TabItem } from '@astrojs/starlight/components'; diff --git a/src/content/docs/aws/getting-started/ci-cd.mdx b/src/content/docs/aws/getting-started/ci-cd.mdx new file mode 100644 index 00000000..feac5951 --- /dev/null +++ b/src/content/docs/aws/getting-started/ci-cd.mdx @@ -0,0 +1,185 @@ +--- +title: CI/CD Setup +description: Run LocalStack in CI pipelines — auth tokens, Docker Compose, and GitHub Actions examples. +template: doc +sidebar: + order: 5 +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +## Overview + +LocalStack works great in CI environments. +The setup differs from local development in a few important ways: + +- **Use a CI Auth Token**, not your personal Developer token +- **Manage the container directly** via Docker Compose or `docker run` — `lstk` and the LocalStack Desktop are local-only tools +- **LocalStack is ephemeral by default** — each CI run starts fresh, which is usually exactly what you want for reproducible tests + +## Step 1 — Get a CI Auth Token + +CI pipelines should use a dedicated CI Auth Token, not a Developer token tied to a specific user. + +1. Go to the [Auth Tokens page](https://app.localstack.cloud/workspace/auth-tokens) in the LocalStack Web Application +2. Create a new **CI Auth Token** +3. Add it as a secret in your CI provider (e.g., `LOCALSTACK_AUTH_TOKEN`) + +:::danger[Keep your token secret] +Never commit an auth token to source control. +Always inject it via your CI provider's secrets or environment variable mechanism. +If a token is compromised, rotate it immediately on the Auth Tokens page — old tokens are invalidated instantly. +::: + +See the [Auth Token documentation](/aws/getting-started/auth-token/) for full details on token types and configuration. + +## Step 2 — Start LocalStack in CI + + + + The recommended approach is to start LocalStack as a service container or as a step using the official GitHub Action: + + ```yaml + # .github/workflows/integration-tests.yml + name: Integration Tests + + on: [push, pull_request] + + jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Start LocalStack + uses: LocalStack/setup-localstack@v0.2 + with: + image-tag: latest + env: + LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} + + - name: Run tests + run: | + # Your test commands here, e.g.: + pip install awscli-local + awslocal s3 mb s3://my-test-bucket + pytest tests/integration/ + ``` + + The `setup-localstack` action handles pulling the image, starting the container, and waiting for LocalStack to be ready. + + + Add LocalStack as a service in your `docker-compose.yml`: + + ```yaml + services: + localstack: + container_name: localstack-main + image: localstack/localstack-pro + ports: + - "127.0.0.1:4566:4566" + - "127.0.0.1:4510-4559:4510-4559" + - "127.0.0.1:443:443" + environment: + - LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?} + - DEBUG=${DEBUG:-0} + volumes: + - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" + - "/var/run/docker.sock:/var/run/docker.sock" + ``` + + Start it and wait for readiness: + + ```bash + docker compose up -d localstack + # Wait for LocalStack to be ready + until curl -s http://localhost:4566/_localstack/health | grep -q '"running"'; do sleep 1; done + ``` + + :::note + Mounting `/var/run/docker.sock` is required for Lambda emulation, which uses Docker to run function containers. + ::: + + + Start LocalStack directly with `docker run`: + + ```bash + docker run \ + --rm -d \ + --name localstack-main \ + -p 127.0.0.1:4566:4566 \ + -p 127.0.0.1:4510-4559:4510-4559 \ + -e LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?} \ + -v /var/run/docker.sock:/var/run/docker.sock \ + localstack/localstack-pro + + # Wait for readiness + until curl -s http://localhost:4566/_localstack/health | grep -q '"running"'; do sleep 1; done + ``` + + + Add LocalStack as a service in your CircleCI config: + + ```yaml + version: 2.1 + + jobs: + integration-tests: + docker: + - image: cimg/python:3.12 + - image: localstack/localstack-pro + environment: + LOCALSTACK_AUTH_TOKEN: $LOCALSTACK_AUTH_TOKEN + steps: + - checkout + - run: + name: Wait for LocalStack + command: | + until curl -s http://localhost:4566/_localstack/health | grep -q '"running"'; do sleep 1; done + - run: + name: Run tests + command: pytest tests/integration/ + ``` + + Set `LOCALSTACK_AUTH_TOKEN` in your CircleCI project's environment variables. + + + +## Verify activation + +After LocalStack starts, confirm the license is active: + +```bash +curl -s http://localhost:4566/_localstack/info | jq '.is_license_activated' +# Should return: true +``` + +## Key differences from local development + +| | Local development | CI/CD | +|---|---|---| +| **CLI** | `lstk` or LocalStack CLI | Docker Compose / `docker run` | +| **Auth** | Browser login or stored token | `LOCALSTACK_AUTH_TOKEN` env var | +| **Token type** | Developer token | CI token | +| **State** | Optional persistence | Ephemeral (fresh per run) | +| **Startup** | Interactive TUI | `--non-interactive` / `-d` flag | + +## Persisting state across runs + +By default, LocalStack starts fresh on every run — all resources are gone when the container stops. +This is ideal for most CI use cases (clean, reproducible tests). + +If you need to share state across runs (e.g., seed data, pre-built infrastructure), look at [Cloud Pods](/aws/capabilities/state-management/cloud-pods/), which let you snapshot and restore LocalStack state. + +## More CI integrations + +LocalStack has dedicated integration guides for many CI providers: + +- [GitHub Actions](/aws/integrations/continuous-integration/github-actions/) +- [GitLab CI](/aws/integrations/continuous-integration/gitlab-ci/) +- [CircleCI](/aws/integrations/continuous-integration/circleci/) +- [AWS CodeBuild](/aws/integrations/continuous-integration/codebuild/) +- [Travis CI](/aws/integrations/continuous-integration/travis-ci/) +- [Bitbucket Pipelines](/aws/integrations/continuous-integration/bitbucket/) + +See the full [CI/CD integrations](/aws/integrations/continuous-integration/) section for details. diff --git a/src/content/docs/aws/getting-started/faq.mdx b/src/content/docs/aws/getting-started/faq.mdx index 12128b64..3eded1df 100644 --- a/src/content/docs/aws/getting-started/faq.mdx +++ b/src/content/docs/aws/getting-started/faq.mdx @@ -3,7 +3,7 @@ title: FAQ description: Frequently asked questions about LocalStack for AWS. template: doc sidebar: - order: 5 + order: 7 --- import { Tabs, TabItem } from '@astrojs/starlight/components'; diff --git a/src/content/docs/aws/getting-started/help-support.md b/src/content/docs/aws/getting-started/help-support.md index c6641003..d2dde0db 100644 --- a/src/content/docs/aws/getting-started/help-support.md +++ b/src/content/docs/aws/getting-started/help-support.md @@ -3,7 +3,7 @@ title: Help & Support description: Get help and support with LocalStack. template: doc sidebar: - order: 6 + order: 8 --- ## Introduction diff --git a/src/content/docs/aws/getting-started/index.md b/src/content/docs/aws/getting-started/index.md deleted file mode 100644 index 017debdb..00000000 --- a/src/content/docs/aws/getting-started/index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Overview -description: This section describes how to get started with LocalStack using a variety of options, and provides details on how LocalStack can be configured to fit the needs of a local cloud sandbox for development, testing, and experimentation. -template: doc -editUrl: false -sidebar: - order: 1 ---- - -[LocalStack](https://localstack.cloud) is a cloud service emulator that runs in a single container on your laptop or in your CI environment. -With LocalStack, you can run your AWS applications or Lambdas entirely on your local machine without connecting to a remote cloud provider! - -Whether you are testing complex CDK applications or Terraform configurations, or just beginning to learn about AWS services, LocalStack helps speed up and simplify your testing and development workflow. - -LocalStack supports a growing number of [AWS services](/aws/services/) -, like [Lambda](/aws/services/lambda), [S3](/aws/services/s3), [DynamoDB](/aws/services/dynamodb), [Kinesis](/aws/services/kinesis), [SQS](/aws/services/sqs), [SNS](/aws/services/sns), and more! -[LocalStack for AWS](https://localstack.cloud/pricing) also supports APIs and advanced features to make your cloud development experience a breeze. - -You can find a comprehensive list of supported APIs on each AWS service page. - -LocalStack also provides additional features to make your life as a cloud developer easier! - -Check out LocalStack's [Cloud Developer Tools](/aws/tooling/). diff --git a/src/content/docs/aws/getting-started/index.mdx b/src/content/docs/aws/getting-started/index.mdx new file mode 100644 index 00000000..4b0e2503 --- /dev/null +++ b/src/content/docs/aws/getting-started/index.mdx @@ -0,0 +1,48 @@ +--- +title: Overview +description: This section describes how to get started with LocalStack for AWS using a variety of options, and provides details on how LocalStack can be configured to fit the needs of a local cloud sandbox for development, testing, and experimentation. +template: doc +editUrl: false +sidebar: + order: 1 +--- + +import { SectionCards } from '../../../../components/SectionCards.tsx'; + +[LocalStack for AWS](https://localstack.cloud) is a cloud service emulator that runs in a single container on your laptop or in your CI environment. +It gives you a fully functional AWS environment — Lambda, DynamoDB, S3, SQS, and [80+ more services](/aws/services/) — without touching a real AWS account and without incurring cloud costs. + +Here's why developers and teams use it: + +- **Faster development loops** — Test changes against local AWS services instantly, without waiting on real deployments or worrying about cloud costs. +- **Integration testing in CI** — Run real integration tests against local AWS infrastructure in every pull request, catching bugs before they reach production. +- **Validate IaC before applying** — Deploy your Terraform, CDK, or CloudFormation to LocalStack first. Confirm it works the way you expect before applying to a real AWS environment. +- **Safe experimentation** — Explore new AWS services and architectures freely, with no risk to production systems. + +LocalStack for AWS also includes advanced capabilities for teams: [Cloud Pods](/aws/capabilities/state-management/cloud-pods/) for sharing and restoring state, [IAM policy enforcement](/aws/capabilities/security-testing/iam-policy-enforcement/), [Chaos Engineering](/aws/capabilities/chaos-engineering/), and more. + +## Choose your path + + diff --git a/src/content/docs/aws/getting-started/installation.mdx b/src/content/docs/aws/getting-started/installation.mdx index 4e76ecba..dcc080ab 100644 --- a/src/content/docs/aws/getting-started/installation.mdx +++ b/src/content/docs/aws/getting-started/installation.mdx @@ -1,24 +1,68 @@ --- title: Installation -description: Basic installation guide to get started with LocalStack on your local machine. +description: All installation methods for LocalStack — lstk, LocalStack CLI, Docker Compose, Docker, and Helm. template: doc sidebar: - order: 2 + order: 3 --- import { Code, LinkButton, Tabs, TabItem } from '@astrojs/starlight/components'; import { LOCALSTACK_VERSION } from "astro:env/server"; -## LocalStack CLI +## Local development -The quickest way get started with LocalStack is by using the LocalStack CLI. -It allows you to start LocalStack from your command line. +There are two CLI options for running LocalStack on your laptop. Start with `lstk` if you want the fastest path to a running instance, or use the LocalStack CLI if you need full feature support. + +### lstk + +`lstk` is a lightweight, Go-based CLI that handles the full startup sequence in one command: browser-based login, image pull, and container launch. +It's the fastest way to get LocalStack running locally. + +:::caution[Early release] +`lstk` currently supports core lifecycle commands (`start`, `stop`, `logs`, `status`). +For advanced features like Cloud Pods, Extensions, and Ephemeral Instances, use the [LocalStack CLI](#localstack-cli) instead. +Both tools can coexist on the same system. +::: + +Install `lstk`: + + + + ```bash + brew install localstack/tap/lstk + ``` + + + ```bash + npm install -g @localstack/lstk + ``` + + + Download a pre-built binary for your platform from [GitHub Releases](https://github.com/localstack/lstk/releases) and add it to your `PATH`. + + + +Start LocalStack: + +```bash +lstk start +``` + +On first run, `lstk` opens a browser login flow. +After authenticating, it pulls the LocalStack image and starts the container. +Subsequent starts use the stored credential from your system keyring — no manual token management needed. + +--- + +### LocalStack CLI + +The full-featured LocalStack CLI gives you access to all LocalStack capabilities. Please make sure that you have a working [Docker installation](https://docs.docker.com/get-docker/) on your machine before moving on. ### Installing LocalStack CLI The CLI starts and manages the LocalStack Docker container. -For alternative methods of managing the LocalStack container, see our [alternative installation instructions](#alternatives). +For alternative methods of managing the LocalStack container, see our [alternative installation instructions](#ci-and-server-environments). @@ -196,30 +240,25 @@ Updating the LocalStack CLI using `localstack update localstack-cli` and `locals If it was installed using the pre-built binary or via Brew, please run the installation steps again to update to the latest version. ::: -## Alternatives - -Besides using the CLI, there are other ways of starting and managing your LocalStack instance: - -- [LocalStack Desktop](#localstack-desktop)\ - Get a desktop experience and work with your local LocalStack instance via the UI. +## CI and server environments -- [LocalStack Docker Extension](#localstack-docker-extension)\ - Use the LocalStack extension for Docker Desktop to work with your LocalStack instance. +For CI pipelines and server deployments, you'll manage the LocalStack container directly rather than using a local CLI. +See the [CI/CD Setup guide](/aws/getting-started/ci-cd/) for a complete walkthrough including GitHub Actions examples. -- [Docker-Compose](#docker-compose)\ - Use Docker Compose to configure and start your LocalStack Docker container. +The options below cover the main container management approaches: -- [Docker](#docker)\ - Use the Docker CLI to manually start the LocalStack Docker container. +- [Docker Compose](#docker-compose) — recommended for CI and team environments +- [Docker](#docker) — direct container control for scripted setups +- [Helm](#helm) — deploy LocalStack in a Kubernetes cluster -- [Helm](#helm)\ - Use Helm to create a LocalStack deployment in a Kubernetes cluster. +The LocalStack emulator is available on Docker Hub as `localstack/localstack-pro`. -LocalStack runs inside a Docker container, and the above options are different ways to start and manage the LocalStack Docker container. +For a comprehensive overview of LocalStack images, see the [Docker images documentation](/aws/capabilities/config/docker-images). -The LocalStack emulator is available on Docker Hub (`localstack/localstack-pro`). +## GUI tools -For a comprehensive overview of the LocalStack images, check out our [Docker images documentation](/aws/capabilities/config/docker-images). +- [LocalStack Desktop](#localstack-desktop) — desktop UI for managing your local instance +- [LocalStack Docker Extension](#localstack-docker-extension) — manage LocalStack from Docker Desktop ### LocalStack Desktop diff --git a/src/content/docs/aws/getting-started/quickstart.mdx b/src/content/docs/aws/getting-started/quickstart.mdx index 7774291f..f4444269 100644 --- a/src/content/docs/aws/getting-started/quickstart.mdx +++ b/src/content/docs/aws/getting-started/quickstart.mdx @@ -1,361 +1,294 @@ --- title: Quickstart -description: How to run an AWS application on your local machine and test local cloud development with LocalStack. +description: Deploy a serverless API locally with LocalStack in under 10 minutes using Lambda and DynamoDB. template: doc sidebar: - order: 4 + order: 2 --- -import { Code, LinkButton, Tabs, TabItem } from '@astrojs/starlight/components'; +import { Tabs, TabItem } from '@astrojs/starlight/components'; ## Introduction -In this quickstart guide, we'll walk you through the process of starting LocalStack on your local machine and deploying a [serverless image resizer application](https://github.com/localstack-samples/sample-serverless-image-resizer-s3-lambda) that utilizes several AWS services. -This guide aims to help you understand how to use LocalStack for the development and testing of your AWS applications locally. -It introduces you to the following key concepts: +In this quickstart you'll start LocalStack and deploy a simple serverless API — a **Lambda function backed by DynamoDB** — entirely on your local machine. +No AWS account needed. -- Starting a LocalStack instance on your local machine. -- Deploying an AWS serverless application infrastructure locally. -- Running an automated integration test suite against local infrastructure. -- Exploring the LocalStack Web Application to view deployed resources. -- Destroying the local infrastructure you have provisioned. +By the end you will have: -## Architecture +- LocalStack running locally in Docker +- A Lambda function deployed and invokable via a public URL +- A DynamoDB table storing data written by the Lambda +- Confirmed that your local environment behaves like real AWS -The following diagram shows the architecture that we will deploy locally using LocalStack: - -![An AWS architecture demonstrating a sample serverless image resizer application](https://user-images.githubusercontent.com/3996682/229322761-92f52eec-5bfb-412a-a3cb-8af4ee1fed24.png) - -The architecture: - -- Configures S3 bucket notifications to invoke a Lambda function. -- Provides S3 pre-signed POST URLs for direct uploads to the S3 bucket. -- Creates S3 website hosting for serving the static application client. -- Configures direct invocation URLs for Lambda functions accessible to the client. -- Establishes Lambda SNS to SNS topic notifications for failure handling. -- Creates SNS to SES subscriptions for email notifications triggered by specific events. - -An internal SES LocalStack testing endpoint (`/_localstack/aws/ses`) is configured as well, to test email sending functionality while running our local integration test suite. +Choose your preferred deployment style below: **AWS CLI** (`awslocal`) or **Terraform** (`tflocal`). ## Prerequisites -- [LocalStack CLI](/aws/getting-started/installation/#installing-localstack-cli) -- [LocalStack Web Application account](https://app.localstack.cloud/sign-up) & [Auth Token](/aws/getting-started/auth-token/) -- [Docker](https://docs.docker.com/get-docker/) -- [Python 3.11+](https://www.python.org/downloads/) & `pip` -- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) & [`awslocal` wrapper](/aws/integrations/aws-native-tools/aws-cli/#localstack-aws-cli-awslocal) -- `jq`, `zip` & `curl` - -You can start LocalStack using the `localstack` CLI. -Start the LocalStack for AWS container with your `LOCALSTACK_AUTH_TOKEN` pre-configured: +- [Docker](https://docs.docker.com/get-docker/) installed and running +- A [LocalStack account](https://app.localstack.cloud/sign-up) (free tier works) - - - \nlocalstack start`} lang="shell" /> - - - \nlocalstack start`} lang="shell" /> - - +## Step 1 — Install and start LocalStack -If you prefer running LocalStack in detached mode, you can add the `-d` flag to the `localstack start` command, and use Docker Desktop to view the logs. +The fastest way to get LocalStack running locally is with `lstk`, a lightweight CLI that handles authentication and image setup automatically. -## Instructions + + + Install `lstk`: -To get started, clone the sample application repository from GitHub: + ```bash + brew install localstack/tap/lstk # macOS / Linux with Homebrew + ``` -```bash -git clone https://github.com/localstack-samples/sample-serverless-image-resizer-s3-lambda.git -cd sample-serverless-image-resizer-s3-lambda -``` + ```bash + npm install -g @localstack/lstk # or via npm + ``` -You can now follow the instructions below to start LocalStack, deploy the sample application, and test the application. + Then start LocalStack: -### Setup a virtual environment + ```bash + lstk start + ``` -To deploy the sample application, you need to have specific Python packages are installed. -It is advisable to utilize a virtual environment for the installation process, allowing the packages to be installed in an isolated environment. -Execute the following commands to create a virtual environment and install the packages in `requirements-dev.txt`: + On first run, `lstk` opens a browser login to authenticate, then pulls the image and starts the container automatically. - - - ```shell - python -m venv .venv - source .venv/bin/activate - pip install -r requirements-dev.txt - ``` + :::note[Early release] + `lstk` currently supports core lifecycle commands (start, stop, logs, status). + For advanced features like Cloud Pods, Extensions, and Ephemeral Instances, use the [LocalStack CLI](/aws/getting-started/installation/#localstack-cli) instead. + ::: - - ```shell - python -m venv .venv - .venv\Scripts\activate - pip install -r requirements-dev.txt + + If you prefer the full-featured LocalStack CLI, [install it first](/aws/getting-started/installation/#localstack-cli), then [configure your auth token](/aws/getting-started/auth-token/), and start LocalStack: + + ```bash + localstack start ``` -:::tip -If you are encountering issues with the installation of the packages, such as Pillow, ensure you use the same version as the Python Lambdas (3.11.6) for Pillow to work. -If you're using pyenv, install and activate Python 3.11 with the following commands: +Wait for the container to report ready — you'll see a log line like `Ready.` or you can verify with: + ```bash -pyenv install 3.11 -pyenv global 3.11 +curl -s http://localhost:4566/_localstack/health | grep '"running"' ``` -::: -### Setup the serverless image resizer +## Step 2 — Deploy the serverless API -This application enables serverless image resizing using [S3](/aws/services/s3/), [SSM](/aws/services/ssm/), [Lambda](/aws/services/lambda/), [SNS](/aws/services/sns/), and [SES](/aws/services/ses/). -A simple web interface allows users to upload and view resized images. -A Lambda function generates S3 pre-signed URLs for direct uploads, while S3 bucket notifications trigger image resizing. -Another Lambda function lists and provides pre-signed URLs for browser display. -The application also handles Lambda failures through SNS and SES email notifications. +Now deploy a Lambda function and a DynamoDB table. Pick the tooling you prefer: -The sample application uses AWS CLI and our `awslocal` wrapper to deploy the application to LocalStack. -Before going further, you need to build your Lambda functions. -You can use the following script that will cover all three of them: + + + Install the `awslocal` wrapper if you haven't already: -```bash -deployment/build-lambdas.sh -``` + ```bash + pip install awscli-local + ``` -You can now deploy the sample application on LocalStack by running the following command: + **Create the Lambda function:** + + ```bash + mkdir -p /tmp/localstack-demo + cat > /tmp/localstack-demo/handler.py << 'EOF' + import json, boto3, os, uuid + + def handler(event, context): + table = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) + method = event.get('requestContext', {}).get('http', {}).get('method', 'GET') + if method == 'POST': + item = {'id': str(uuid.uuid4()), **json.loads(event.get('body', '{}'))} + table.put_item(Item=item) + return {'statusCode': 200, 'body': json.dumps(item)} + result = table.scan() + return {'statusCode': 200, 'body': json.dumps(result['Items'])} + EOF + cd /tmp/localstack-demo && zip handler.zip handler.py + ``` -```bash -deployment/awslocal/deploy.sh -``` + **Create the DynamoDB table:** -Alternatively, you can follow these instructions to deploy the sample application manually step-by-step. + ```bash + awslocal dynamodb create-table \ + --table-name Messages \ + --attribute-definitions AttributeName=id,AttributeType=S \ + --key-schema AttributeName=id,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST + ``` -:::tip -In absence of the `awslocal` wrapper, you can use the `aws` CLI directly, by configuring an [endpoint URL](/aws/integrations/aws-native-tools/aws-cli/#configuring-an-endpoint-url) or a [custom profile](/aws/integrations/aws-native-tools/aws-cli/#configuring-a-custom-profile) like `localstack`. -You can then swap `awslocal` with `aws --endpoint-url=http://localhost:4566` or `aws --profile=localstack` in the commands below. -::: + **Deploy the Lambda:** -#### Create the S3 buckets + ```bash + awslocal lambda create-function \ + --function-name messages-api \ + --runtime python3.12 \ + --handler handler.handler \ + --zip-file fileb:///tmp/localstack-demo/handler.zip \ + --role arn:aws:iam::000000000000:role/lambda-role \ + --environment Variables={TABLE_NAME=Messages} -```bash -awslocal s3 mb s3://localstack-thumbnails-app-images -awslocal s3 mb s3://localstack-thumbnails-app-resized -``` + awslocal lambda wait function-active --function-name messages-api + ``` -#### Add bucket names into the parameter store + **Create a public function URL:** -```bash -awslocal ssm put-parameter \ - --name /localstack-thumbnail-app/buckets/images \ - --type "String" \ - --value "localstack-thumbnails-app-images" -awslocal ssm put-parameter \ - --name /localstack-thumbnail-app/buckets/resized \ - --type "String" \ - --value "localstack-thumbnails-app-resized" -``` + ```bash + awslocal lambda create-function-url-config \ + --function-name messages-api \ + --auth-type NONE + ``` -#### Create SNS DLQ Topic for failed lambda invocations + **Retrieve the URL:** -```bash -awslocal sns create-topic --name failed-resize-topic -``` + ```bash + LAMBDA_URL=$(awslocal lambda list-function-url-configs \ + --function-name messages-api \ + --query 'FunctionUrlConfigs[0].FunctionUrl' \ + --output text) + echo $LAMBDA_URL + ``` + + + Install Terraform and the `tflocal` wrapper: -To receive immediate alerts in case of image resize failures, subscribe an email address to the system. -You can use the following command to subscribe an email address to the SNS topic: + ```bash + brew install hashicorp/tap/terraform # or see https://developer.hashicorp.com/terraform/install + pip install terraform-local + ``` -```bash -awslocal sns subscribe \ - --topic-arn arn:aws:sns:us-east-1:000000000000:failed-resize-topic \ - --protocol email \ - --notification-endpoint my-email@example.com -``` + Create a project directory and `main.tf`: -#### Create the Presign Lambda - -```bash showshowLineNumbers -(cd lambdas/presign; rm -f lambda.zip; zip lambda.zip handler.py) -awslocal lambda create-function \ - --function-name presign \ - --runtime python3.11 \ - --timeout 10 \ - --zip-file fileb://lambdas/presign/lambda.zip \ - --handler handler.handler \ - --role arn:aws:iam::000000000000:role/lambda-role \ - --environment Variables="{STAGE=local}" -awslocal lambda wait function-active-v2 --function-name presign -awslocal lambda create-function-url-config \ - --function-name presign \ - --auth-type NONE -``` + ```bash + mkdir -p /tmp/localstack-demo && cd /tmp/localstack-demo + ``` -#### Create the Image List Lambda - -```bash showshowLineNumbers -(cd lambdas/list; rm -f lambda.zip; zip lambda.zip handler.py) -awslocal lambda create-function \ - --function-name list \ - --handler handler.handler \ - --zip-file fileb://lambdas/list/lambda.zip \ - --runtime python3.11 \ - --timeout 10 \ - --role arn:aws:iam::000000000000:role/lambda-role \ - --environment Variables="{STAGE=local}" -awslocal lambda wait function-active-v2 --function-name list -awslocal lambda create-function-url-config \ - --function-name list \ - --auth-type NONE -``` + ```hcl + # main.tf + terraform { + required_providers { + aws = { source = "hashicorp/aws" } + archive = { source = "hashicorp/archive" } + } + } + + resource "aws_dynamodb_table" "messages" { + name = "Messages" + billing_mode = "PAY_PER_REQUEST" + hash_key = "id" + attribute { + name = "id" + type = "S" + } + } + + data "archive_file" "lambda" { + type = "zip" + output_path = "${path.module}/handler.zip" + source { + filename = "handler.py" + content = <<-EOF + import json, boto3, os, uuid + def handler(event, context): + table = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) + method = event.get('requestContext', {}).get('http', {}).get('method', 'GET') + if method == 'POST': + item = {'id': str(uuid.uuid4()), **json.loads(event.get('body', '{}'))} + table.put_item(Item=item) + return {'statusCode': 200, 'body': json.dumps(item)} + result = table.scan() + return {'statusCode': 200, 'body': json.dumps(result['Items'])} + EOF + } + } + + resource "aws_iam_role" "lambda_role" { + name = "lambda-role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ Action = "sts:AssumeRole", Effect = "Allow", + Principal = { Service = "lambda.amazonaws.com" } }] + }) + } + + resource "aws_lambda_function" "messages_api" { + function_name = "messages-api" + runtime = "python3.12" + handler = "handler.handler" + filename = data.archive_file.lambda.output_path + source_code_hash = data.archive_file.lambda.output_base64sha256 + role = aws_iam_role.lambda_role.arn + environment { + variables = { TABLE_NAME = aws_dynamodb_table.messages.name } + } + } + + resource "aws_lambda_function_url" "messages_api" { + function_name = aws_lambda_function.messages_api.function_name + authorization_type = "NONE" + } + + output "function_url" { + value = aws_lambda_function_url.messages_api.function_url + } + ``` -#### Build the Image Resizer Lambda + **Deploy:** - - - ```bash showshowLineNumbers - cd lambdas/resize - rm -rf libs lambda.zip - docker run --platform linux/x86_64 -v "$PWD":/var/task "public.ecr.aws/sam/build-python3.11" /bin/sh -c "pip install -r requirements.txt -t libs; exit" - cd libs && zip -r ../lambda.zip . && cd .. - zip lambda.zip handler.py - rm -rf libs - cd ../.. + ```bash + tflocal init + tflocal apply -auto-approve ``` - - - ```bash showshowLineNumbers - cd lambdas/resize - rm -rf package lambda.zip - mkdir package - pip install -r requirements.txt -t package --platform manylinux_2_28_x86_64 --python-version 3.11 --no-deps - zip lambda.zip handler.py - cd package - zip -r ../lambda.zip *; - cd ../.. - ``` - - - ```bash showshowLineNumbers - cd lambdas/resize - rm -rf package lambda.zip - mkdir package - pip install -r requirements.txt -t package - zip lambda.zip handler.py - cd package - zip -r ../lambda.zip\_; - cd ../.. + + **Retrieve the URL:** + + ```bash + LAMBDA_URL=$(tflocal output -raw function_url) + echo $LAMBDA_URL ``` -#### Create the Image Resizer Lambda - -```bash showshowLineNumbers -awslocal lambda create-function \ - --function-name resize \ - --runtime python3.11 \ - --timeout 10 \ - --zip-file fileb://lambdas/resize/lambda.zip \ - --handler handler.handler \ - --dead-letter-config TargetArn=arn:aws:sns:us-east-1:000000000000:failed-resize-topic \ - --role arn:aws:iam::000000000000:role/lambda-role \ - --environment Variables="{STAGE=local}" -awslocal lambda wait function-active-v2 --function-name resize -awslocal lambda put-function-event-invoke-config \ - --function-name resize \ - --maximum-event-age-in-seconds 3600 \ - --maximum-retry-attempts 0 -``` +## Step 3 — Test the API -#### Connect S3 bucket to Resizer Lambda +Store a message: ```bash -awslocal s3api put-bucket-notification-configuration \ - --bucket localstack-thumbnails-app-images \ - --notification-configuration "{\"LambdaFunctionConfigurations\": [{\"LambdaFunctionArn\": \"$(awslocal lambda get-function --function-name resize --output json | jq -r .Configuration.FunctionArn)\", \"Events\": [\"s3:ObjectCreated:*\"]}]}" +curl -X POST "$LAMBDA_URL" \ + -H "Content-Type: application/json" \ + -d '{"message": "Hello, LocalStack!"}' ``` -#### Create the S3 static website +You should get back a response like: -```bash -awslocal s3 mb s3://webapp -awslocal s3 sync --delete ./website s3://webapp -awslocal s3 website s3://webapp --index-document index.html +```json +{"id": "a1b2c3d4-...", "message": "Hello, LocalStack!"} ``` -#### Retrieve the Lambda Function URLs - -Retrieve the Lambda function URLs for the `presign` and `list` Lambda functions using the following commands: +List all messages: ```bash -awslocal lambda list-function-url-configs --function-name presign --output json | jq -r '.FunctionUrlConfigs[0].FunctionUrl' -awslocal lambda list-function-url-configs --function-name list --output json | jq -r '.FunctionUrlConfigs[0].FunctionUrl' +curl "$LAMBDA_URL" ``` -Save these URLs for later use in the sample application. - -### Run the sample AWS application - -To access the application, go to [**https://webapp.s3-website.localhost.localstack.cloud:4566**](https://webapp.s3-website.localhost.localstack.cloud:4566) in your browser. - -![Serverless image resizer application](/images/aws/serverless-image-resizer-application.png) - -Paste the `presign` and `list` Lambda function URLs into the application and click **Apply**. -Alternatively, click on **Load from API** to automatically load the URLs. +**That's the win.** You just invoked a real Lambda function that wrote to a real DynamoDB table — all running locally, with no AWS account and no cloud costs. -Upload an image, and click **Upload**. -The upload form uses the `presign` Lambda to request an S3 pre-signed POST URL, forwarding the POST request to S3. -Asynchronous resizing (maximum 400x400 pixels) occurs through S3 bucket notifications. +## Step 4 — Inspect your resources -If successful, the application displays a **success!** alert. -Click **Refresh** to trigger your browser to request the `list` Lambda URL, returning a JSON document of all items in the images (`localstack-thumbnails-app-images`) and resized images (`localstack-thumbnails-app-resized`) bucket. +You can browse the resources you just deployed in the [LocalStack Web Application](https://app.localstack.cloud/). +Navigate to your [Default Instance](https://app.localstack.cloud/inst/default/status) and click through to [Lambda](https://app.localstack.cloud/inst/default/resources/lambda/functions) or [DynamoDB](https://app.localstack.cloud/inst/default/resources/dynamodb) to see your running infrastructure. -![Serverless image resizer application displaying a resized image](/images/aws/resized-image-sample-application.png) +## Step 5 — Clean up -### View the deployed resources - -You can inspect the resources deployed as part of the sample application by accessing the [**LocalStack Web Application**](https://app.localstack.cloud/). -Navigate to your [**Default Instance**](https://app.localstack.cloud/inst/default/status) to view the deployed resources. - -![Status Page of the LocalStack Web Application"](/images/aws/localstack-web-application-status.png) - -Click on [S3](https://app.localstack.cloud/inst/default/resources/s3) or [Lambda](https://app.localstack.cloud/inst/default/resources/lambda/functions) to view the S3 buckets and Lambda functions respectively. - -![The Lambda Resource Browser Page of the LocalStack Web Application](/images/aws/localstack-web-application-lambda.png) - -### Run integration tests - -To run automated integration tests against the sample application, use the following command: - -```bash -pytest -v -``` - -Additionally, you can verify that when the `resize` Lambda fails, an SNS message is sent to a topic that an SES subscription listens to, triggering an email with the raw failure message. -Since there's no real email server involved, you can use the LocalStack SES developer endpoint to list messages sent via SES: +When you're done, stop LocalStack to tear down all local resources: ```bash -curl -s http://localhost.localstack.cloud:4566/_aws/ses | jq +lstk stop # if using lstk +localstack stop # if using the LocalStack CLI ``` -An alternative option is to use a service like MailHog or `smtp4dev`. -Start LocalStack with `SMTP_HOST=host.docker.internal:1025`, pointing to the mock SMTP server. - -### Destroy the local infrastructure - -Now that you've learned how to deploy a local AWS infrastructure for your sample application, let's clean up and tear down the resources associated with the project: - -```bash -localstack stop -``` - -LocalStack is ephemeral, meaning it doesn't persist any data across restarts. -It runs inside a Docker container, and once it's stopped, all locally created resources are automatically removed. - -To persist the local cloud resources across restarts, navigate to our [persistence documentation](/aws/capabilities/state-management/persistence) or learn about [Cloud Pods](/aws/capabilities/state-management/cloud-pods), our next generation state management utility. - -## Next Steps +LocalStack is ephemeral by default — stopping it removes all provisioned resources. +To persist state across restarts, see [Persistence](/aws/capabilities/state-management/persistence/) or [Cloud Pods](/aws/capabilities/state-management/cloud-pods/). -Congratulations on deploying an AWS application locally using LocalStack! -To expand your LocalStack capabilities, explore the following based on your expertise: +## Next steps -- [Tutorials](/aws/tutorials): Check out our tutorials to learn how to use LocalStack across various AWS services and application stacks. -- [Supported Services](/aws/services): Explore LocalStack's emulated AWS services. -- [Capabilities](/aws/capabilities/): Learn about LocalStack's capabilities including features like IAM policy stream, state management, and more. -- [Tooling](/aws/tooling/): Get details on LocalStack's tooling and integrations. -- [Blog](https://blog.localstack.cloud): Read our blog posts about LocalStack and the latest enhancements for a better local development and testing experience. +- [Tutorials](/aws/tutorials/) — Deeper dives into specific AWS services and application stacks +- [Supported Services](/aws/services/) — Full list of emulated AWS services +- [CI/CD Setup](/aws/getting-started/ci-cd/) — Run LocalStack in GitHub Actions and other pipelines +- [AI & Agent Workflows](/aws/getting-started/ai-workflows/) — Use LocalStack with AI coding tools and agents +- [Tooling](/aws/tooling/) — `awslocal`, `tflocal`, LocalStack Desktop, and more From 6ea3ae46d9a8888c5b222c9de5f8d359c3e2692c Mon Sep 17 00:00:00 2001 From: Brian Rinaldi Date: Fri, 24 Apr 2026 14:47:40 -0400 Subject: [PATCH 2/4] Update quickstart.mdx --- src/content/docs/aws/getting-started/quickstart.mdx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/content/docs/aws/getting-started/quickstart.mdx b/src/content/docs/aws/getting-started/quickstart.mdx index f4444269..687b8733 100644 --- a/src/content/docs/aws/getting-started/quickstart.mdx +++ b/src/content/docs/aws/getting-started/quickstart.mdx @@ -5,6 +5,7 @@ template: doc sidebar: order: 2 --- + import { Tabs, TabItem } from '@astrojs/starlight/components'; ## Introduction @@ -24,7 +25,7 @@ Choose your preferred deployment style below: **AWS CLI** (`awslocal`) or **Terr ## Prerequisites - [Docker](https://docs.docker.com/get-docker/) installed and running -- A [LocalStack account](https://app.localstack.cloud/sign-up) (free tier works) +- A [LocalStack account](https://app.localstack.cloud/sign-up) ## Step 1 — Install and start LocalStack @@ -54,6 +55,7 @@ The fastest way to get LocalStack running locally is with `lstk`, a lightweight `lstk` currently supports core lifecycle commands (start, stop, logs, status). For advanced features like Cloud Pods, Extensions, and Ephemeral Instances, use the [LocalStack CLI](/aws/getting-started/installation/#localstack-cli) instead. ::: + If you prefer the full-featured LocalStack CLI, [install it first](/aws/getting-started/installation/#localstack-cli), then [configure your auth token](/aws/getting-started/auth-token/), and start LocalStack: @@ -61,6 +63,7 @@ The fastest way to get LocalStack running locally is with `lstk`, a lightweight ```bash localstack start ``` + @@ -143,6 +146,7 @@ Now deploy a Lambda function and a DynamoDB table. Pick the tooling you prefer: --output text) echo $LAMBDA_URL ``` + Install Terraform and the `tflocal` wrapper: @@ -241,6 +245,7 @@ Now deploy a Lambda function and a DynamoDB table. Pick the tooling you prefer: LAMBDA_URL=$(tflocal output -raw function_url) echo $LAMBDA_URL ``` + @@ -257,7 +262,7 @@ curl -X POST "$LAMBDA_URL" \ You should get back a response like: ```json -{"id": "a1b2c3d4-...", "message": "Hello, LocalStack!"} +{ "id": "a1b2c3d4-...", "message": "Hello, LocalStack!" } ``` List all messages: From 71369d638c82c8f76090482ccbd711ed083bc30c Mon Sep 17 00:00:00 2001 From: Brian Rinaldi Date: Tue, 28 Apr 2026 07:46:48 -0400 Subject: [PATCH 3/4] Clean up the ordering Fixed some issues on the quick start and reordered the pages to make a more logical order --- .../docs/aws/getting-started/ai-workflows.mdx | 10 +- .../docs/aws/getting-started/auth-token.mdx | 2 +- .../docs/aws/getting-started/ci-cd.mdx | 24 +- .../docs/aws/getting-started/installation.mdx | 118 ++++-- .../docs/aws/getting-started/quickstart.mdx | 401 ++++++++++-------- 5 files changed, 323 insertions(+), 232 deletions(-) diff --git a/src/content/docs/aws/getting-started/ai-workflows.mdx b/src/content/docs/aws/getting-started/ai-workflows.mdx index 4746e4ff..22469037 100644 --- a/src/content/docs/aws/getting-started/ai-workflows.mdx +++ b/src/content/docs/aws/getting-started/ai-workflows.mdx @@ -3,7 +3,7 @@ title: AI & Agent Workflows description: Use LocalStack with AI coding assistants, MCP servers, and agent-driven infrastructure automation. template: doc sidebar: - order: 6 + order: 5 --- ## Overview @@ -66,8 +66,8 @@ See [Tooling](/aws/tooling/) for the full list of LocalStack-aware wrappers for ## Summary -| Use case | Tool | -|---|---| +| Use case | Tool | +| ------------------------------------------------------ | ---------------------------------------------------------------------------- | | AI assistant that can inspect & manage local resources | [LocalStack MCP Server](https://github.com/localstack/localstack-mcp-server) | -| Agent-driven infrastructure deployment | [LocalStack Skills](https://github.com/localstack/skills) | -| Validate AI-generated IaC safely | LocalStack + `tflocal` / `cdklocal` / `awslocal` | +| Agent-driven infrastructure deployment | [LocalStack Skills](https://github.com/localstack/skills) | +| Validate AI-generated IaC safely | LocalStack + `tflocal` / `cdklocal` / `awslocal` | diff --git a/src/content/docs/aws/getting-started/auth-token.mdx b/src/content/docs/aws/getting-started/auth-token.mdx index 4f6446c0..b35141c9 100644 --- a/src/content/docs/aws/getting-started/auth-token.mdx +++ b/src/content/docs/aws/getting-started/auth-token.mdx @@ -3,7 +3,7 @@ title: Auth Token description: Configure your Auth Token to access and activate LocalStack. template: doc sidebar: - order: 4 + order: 6 --- import { Code, Tabs, TabItem } from '@astrojs/starlight/components'; diff --git a/src/content/docs/aws/getting-started/ci-cd.mdx b/src/content/docs/aws/getting-started/ci-cd.mdx index feac5951..594ffed2 100644 --- a/src/content/docs/aws/getting-started/ci-cd.mdx +++ b/src/content/docs/aws/getting-started/ci-cd.mdx @@ -1,16 +1,16 @@ --- -title: CI/CD Setup +title: CI/CD description: Run LocalStack in CI pipelines — auth tokens, Docker Compose, and GitHub Actions examples. template: doc sidebar: - order: 5 + order: 4 --- import { Tabs, TabItem } from '@astrojs/starlight/components'; ## Overview -LocalStack works great in CI environments. +LocalStack works great in CI environments, allowing your integration tests to run incredibly fast and with no cloud costs. The setup differs from local development in a few important ways: - **Use a CI Auth Token**, not your personal Developer token @@ -67,6 +67,7 @@ See the [Auth Token documentation](/aws/getting-started/auth-token/) for full de ``` The `setup-localstack` action handles pulling the image, starting the container, and waiting for LocalStack to be ready. + Add LocalStack as a service in your `docker-compose.yml`: @@ -99,6 +100,7 @@ See the [Auth Token documentation](/aws/getting-started/auth-token/) for full de :::note Mounting `/var/run/docker.sock` is required for Lambda emulation, which uses Docker to run function containers. ::: + Start LocalStack directly with `docker run`: @@ -116,6 +118,7 @@ See the [Auth Token documentation](/aws/getting-started/auth-token/) for full de # Wait for readiness until curl -s http://localhost:4566/_localstack/health | grep -q '"running"'; do sleep 1; done ``` + Add LocalStack as a service in your CircleCI config: @@ -142,6 +145,7 @@ See the [Auth Token documentation](/aws/getting-started/auth-token/) for full de ``` Set `LOCALSTACK_AUTH_TOKEN` in your CircleCI project's environment variables. + @@ -156,13 +160,13 @@ curl -s http://localhost:4566/_localstack/info | jq '.is_license_activated' ## Key differences from local development -| | Local development | CI/CD | -|---|---|---| -| **CLI** | `lstk` or LocalStack CLI | Docker Compose / `docker run` | -| **Auth** | Browser login or stored token | `LOCALSTACK_AUTH_TOKEN` env var | -| **Token type** | Developer token | CI token | -| **State** | Optional persistence | Ephemeral (fresh per run) | -| **Startup** | Interactive TUI | `--non-interactive` / `-d` flag | +| | Local development | CI/CD | +| -------------- | ----------------------------- | ------------------------------- | +| **CLI** | `lstk` or LocalStack CLI | Docker Compose / `docker run` | +| **Auth** | Browser login or stored token | `LOCALSTACK_AUTH_TOKEN` env var | +| **Token type** | Developer token | CI token | +| **State** | Optional persistence | Ephemeral (fresh per run) | +| **Startup** | Interactive TUI | `--non-interactive` / `-d` flag | ## Persisting state across runs diff --git a/src/content/docs/aws/getting-started/installation.mdx b/src/content/docs/aws/getting-started/installation.mdx index dcc080ab..e6239ce0 100644 --- a/src/content/docs/aws/getting-started/installation.mdx +++ b/src/content/docs/aws/getting-started/installation.mdx @@ -3,11 +3,11 @@ title: Installation description: All installation methods for LocalStack — lstk, LocalStack CLI, Docker Compose, Docker, and Helm. template: doc sidebar: - order: 3 + order: 2 --- import { Code, LinkButton, Tabs, TabItem } from '@astrojs/starlight/components'; -import { LOCALSTACK_VERSION } from "astro:env/server"; +import { LOCALSTACK_VERSION } from 'astro:env/server'; ## Local development @@ -28,17 +28,13 @@ Install `lstk`: - ```bash - brew install localstack/tap/lstk - ``` - - - ```bash - npm install -g @localstack/lstk - ``` + ```bash brew install localstack/tap/lstk ``` + ```bash npm install -g @localstack/lstk ``` - Download a pre-built binary for your platform from [GitHub Releases](https://github.com/localstack/lstk/releases) and add it to your `PATH`. + Download a pre-built binary for your platform from [GitHub + Releases](https://github.com/localstack/lstk/releases) and add it to your + `PATH`. @@ -70,22 +66,43 @@ For alternative methods of managing the LocalStack container, see our [alternati You can download the pre-built binary for your architecture using the link below: -x86-64 -ARM64 + + x86-64 + + + ARM64 + or use the curl commands below: For x86-64: - + For ARM64: - + Then extract the LocalStack CLI from the terminal: - +
Alternative: Homebrew on Linux @@ -95,6 +112,7 @@ If you are using [Homebrew for Linux](https://docs.brew.sh/Homebrew-on-Linux), y ```bash brew install localstack/tap/localstack-cli ``` +
@@ -112,16 +130,28 @@ brew install localstack/tap/localstack-cli You may download the binary for your architecture using the link below: -Intel (AMD64) + + Intel (AMD64) + or use the following curl command: - + Then extract the LocalStack CLI from the terminal: - + @@ -130,9 +160,16 @@ Then extract the LocalStack CLI from the terminal: You can download the pre-built binary for your architecture using the link below: -Intel (AMD64) + + Intel (AMD64) + Then extract the archive and execute the binary in Powershell. + @@ -156,8 +193,8 @@ To download a specific version of LocalStack, replace `` with the requi ```bash python3 -m pip install localstack== ``` -::: +::: :::tip[MacOS Sierra?] If you have problems with permissions in MacOS X Sierra, install with: @@ -165,6 +202,7 @@ If you have problems with permissions in MacOS X Sierra, install with: ```bash python3 -m pip install --user localstack ``` + ::: :::danger @@ -183,7 +221,6 @@ To verify that the LocalStack CLI was installed correctly, you can check the ver You are all set! - :::note To start LocalStack, you must first [set up your auth token](/aws/getting-started/auth-token). ::: @@ -200,7 +237,7 @@ localstack start # start localstack in background with -d flag / / / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/ / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,< /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_| - + 💻 LocalStack CLI ${LOCALSTACK_VERSION} 👤 Profile: default @@ -211,7 +248,6 @@ localstack start # start localstack in background with -d flag [12:47:15] detaching bootstrap.py:1262 ``` - ### Updating LocalStack CLI The LocalStack CLI allows you to easily update the different components of LocalStack. @@ -287,24 +323,23 @@ Docker Compose v1.9.0 and above is supported. ```yaml showshowLineNumbers services: localstack: - container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}" - image: localstack/localstack-pro # required for Pro + container_name: '${LOCALSTACK_DOCKER_NAME:-localstack-main}' + image: localstack/localstack-pro # required for Pro ports: - - "127.0.0.1:4566:4566" # LocalStack Gateway - - "127.0.0.1:4510-4559:4510-4559" # external services port range - - "127.0.0.1:443:443" # LocalStack HTTPS Gateway (Pro) + - '127.0.0.1:4566:4566' # LocalStack Gateway + - '127.0.0.1:4510-4559:4510-4559' # external services port range + - '127.0.0.1:443:443' # LocalStack HTTPS Gateway (Pro) environment: # Activate LocalStack for AWS: https://docs.localstack.cloud/getting-started/auth-token/ - - LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?} # required for Pro + - LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?} # required for Pro # LocalStack configuration: https://docs.localstack.cloud/references/configuration/ - DEBUG=${DEBUG:-0} - PERSISTENCE=${PERSISTENCE:-0} volumes: - - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - - "/var/run/docker.sock:/var/run/docker.sock" + - '${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack' + - '/var/run/docker.sock:/var/run/docker.sock' ``` - Start the container by running the following command: ```bash @@ -312,6 +347,7 @@ docker compose up ``` :::note + - This command pulls the current nightly build from the `main` branch (if you don't have the image locally) and **not** the latest supported version. If you want to use a specific version, set the appropriate LocalStack image tag at `services.localstack.image` in the `docker-compose.yml` file (for example `localstack/localstack:`). @@ -330,7 +366,7 @@ docker compose up Please consider removing it, if this functionality is needed. - To configure an Auth Token, refer to the [Auth Token](/aws/getting-started/auth-token) documentation. -::: + ::: Please note that there are a few pitfalls when configuring your stack manually via docker-compose (e.g., required container name, Docker network, volume mounts, and environment variables). We recommend using the LocalStack CLI to validate your configuration, which will print warning messages in case it detects any potential misconfigurations: @@ -366,6 +402,7 @@ docker run \ ``` :::note + - This command pulls the current nightly build from the `main` branch (if you don't have the image locally) and **not** the latest supported version. If you want to use a specific version of LocalStack, use the appropriate tag: `docker run --rm -it -p 4566:4566 -p 4510-4559:4510-4559 localstack/localstack:`. Check-out the [LocalStack releases](https://github.com/localstack/localstack/releases) to know more about specific LocalStack versions. @@ -386,7 +423,7 @@ docker run \ For instance, setting `LOCALSTACK_PERSISTENCE=1` is equivalent to `PERSISTENCE=1`. - To configure an Auth Token, refer to the [Auth Token](/aws/getting-started/auth-token) documentation. -::: + ::: ### Helm @@ -400,6 +437,7 @@ If you want to deploy LocalStack in your [Kubernetes](https://kubernetes.io) clu #### Deploy LocalStack using Helm You can deploy LocalStack in a Kubernetes cluster by running these commands: + ```bash helm repo add localstack-repo https://helm.localstack.cloud helm upgrade --install localstack localstack-repo/localstack @@ -410,6 +448,7 @@ The Helm charts are not maintained in the main repository, but in a [separate on ## What's next? Now that you have LocalStack up and running, the following resources might be useful for your next steps: + - Check out our [Quickstart guide](/aws/getting-started/quickstart) if you are a new user to get started with LocalStack quickly. - [Use the LocalStack integrations](/aws/integrations) to interact with LocalStack and other integrated tools, for example: - Use `awslocal` to use the AWS CLI against your local cloud! @@ -425,10 +464,12 @@ Now that you have LocalStack up and running, the following resources might be us #### The LocalStack CLI installation is successful, but I cannot execute `localstack` If you can successfully install LocalStack using `pip` but you cannot use it in your terminal, you most likely haven't set up your operating system's / terminal's `PATH` variable (in order to tell them where to find programs installed via `pip`). + - If you are using Windows, you can enable the `PATH` configuration when installing Python, [as described in the official docs of Python](https://docs.python.org/3/using/windows.html#finding-the-python-executable). - If you are using a MacOS or Linux operating system, please make sure that the `PATH` is correctly set up - either system wide, or in your terminal. As a workaround you can call the LocalStack CLI python module directly: + ```bash python3 -m localstack.cli.main ``` @@ -436,12 +477,15 @@ python3 -m localstack.cli.main #### The `localstack` CLI does not start the LocalStack container If you are using the `localstack` CLI to start LocalStack, but the container is not starting, please check the following: + - Uncheck the **Use kernel networking for UDP** option in Docker Desktop (**Settings** → **Resources** → **Network**) or follow the steps in our [documentation](/aws/tooling/dns-server#system-dns-configuration) to disable it. - Start LocalStack with a specific DNS address: + ```bash DNS_ADDRESS=0 localstack start ``` -- Remove port 53 as indicated in our [standard `docker-compose.yml` file](https://github.com/localstack/localstack/blob/main/docker-compose-pro.yml). + +- Remove port 53 as indicated in our [standard `docker-compose.yml` file](https://github.com/localstack/localstack/blob/main/docker-compose-pro.yml). #### How should I access the LocalStack logs on my local machine? diff --git a/src/content/docs/aws/getting-started/quickstart.mdx b/src/content/docs/aws/getting-started/quickstart.mdx index 687b8733..00f268b7 100644 --- a/src/content/docs/aws/getting-started/quickstart.mdx +++ b/src/content/docs/aws/getting-started/quickstart.mdx @@ -1,16 +1,16 @@ --- -title: Quickstart +title: Local Development description: Deploy a serverless API locally with LocalStack in under 10 minutes using Lambda and DynamoDB. template: doc sidebar: - order: 2 + order: 3 --- -import { Tabs, TabItem } from '@astrojs/starlight/components'; +import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'; ## Introduction -In this quickstart you'll start LocalStack and deploy a simple serverless API — a **Lambda function backed by DynamoDB** — entirely on your local machine. +In this quickstart you'll start LocalStack and deploy a simple serverless API including a Lambda function backed by DynamoDB, entirely on your local machine. No AWS account needed. By the end you will have: @@ -18,9 +18,9 @@ By the end you will have: - LocalStack running locally in Docker - A Lambda function deployed and invokable via a public URL - A DynamoDB table storing data written by the Lambda -- Confirmed that your local environment behaves like real AWS +- A local environment that behaves like real AWS -Choose your preferred deployment style below: **AWS CLI** (`awslocal`) or **Terraform** (`tflocal`). +Choose your preferred deployment style below: **AWS CLI** or **Terraform**. ## Prerequisites @@ -46,10 +46,19 @@ The fastest way to get LocalStack running locally is with `lstk`, a lightweight Then start LocalStack: ```bash - lstk start + lstk ``` - On first run, `lstk` opens a browser login to authenticate, then pulls the image and starts the container automatically. + On first run, `lstk` opens a browser window to authenticate. It also pulls the LocalStack image and starts the container automatically. + + When the container is ready, you'll see log lines like: + + ```bash + ✔︎ LocalStack ready (containerId: 400b3e61f3c6) + • Endpoint: localhost.localstack.cloud:4566 + • Web app: https://app.localstack.cloud + > Tip: View deployed resources: lstk status + ``` :::note[Early release] `lstk` currently supports core lifecycle commands (start, stop, logs, status). @@ -64,188 +73,213 @@ The fastest way to get LocalStack running locally is with `lstk`, a lightweight localstack start ``` - - + When the container is ready, you'll see log lines like: -Wait for the container to report ready — you'll see a log line like `Ready.` or you can verify with: + ```bash + __ _______ __ __ + / / ____ _________ _/ / ___// /_____ ______/ /__ + / / / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/ + / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,< + /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_| + + 💻 LocalStack CLI ${LOCALSTACK_VERSION} + 👤 Profile: default + + [12:47:13] starting LocalStack in Docker mode 🐳 localstack.py:494 + preparing environment bootstrap.py:1240 + configuring container bootstrap.py:1248 + starting container bootstrap.py:1258 + [12:47:15] detaching bootstrap.py:1262 + ``` -```bash -curl -s http://localhost:4566/_localstack/health | grep '"running"' -``` + + ## Step 2 — Deploy the serverless API -Now deploy a Lambda function and a DynamoDB table. Pick the tooling you prefer: +Now deploy a Lambda function and a DynamoDB table. For this tutorial, you can choose between creating resources using the AWS CLI via our `awslocal` wrapper or Terraform via our `tflocal` wrapper. - Install the `awslocal` wrapper if you haven't already: - - ```bash - pip install awscli-local - ``` - - **Create the Lambda function:** - - ```bash - mkdir -p /tmp/localstack-demo - cat > /tmp/localstack-demo/handler.py << 'EOF' - import json, boto3, os, uuid - - def handler(event, context): - table = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) - method = event.get('requestContext', {}).get('http', {}).get('method', 'GET') - if method == 'POST': - item = {'id': str(uuid.uuid4()), **json.loads(event.get('body', '{}'))} - table.put_item(Item=item) - return {'statusCode': 200, 'body': json.dumps(item)} - result = table.scan() - return {'statusCode': 200, 'body': json.dumps(result['Items'])} - EOF - cd /tmp/localstack-demo && zip handler.zip handler.py - ``` - - **Create the DynamoDB table:** - - ```bash - awslocal dynamodb create-table \ - --table-name Messages \ - --attribute-definitions AttributeName=id,AttributeType=S \ - --key-schema AttributeName=id,KeyType=HASH \ - --billing-mode PAY_PER_REQUEST - ``` - - **Deploy the Lambda:** - - ```bash - awslocal lambda create-function \ - --function-name messages-api \ - --runtime python3.12 \ - --handler handler.handler \ - --zip-file fileb:///tmp/localstack-demo/handler.zip \ - --role arn:aws:iam::000000000000:role/lambda-role \ - --environment Variables={TABLE_NAME=Messages} - - awslocal lambda wait function-active --function-name messages-api - ``` - - **Create a public function URL:** - - ```bash - awslocal lambda create-function-url-config \ - --function-name messages-api \ - --auth-type NONE - ``` - - **Retrieve the URL:** - - ```bash - LAMBDA_URL=$(awslocal lambda list-function-url-configs \ - --function-name messages-api \ - --query 'FunctionUrlConfigs[0].FunctionUrl' \ - --output text) - echo $LAMBDA_URL - ``` + + +1. Install the `awslocal` wrapper if you haven't already: + + ```bash + pip install awscli-local + ``` + +2. Create the Lambda function + + The below code creates a Lambda function using Python and zips the code to be ready for deployment. + + ```bash + mkdir -p /tmp/localstack-demo + cat > /tmp/localstack-demo/handler.py << 'EOF' + import json, boto3, os, uuid + + def handler(event, context): + table = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) + method = event.get('requestContext', {}).get('http', {}).get('method', 'GET') + if method == 'POST': + item = {'id': str(uuid.uuid4()), **json.loads(event.get('body', '{}'))} + table.put_item(Item=item) + return {'statusCode': 200, 'body': json.dumps(item)} + result = table.scan() + return {'statusCode': 200, 'body': json.dumps(result['Items'])} + EOF + cd /tmp/localstack-demo && zip handler.zip handler.py + ``` + +3. Create the DynamoDB table + + ```bash + awslocal dynamodb create-table \ + --table-name Messages \ + --attribute-definitions AttributeName=id,AttributeType=S \ + --key-schema AttributeName=id,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST + ``` + +4. Deploy the Lambda + + ```bash + awslocal lambda create-function \ + --function-name messages-api \ + --runtime python3.12 \ + --handler handler.handler \ + --zip-file fileb:///tmp/localstack-demo/handler.zip \ + --role arn:aws:iam::000000000000:role/lambda-role \ + --environment Variables={TABLE_NAME=Messages} + + awslocal lambda wait function-active --function-name messages-api + ``` + +5. Create a public function URL + + ```bash + awslocal lambda create-function-url-config \ + --function-name messages-api \ + --auth-type NONE + ``` + +6. Retrieve the URL + + ```bash + LAMBDA_URL=$(awslocal lambda list-function-url-configs \ + --function-name messages-api \ + --query 'FunctionUrlConfigs[0].FunctionUrl' \ + --output text) + echo $LAMBDA_URL + ``` + + - Install Terraform and the `tflocal` wrapper: + +1. Install Terraform and the `tflocal` wrapper: ```bash - brew install hashicorp/tap/terraform # or see https://developer.hashicorp.com/terraform/install + brew install hashicorp/tap/terraform pip install terraform-local ``` - Create a project directory and `main.tf`: - - ```bash - mkdir -p /tmp/localstack-demo && cd /tmp/localstack-demo - ``` - - ```hcl - # main.tf - terraform { - required_providers { - aws = { source = "hashicorp/aws" } - archive = { source = "hashicorp/archive" } - } - } - - resource "aws_dynamodb_table" "messages" { - name = "Messages" - billing_mode = "PAY_PER_REQUEST" - hash_key = "id" - attribute { - name = "id" - type = "S" - } - } - - data "archive_file" "lambda" { - type = "zip" - output_path = "${path.module}/handler.zip" - source { - filename = "handler.py" - content = <<-EOF - import json, boto3, os, uuid - def handler(event, context): - table = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) - method = event.get('requestContext', {}).get('http', {}).get('method', 'GET') - if method == 'POST': - item = {'id': str(uuid.uuid4()), **json.loads(event.get('body', '{}'))} - table.put_item(Item=item) - return {'statusCode': 200, 'body': json.dumps(item)} - result = table.scan() - return {'statusCode': 200, 'body': json.dumps(result['Items'])} - EOF - } - } - - resource "aws_iam_role" "lambda_role" { - name = "lambda-role" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ Action = "sts:AssumeRole", Effect = "Allow", - Principal = { Service = "lambda.amazonaws.com" } }] - }) - } - - resource "aws_lambda_function" "messages_api" { - function_name = "messages-api" - runtime = "python3.12" - handler = "handler.handler" - filename = data.archive_file.lambda.output_path - source_code_hash = data.archive_file.lambda.output_base64sha256 - role = aws_iam_role.lambda_role.arn - environment { - variables = { TABLE_NAME = aws_dynamodb_table.messages.name } - } - } - - resource "aws_lambda_function_url" "messages_api" { - function_name = aws_lambda_function.messages_api.function_name - authorization_type = "NONE" - } - - output "function_url" { - value = aws_lambda_function_url.messages_api.function_url - } - ``` - - **Deploy:** - - ```bash - tflocal init - tflocal apply -auto-approve - ``` - - **Retrieve the URL:** - - ```bash - LAMBDA_URL=$(tflocal output -raw function_url) - echo $LAMBDA_URL - ``` - + For additional installation options, see the [Terraform installation guide](https://developer.hashicorp.com/terraform/install). + +2. Create a project directory. + + ```bash + mkdir -p /tmp/localstack-demo && cd /tmp/localstack-demo + ``` + + Then create a `main.tf` file with the following content: + + ```hcl + # main.tf + terraform { + required_providers { + aws = { source = "hashicorp/aws" } + archive = { source = "hashicorp/archive" } + } + } + + resource "aws_dynamodb_table" "messages" { + name = "Messages" + billing_mode = "PAY_PER_REQUEST" + hash_key = "id" + attribute { + name = "id" + type = "S" + } + } + + data "archive_file" "lambda" { + type = "zip" + output_path = "${path.module}/handler.zip" + source { + filename = "handler.py" + content = <<-EOF + import json, boto3, os, uuid + def handler(event, context): + table = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) + method = event.get('requestContext', {}).get('http', {}).get('method', 'GET') + if method == 'POST': + item = {'id': str(uuid.uuid4()), **json.loads(event.get('body', '{}'))} + table.put_item(Item=item) + return {'statusCode': 200, 'body': json.dumps(item)} + result = table.scan() + return {'statusCode': 200, 'body': json.dumps(result['Items'])} + EOF + } + } + + resource "aws_iam_role" "lambda_role" { + name = "lambda-role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ Action = "sts:AssumeRole", Effect = "Allow", + Principal = { Service = "lambda.amazonaws.com" } }] + }) + } + + resource "aws_lambda_function" "messages_api" { + function_name = "messages-api" + runtime = "python3.12" + handler = "handler.handler" + filename = data.archive_file.lambda.output_path + source_code_hash = data.archive_file.lambda.output_base64sha256 + role = aws_iam_role.lambda_role.arn + environment { + variables = { TABLE_NAME = aws_dynamodb_table.messages.name } + } + } + + resource "aws_lambda_function_url" "messages_api" { + function_name = aws_lambda_function.messages_api.function_name + authorization_type = "NONE" + } + + output "function_url" { + value = aws_lambda_function_url.messages_api.function_url + } + ``` + +3. Deploy + + ```bash + tflocal init + tflocal apply -auto-approve + ``` + +4. Retrieve the URL + + ```bash + LAMBDA_URL=$(tflocal output -raw function_url) + echo $LAMBDA_URL + ``` + + @@ -280,16 +314,25 @@ Navigate to your [Default Instance](https://app.localstack.cloud/inst/default/st ## Step 5 — Clean up -When you're done, stop LocalStack to tear down all local resources: +First, stop LocalStack to tear down all local resources: -```bash -lstk stop # if using lstk -localstack stop # if using the LocalStack CLI -``` +{/* prettier-ignore-start */} + + + ```bash lstk stop ``` + ```bash localstack stop ``` + +{/* prettier-ignore-end */} LocalStack is ephemeral by default — stopping it removes all provisioned resources. To persist state across restarts, see [Persistence](/aws/capabilities/state-management/persistence/) or [Cloud Pods](/aws/capabilities/state-management/cloud-pods/). +Now that you're done, you can remove the tutorial files from your machine (the Lambda source, zip, and, if you used Terraform, `main.tf` and state under the same folder): + +```bash +rm -rf /tmp/localstack-demo +``` + ## Next steps - [Tutorials](/aws/tutorials/) — Deeper dives into specific AWS services and application stacks From c778969deee249c6a1712a0cfca17e5ed992c105 Mon Sep 17 00:00:00 2001 From: Brian Rinaldi Date: Tue, 28 Apr 2026 08:45:42 -0400 Subject: [PATCH 4/4] Clean up CI-CD landing page --- .../docs/aws/getting-started/ci-cd.mdx | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/content/docs/aws/getting-started/ci-cd.mdx b/src/content/docs/aws/getting-started/ci-cd.mdx index 594ffed2..0618d865 100644 --- a/src/content/docs/aws/getting-started/ci-cd.mdx +++ b/src/content/docs/aws/getting-started/ci-cd.mdx @@ -1,6 +1,6 @@ --- title: CI/CD -description: Run LocalStack in CI pipelines — auth tokens, Docker Compose, and GitHub Actions examples. +description: Run LocalStack in CI pipelines — auth tokens, Docker Compose, GitHub Actions examples, and persisting state with Cloud Pods or state export. template: doc sidebar: order: 4 @@ -11,15 +11,16 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; ## Overview LocalStack works great in CI environments, allowing your integration tests to run incredibly fast and with no cloud costs. -The setup differs from local development in a few important ways: +The setup differs slighty from local development in a few important ways: - **Use a CI Auth Token**, not your personal Developer token - **Manage the container directly** via Docker Compose or `docker run` — `lstk` and the LocalStack Desktop are local-only tools -- **LocalStack is ephemeral by default** — each CI run starts fresh, which is usually exactly what you want for reproducible tests +- **Runs are often isolated per job** — many pipelines start from an empty LocalStack instance for reproducible tests +- **Persistence in CI is supported** — [Cloud Pods](/aws/capabilities/state-management/cloud-pods/), snapshot-based [persistence](/aws/capabilities/state-management/persistence/) with a mounted volume, or `localstack state export` / `localstack state import` with artifacts or cache. ## Step 1 — Get a CI Auth Token -CI pipelines should use a dedicated CI Auth Token, not a Developer token tied to a specific user. +CI pipelines should use a dedicated CI Auth Token, not a developer token tied to a specific user. 1. Go to the [Auth Tokens page](https://app.localstack.cloud/workspace/auth-tokens) in the LocalStack Web Application 2. Create a new **CI Auth Token** @@ -52,9 +53,10 @@ See the [Auth Token documentation](/aws/getting-started/auth-token/) for full de - uses: actions/checkout@v4 - name: Start LocalStack - uses: LocalStack/setup-localstack@v0.2 + uses: LocalStack/setup-localstack@v0.2.2 with: image-tag: latest + install-awslocal: "true" env: LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }} @@ -160,20 +162,24 @@ curl -s http://localhost:4566/_localstack/info | jq '.is_license_activated' ## Key differences from local development -| | Local development | CI/CD | -| -------------- | ----------------------------- | ------------------------------- | -| **CLI** | `lstk` or LocalStack CLI | Docker Compose / `docker run` | -| **Auth** | Browser login or stored token | `LOCALSTACK_AUTH_TOKEN` env var | -| **Token type** | Developer token | CI token | -| **State** | Optional persistence | Ephemeral (fresh per run) | -| **Startup** | Interactive TUI | `--non-interactive` / `-d` flag | +| | Local development | CI/CD | +| -------------- | ----------------------------- | ----------------------------------------------------------------------------------- | +| **CLI** | `lstk` or LocalStack CLI | Docker Compose / `docker run` | +| **Auth** | Browser login or stored token | `LOCALSTACK_AUTH_TOKEN` env var | +| **Token type** | Developer token | CI token | +| **State** | Optional persistence | Optional persistence (same mechanisms; typical pattern is a fresh instance per job) | +| **Startup** | Interactive TUI | `--non-interactive` / `-d` flag | ## Persisting state across runs -By default, LocalStack starts fresh on every run — all resources are gone when the container stops. -This is ideal for most CI use cases (clean, reproducible tests). +If you tear down the container at the end of a job, nothing is left on disk unless you save it — which is why many teams use a clean instance every time. +When you **do** need to reuse infrastructure or data between pipeline runs or steps, CI is fully supported: -If you need to share state across runs (e.g., seed data, pre-built infrastructure), look at [Cloud Pods](/aws/capabilities/state-management/cloud-pods/), which let you snapshot and restore LocalStack state. +- **[Cloud Pods](/aws/capabilities/state-management/cloud-pods/)** — save and load snapshots; the [`setup-localstack`](https://github.com/localstack/setup-localstack) action can load and save pods via `state-backend: cloud-pods` (see [GitHub Actions](/aws/integrations/continuous-integration/github-actions/) — _Store Localstack state_). +- **Snapshot-based [persistence](/aws/capabilities/state-management/persistence/)** — enable `PERSISTENCE=1` and mount a volume so state survives container restarts on the same runner or workspace. +- **State export/import** — run `localstack state export` and `localstack state import` and pass the file through your CI provider’s **artifacts**, **cache**, or attached storage (for example, see [GitLab CI](/aws/integrations/continuous-integration/gitlab-ci/) — _Store Localstack state_). + +Choose the approach that fits your runner model: for example, multi-job GitLab pipelines often need explicit state handoff because services do not carry between jobs. ## More CI integrations