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..687b8733 100644 --- a/src/content/docs/aws/getting-started/quickstart.mdx +++ b/src/content/docs/aws/getting-started/quickstart.mdx @@ -1,361 +1,299 @@ --- 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'; -## 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: - -- 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. +import { Tabs, TabItem } from '@astrojs/starlight/components'; -## Architecture - -The following diagram shows the architecture that we will deploy locally using LocalStack: +## Introduction -![An AWS architecture demonstrating a sample serverless image resizer application](https://user-images.githubusercontent.com/3996682/229322761-92f52eec-5bfb-412a-a3cb-8af4ee1fed24.png) +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. -The architecture: +By the end you will have: -- 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. +- 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 -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` +- [Docker](https://docs.docker.com/get-docker/) installed and running +- A [LocalStack account](https://app.localstack.cloud/sign-up) -You can start LocalStack using the `localstack` CLI. -Start the LocalStack for AWS container with your `LOCALSTACK_AUTH_TOKEN` pre-configured: +## Step 1 — Install and start LocalStack - - - \nlocalstack start`} lang="shell" /> - - - \nlocalstack start`} lang="shell" /> - - +The fastest way to get LocalStack running locally is with `lstk`, a lightweight CLI that handles authentication and image setup automatically. -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. + + + Install `lstk`: -## Instructions + ```bash + brew install localstack/tap/lstk # macOS / Linux with Homebrew + ``` -To get started, clone the sample application repository from GitHub: + ```bash + npm install -g @localstack/lstk # or via npm + ``` -```bash -git clone https://github.com/localstack-samples/sample-serverless-image-resizer-s3-lambda.git -cd sample-serverless-image-resizer-s3-lambda -``` + Then start LocalStack: -You can now follow the instructions below to start LocalStack, deploy the sample application, and test the application. + ```bash + lstk start + ``` -### Setup a virtual environment + On first run, `lstk` opens a browser login to authenticate, then pulls the image and starts the container automatically. -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`: + :::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 - source .venv/bin/activate - pip install -r requirements-dev.txt - ``` - - ```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: -```bash -pyenv install 3.11 -pyenv global 3.11 -``` -::: - -### Setup the serverless image resizer - -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. - -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: +Wait for the container to report ready — you'll see a log line like `Ready.` or you can verify with: ```bash -deployment/build-lambdas.sh +curl -s http://localhost:4566/_localstack/health | grep '"running"' ``` -You can now deploy the sample application on LocalStack by running the following command: +## Step 2 — Deploy the serverless API -```bash -deployment/awslocal/deploy.sh -``` +Now deploy a Lambda function and a DynamoDB table. Pick the tooling you prefer: -Alternatively, you can follow these instructions to deploy the sample application manually step-by-step. + + + Install the `awslocal` wrapper if you haven't already: -:::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. -::: + ```bash + pip install awscli-local + ``` -#### Create the S3 buckets + **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 -awslocal s3 mb s3://localstack-thumbnails-app-images -awslocal s3 mb s3://localstack-thumbnails-app-resized -``` + **Create the DynamoDB table:** -#### Add bucket names into the parameter store + ```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 + ``` -```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" -``` + **Deploy the Lambda:** -#### Create SNS DLQ Topic for failed lambda invocations + ```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 sns create-topic --name failed-resize-topic -``` + awslocal lambda wait function-active --function-name messages-api + ``` -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: + **Create a public function URL:** -```bash -awslocal sns subscribe \ - --topic-arn arn:aws:sns:us-east-1:000000000000:failed-resize-topic \ - --protocol email \ - --notification-endpoint my-email@example.com -``` + ```bash + awslocal lambda create-function-url-config \ + --function-name messages-api \ + --auth-type NONE + ``` -#### 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 -``` + **Retrieve the URL:** -#### 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 -``` + ```bash + LAMBDA_URL=$(awslocal lambda list-function-url-configs \ + --function-name messages-api \ + --query 'FunctionUrlConfigs[0].FunctionUrl' \ + --output text) + echo $LAMBDA_URL + ``` -#### Build the Image Resizer Lambda + + + Install Terraform and the `tflocal` wrapper: - - - ```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 + brew install hashicorp/tap/terraform # or see https://developer.hashicorp.com/terraform/install + pip install terraform-local ``` - - - ```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 ../.. + + Create a project directory and `main.tf`: + + ```bash + mkdir -p /tmp/localstack-demo && cd /tmp/localstack-demo ``` - - - ```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 ../.. + + ```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 + } ``` - - -#### 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 -``` + **Deploy:** -#### Connect S3 bucket to Resizer Lambda + ```bash + tflocal init + tflocal apply -auto-approve + ``` -```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:*\"]}]}" -``` + **Retrieve the URL:** -#### Create the S3 static website + ```bash + LAMBDA_URL=$(tflocal output -raw function_url) + echo $LAMBDA_URL + ``` -```bash -awslocal s3 mb s3://webapp -awslocal s3 sync --delete ./website s3://webapp -awslocal s3 website s3://webapp --index-document index.html -``` + + -#### Retrieve the Lambda Function URLs +## Step 3 — Test the API -Retrieve the Lambda function URLs for the `presign` and `list` Lambda functions using the following commands: +Store a message: ```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 -X POST "$LAMBDA_URL" \ + -H "Content-Type: application/json" \ + -d '{"message": "Hello, LocalStack!"}' ``` -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. - -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. - -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. - -![Serverless image resizer application displaying a resized image](/images/aws/resized-image-sample-application.png) - -### View the deployed resources +You should get back a response like: -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 +```json +{ "id": "a1b2c3d4-...", "message": "Hello, LocalStack!" } +``` -To run automated integration tests against the sample application, use the following command: +List all messages: ```bash -pytest -v +curl "$LAMBDA_URL" ``` -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: +**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. -```bash -curl -s http://localhost.localstack.cloud:4566/_aws/ses | jq -``` +## Step 4 — Inspect your resources -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. +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. -### Destroy the local infrastructure +## Step 5 — Clean up -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: +When you're done, stop LocalStack to tear down all local resources: ```bash -localstack stop +lstk stop # if using lstk +localstack stop # if using the LocalStack CLI ``` -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