LocalStack es un emulador de servicios de AWS que se ejecuta en un contenedor Docker. Con él puedes desarrollar y probar aplicaciones que usan AWS sin conectarte a la nube real, lo que te ahorra costes y te permite trabajar completamente offline.

En este post te explico cómo instalar y configurar LocalStack en tu homelab usando Docker Compose, cómo interactuar con los servicios emulados y algunos ejemplos prácticos.

¿Qué es LocalStack?

LocalStack es una plataforma que emula los servicios de AWS de forma local. Te permite levantar un contenedor de Docker que expone las mismas APIs que AWS, así puedes interactuar con las herramientas habituales (AWS CLI, SDKs, Terraform, etc.) apuntando a localhost (u otro host donde tengas LocalStack corriendo) en lugar de a la nube real de AWS.

Algunos de los servicios disponibles en la versión gratuita son:

Categoría Servicios
Almacenamiento S3
Bases de Datos DynamoDB
Mensajería y Eventos SQS, SNS, EventBridge
Computación Serverless Lambda
Gestión de APIs API Gateway
Infraestructura y Monitorización CloudFormation, CloudWatch
Seguridad y Acceso IAM, KMS, Secrets Manager, Security Token Service
Otros Servicios Kinesis, Step Functions, Route 53

Para consultar la lista completa de servicios soportados, visita: Licensing & Tiers | Docs.

⚠️ Aviso importante

En diciembre de 2025, LocalStack publicó en su blog lo siguiente: The Road Ahead for LocalStack: Upcoming Changes to the Delivery of Our AWS Cloud Emulators.

En dicha entrada vienen a decir que a partir del 23 de marzo de 2026, necesitarás una cuenta en LocalStack Cloud incluso para usar el tier gratuito.

Me limitaré a no hacer comentarios al respecto, pero si quieres seguir usando LocalStack sin necesidad de una cuenta, según nos dicen ellos mismos, la única alternativa será usar la última versión que publiquen antes de hacer efectiva la obligación de registro. Esto implica que con el tiempo, la versión gratuita se quedará obsoleta y no tendrá soporte para nuevos servicios ni actualizaciones.

Cuando implementen la obligación de registro, actualizaré este post con las instrucciones necesarias para utilizar la versión gratuita con y sin cuenta.

Requisitos

  • Docker y Docker Compose instalados. Si aún no los tienes, puedes seguir mi guía de instalación de Docker.
  • (Opcional) Tener la consola de AWS CLI instalada para interactuar con los servicios emulados.

Instalación con Docker Compose

Empezamos creando el directorio para nuestro proyecto de LocalStack:

mkdir -p ~/Rootless-Docker-Files/localstack

Creamos el fichero docker-compose.yml:

cd ~/Rootless-Docker-Files/localstack

nano -cl docker-compose.yml

Añadimos el siguiente contenido, sacado del ejemplo que hay en su repositorio con algunas modificaciones leves:

services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}"
    image: localstack/localstack
    restart: unless-stopped
    ports:
      - "127.0.0.1:4566:4566"            # LocalStack Gateway
      - "127.0.0.1:4510-4559:4510-4559"  # external services port range
    environment:
      # LocalStack configuration: https://docs.localstack.cloud/references/configuration/
      - DEBUG=${DEBUG:-0}
    volumes:
      - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
#     - "/var/run/docker.sock:/var/run/docker.sock"
      - "/run/user/1000/docker.sock:/var/run/docker.sock"

⚠️ Nota: Asegúrate de que la ruta al socket de Docker coincide con la de tu sistema.

Para instalaciones de Docker como root, estará en /var/run/docker.sock. Si es tu caso, descomenta esa línea y comenta la siguiente.

En el caso de Docker Rootless, el socket suele estar en /run/user/$(id -u)/docker.sock. Este es mi caso, por lo que he puesto la ruta con el UID 1000 (el de mi usuario).

Si no estás seguro, puedes comprobar la ruta ejecutando: echo $XDG_RUNTIME_DIR/docker.sock o echo $DOCKER_HOST.

Si quieres montar LocalStack en otro equipo diferente al que vas a usar para interactuar con él (ej. LocalStack en un VM y acceder con AWS CLI desde tu equipo), asegúrate de modificar la sección ports y quita la dirección de loopback para que los puertos se expongan en todas las interfaces de red (cuidado con esto). Alternativamente, puedes poner la IP de la interfaz de red que sea accesible desde tu equipo cliente.

El ejemplo más sencillo, que expone los puertos en todas las interfaces, sería:

...
ports:
  - "4566:4566"            # LocalStack Gateway
  - "4510-4559:4510-4559"  # external services port range
...

Para más información sobre los puertos de Docker, consulta Port publishing and mapping | Docker Docs.

Iniciamos el escenario:

docker compose up -d

Podemos seguir los logs con:

docker compose logs --follow

LocalStack Up and Logs

Y para comprobar que todo funciona correctamente, podemos consultar el endpoint de estado de salud:

curl -s http://localhost:4566/_localstack/health | jq

LocalStack health endpoint

Como es obvio, necesitarás tener instalado jq para formatear la salida JSON.

Interactuando con LocalStack

Existen un par de opciones, pero en este post utilizaré AWS CLI, para instalarlo puedes seguir la documentación oficial.

Alternativamente, puedes usar el paquete awscli si existe en los repositorios de tu distribución, aunque puede estar desactualizado.

En el caso de Debian 13:

su -

apt install awscli

exit

AWS CLI version

Opción 1: AWS CLI

Se puede utilizar AWS CLI exportando las credenciales de prueba como test:test, la región us-east-1 y añadiendo el parámetro --endpoint-url cada vez que ejecutamos un comando:

# Configurar credenciales de prueba
export AWS_ACCESS_KEY_ID="test"
export AWS_SECRET_ACCESS_KEY="test"
export AWS_DEFAULT_REGION="us-east-1"

# Crear un bucket en S3
aws --endpoint-url=http://localhost:4566 s3 mb s3://mi-bucket

# Listar buckets
aws --endpoint-url=http://localhost:4566 s3 ls

# Para borrar el bucket
aws --endpoint-url=http://localhost:4566 s3 rb s3://mi-bucket

Ejemplo AWS CLI con endpoint

Podemos ver que al intentar crear un bucket sin haber exportado las variables de entorno, nos da un error de credenciales pero posteriormente, al exportarlas, el comando se ejecuta correctamente.

Ahora, te recomiendo crear un perfil para LocalStack en tu configuración de AWS, así no tendrás que exportar las variables ni añadir el parámetro --endpoint-url cada vez.

Edita ~/.aws/config y añade el siguiente contenido:

mkdir -p ~/.aws

nano -cl ~/.aws/config
[profile localstack]
region = us-east-1
output = json
endpoint_url = http://localhost:4566

Edita ~/.aws/credentials:

nano -cl ~/.aws/credentials
[localstack]
aws_access_key_id = test
aws_secret_access_key = test

Y para usar el nuevo perfil:

aws s3 ls --profile localstack

Ejemplo AWS CLI con perfil

Finalmente, para no tener que especificar el perfil cada vez, puedes exportarlo como variable de entorno:

export AWS_PROFILE="localstack"

Ejemplo AWS CLI con variable de entorno

Esta exportación no es persistente, por lo que si quieres que se mantenga tras reiniciar la terminal, añádela a tu fichero ~/.bashrc, ~/.zshrc o el que uses habitualmente:

echo 'export AWS_PROFILE="localstack"' >> ~/.bashrc

Opción 2: awslocal

awslocal es un wrapper de AWS CLI que configura automáticamente el endpoint. Es más cómodo para el día a día pero a mí no me gusta instalar herramientas adicionales si no son necesarias.

Si tienes interés en instalarlo, puedes hacerlo siguiendo las instrucciones oficiales.

Opción 3: Lo que quieras

LocalStack es compatible con cualquier herramienta que pueda utilizar un endpoint personalizado, por lo que puedes usar Boto3, Terraform, etc. Solo tendrás que configurar el endpoint para que apunte a tu instancia de LocalStack.

Algunos ejemplos prácticos

Trabajando con S3

# Crear bucket
aws s3 mb s3://datos-ejemplo

# Subir archivo
aws s3 cp archivo.txt s3://datos-ejemplo/

# Descargar archivo
aws s3 cp s3://datos-ejemplo/archivo.txt ./descargado.txt

# Listar contenido
aws s3 ls s3://datos-ejemplo/ --recursive

# Eliminar bucket aunque tenga contenido
aws s3 rb s3://datos-ejemplo --force

S3

Trabajando con SQS

# Crear cola
aws sqs create-queue --queue-name test-queue

# Enviar mensaje
aws sqs send-message \
  --queue-url http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/test-queue \
  --message-body "Mensaje de prueba"

# Recibir mensaje
aws sqs receive-message \
  --queue-url http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/test-queue

# Listar colas
aws sqs list-queues

# Borrar cola
aws sqs delete-queue --queue-url http://sqs.us-east-1.localhost.localstack.cloud:4566/000000000000/test-queue

SQS operations

Trabajando con DynamoDB

# Crear tabla
aws dynamodb create-table \
  --table-name usuarios \
  --attribute-definitions AttributeName=id,AttributeType=S \
  --key-schema AttributeName=id,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

# Insertar item
aws dynamodb put-item \
  --table-name usuarios \
  --item '{"id": {"S": "1"}, "nombre": {"S": "Juanje"}, "email": {"S": "juanje@ejemplo.com"}}'

# Consultar item
aws dynamodb get-item \
  --table-name usuarios \
  --key '{"id": {"S": "1"}}'

# Listar tablas
aws dynamodb list-tables

# Borrar tabla
aws dynamodb delete-table --table-name usuarios

DynamoDB operations - 1

DynamoDB operations - 2

Conclusión

LocalStack es una herramienta fantástica para cualquier persona que quiera aprender o ya trabaje con AWS. Te permite desarrollar y probar sin costes, sin conexión a Internet y con la tranquilidad de que no vas a romper nada en producción.

A mí me fue de gran utilidad para familiarizarme con AWS y Terraform. No pierdes nada por probarlo, así que te animo a que lo instales y juegues un poco con él.

No olvides consultar la documentación oficial para conocer todas las opciones de configuración y los servicios soportados.

Una vez que te sientas cómodo con LocalStack, el siguiente paso lógico es automatizar la creación de recursos con Terraform. Si quieres aprender los fundamentos, te lo cuento todo en mi post sobre Terraform e infraestructura como código.

Referencias