LocalStack: Getting started

LocalStack: Getting started

*cover image created by me

Some time ago, I tried LocalStack for serverless architecture locally (I'm always looking for ways to work with serverless locally: Link), and it left me with a very good impression. Now, I’ve seen that they’ve expanded their features and the services they integrate, so I’ve taken on the task of exploring it in depth. In this post, I’ll share my thoughts and a step-by-step guide to Getting Started.

What is LocalStack?

It is a tool that allows you to locally test some AWS services, but in the words of LocalStack :

Develop and test your AWS applications locally to reduce development time and increase product velocity. Reduce unnecessary AWS spend and remove the complexity and risk of maintaining AWS dev accounts.

https://www.localstack.cloud/

Previously, I have written about how to test Lambda and some services locally, but LocalStack offers us some additional alternatives in its free version and extra functionalities in the paid license version.

Install LocalStack

We log in to the LocalStack account; I am personally logged in with my GitHub account. LocalStack offers several authentication methods.

On Linux, download the file:

curl --output localstack-cli-3.7.0-linux-amd64-onefile.tar.gz \
    --location https://github.com/localstack/localstack-cli/releases/download/v3.7.0/localstack-cli-3.7.0-linux-amd64-onefile.tar.gz

We extract and install:

sudo tar xvzf localstack-cli-3.7.0-linux-*-onefile.tar.gz -C /usr/local/bin

We check which version we have installed:

localstack --version
# 3.7.0

Configure the Auth token:

  1. Go to the LocalStack page after logging in: https://app.localstack.cloud/workspace/auth-token

  2. Copy the Auth Token

  1. Export the Auth token on the machine or configure it with the LocalStack command
localstack auth set-token XXX-XXX-XXX
# Token configured successfully

Start LocalStack

We run the start command

localstack start

If we run the command directly, the following error will appear:

[11:14:59] starting LocalStack in Docker mode 🐳               localstack.py:503
2024-09-03T11:15:00.313  INFO --- [  MainThread] localstack.utils.bootstrap : Execution of "prepare_host" took 764.13ms
❌ Error: 
===============================================
License activation failed! 🔑❌

Reason: Unexpected license server error: {"error": true, "message": "licensing.license.not_assigned"}

Due to this error, Localstack has quit. LocalStack pro features can only be used with a valid license.

- Please check that your credentials are set up correctly and that you have an active license.
  You can find your credentials in our webapp at https://app.localstack.cloud.
- If you want to continue using LocalStack without pro features you can set `ACTIVATE_PRO=0`.

We set the ACTIVATE_PRO=0 parameter as commented in the last line:

export ACTIVATE_PRO=0

We restart the service:

localstack start

The service should start correctly:

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 💻 LocalStack CLI 3.7.0
 👤 Profile: default

[11:16:12] starting LocalStack in Docker mode 🐳               localstack.py:503
           container image not found on host                   bootstrap.py:1272
[11:17:02] download complete                                   bootstrap.py:1276
──────────────── LocalStack Runtime Log (press CTRL-C to quit) ─────────────────

LocalStack version: 3.7.2.dev6
LocalStack build date: 2024-09-03
LocalStack build git hash: daa45717

Ready.

We set up a test environment:

We follow the getting started guide to test with a known stack. In future posts, we will test our own stacks. The guide we will follow is:

https://docs.localstack.cloud/getting-started/quickstart/

An AWS architecture demonstrating a sample serverless image resizer application

  1. Download the source code, which is a reference architecture that enables image resizing to an S3 Bucket and other functionalities:"

     git clone https://github.com/localstack-samples/sample-serverless-image-resizer-s3-lambda.git
     cd sample-serverless-image-resizer-s3-lambda
    
  2. We install the project dependencies:

It is recommended to install Python version 3.9 as indicated in the getting started guide, because the test Lambdas will not work correctly otherwise.

  • We install pyenv: https://github.com/pyenv/pyenv-installer

  •       pyenv install 3.9.0
          pyenv global 3.9.0
    

    Install project dependencies

  •       python3 -m venv .venv
          source .venv/bin/activate
          pip install -r requirements-dev.txt
    

Testing connection

To understand how it works, we will test the use of the awslocal command, which is a wrapper for the AWS CLI provided by LocalStack to keep the connections to our local stack and the Cloud stack well separated.

awslocal s3 ls

The stack log will show this:

Ready.
2024-09-03T09:53:20.688  INFO --- [et.reactor-0] localstack.utils.bootstrap : Execution of "_load_service_plugin" took 706.66ms
2024-09-03T09:53:20.688  INFO --- [et.reactor-0] localstack.utils.bootstrap : Execution of "require" took 706.99ms
2024-09-03T09:53:20.792  INFO --- [et.reactor-0] localstack.request.aws     : AWS s3.ListBuckets => 200

To continue investigating, we check which user is connected…

(.venv) ~/workspace/sample-serverless-image-resizer-s3-lambda (main)$ awslocal sts get-caller-identity
{
    "UserId": "AKIAIOSFODNN7EXAMPLE",
    "Account": "000000000000",
    "Arn": "arn:aws:iam::000000000000:root" # Cuenta y usuario
}

In the LocalStack log, we will find…

2024-09-03T10:17:03.212  INFO --- [et.reactor-0] localstack.request.aws     : AWS sts.GetCallerIdentity => 200

Deploy the Services in our LocalStack

  1. We modify the file bin/deploy.sh, replacing the Python versions with 3.9

     #bin/deploy.sh
     # ... configure the python version to 3.9
     awslocal lambda create-function \
         --function-name presign \
         --runtime python3.9 \
         --timeout 10 \
         --zip-file fileb://lambdas/presign/lambda.zip \
         --handler handler.handler \
         --role arn:aws:iam::000000000000:role/lambda-role \
         --environment Variables="{STAGE=local}"
     # ...
    
  2. Run bin/deploy.sh

    This command deploys the following architecture:

Testing the Image Resizing Stack and reviewing how LocalStack works

  1. We can view the information we have deployed: By accessing this URL, which is automatically brought up by LocalStack, we will have an overview of the services we have deployed.

You can access each service, where you can find a panel with a list of resources and details for each one; for example, the Lambdas we have deployed:

  1. Testing that the image resizing app we deployed is working correctly
  • The output from the installer provides the following information:

      make_bucket: webapp
      upload: website/index.html to s3://webapp/index.html             
      upload: website/app.js to s3://webapp/app.js                      
      upload: website/favicon.ico to s3://webapp/favicon.ico            
    
      Fetching function URL for 'presign' Lambda...
      http://9htiqm8nu1kb6rwjyl12ymf0574bv7mp.lambda-url.us-east-1.localhost.localstack.cloud:4566/
      Fetching function URL for 'list' Lambda...
      http://632bfbyw4si5k354zabiydf4oj8lt9oo.lambda-url.us-east-1.localhost.localstack.cloud:4566/
      Now open the Web app under https://webapp.s3-website.localhost.localstack.cloud:4566/
      and paste the function URLs above (make sure to use https:// as protocol)
    

    By following the steps, we have the process of detecting the Lambda endpoints, and if we upload an image, its corresponding Resized Image as shown in the image below.

Conclusions

  • We tested the LocalStack application by deploying a complete stack provided for testing, and it works correctly. We tested the Lambda, S3, and SNS services.

  • The user experience is good, with a lot of information.

  • It is necessary to be logged in, even without a PRO license, to make the most of the app.

  • A very interesting tool that I will continue to test, especially with infrastructure-as-code tools, to validate which ones can be integrated and how they behave.

References