Compartir comentarios
Las respuestas se generan en base a la documentación.

Desarrolla y prueba aplicaciones AWS Cloud usando LocalStack y Docker

En el desarrollo de aplicaciones moderno, probar las aplicaciones en la nube localmente antes de desplegarlas en un entorno de producción te ayuda a realizar lanzamientos más rápido y con mayor confianza. Este enfoque implica simular servicios de forma local, identificar y corregir problemas de manera temprana y realizar iteraciones rápidas sin incurrir en costos ni enfrentarte a las complejidades de un entorno de nube completo. Herramientas como LocalStack se han vuelto invaluables en este proceso, ya que facilitan la emulación de servicios de AWS y la contenedorización de aplicaciones para entornos de prueba coherentes y aislados.

En esta guía, aprenderás a:

  • Usar Docker para iniciar un contenedor de LocalStack
  • Conectarte a LocalStack desde una aplicación no contenedorizada
  • Conectarte a LocalStack desde una aplicación contenedorizada

¿Qué es LocalStack?

LocalStack es un emulador de servicios en la nube que se ejecuta en un solo contenedor en tu computadora. Proporciona una forma potente, flexible y económica de probar y desarrollar aplicaciones basadas en AWS de forma local.

¿Por qué usar LocalStack?

Simular los servicios de AWS localmente te ayuda a probar cómo interactúa tu aplicación con servicios como S3, Lambda y DynamoDB sin necesidad de conectarte a la nube real de AWS. Puedes realizar iteraciones rápidas en tu desarrollo, evitando el costo y la complejidad de desplegar en la nube durante esta fase.

Al imitar el comportamiento de estos servicios de forma local, LocalStack propicia ciclos de retroalimentación más rápidos. Tu aplicación puede interactuar con APIs externas, pero todo se ejecuta localmente, eliminando la necesidad de lidiar con el aprovisionamiento en la nube o la latencia de red.

Esto facilita la validación de integraciones y la prueba de escenarios basados en la nube sin necesidad de configurar roles o políticas de IAM en un entorno real. Puedes simular arquitecturas de nube complejas localmente y enviar tus cambios a AWS solo cuando estés listo.

Uso de LocalStack con Docker

La imagen oficial de Docker para LocalStack proporciona una manera conveniente de ejecutar LocalStack en tu máquina de desarrollo. Es de uso gratuito y no requiere ninguna clave de API para ejecutarse. Incluso puedes usar la extensión de LocalStack para Docker para interactuar con LocalStack mediante una interfaz gráfica de usuario.

Requisitos previos

Se requieren los siguientes requisitos previos para seguir esta guía práctica:

Iniciar LocalStack

Inicia una demostración rápida de LocalStack siguiendo estos pasos:

  1. Comienza clonando una aplicación de ejemplo. Abre la terminal y ejecuta el siguiente comando:

    $ git clone https://github.com/dockersamples/todo-list-localstack-docker
    $ cd todo-list-localstack-docker
    
  2. Iniciar LocalStack

    Ejecuta el siguiente comando para levantar LocalStack.

    $ docker compose -f compose-native.yml up -d
    

    Este archivo Compose también incluye especificaciones para una base de datos MongoDB requerida. Puedes verificar que los servicios estén en funcionamiento visitando el panel de Docker Desktop.

    Diagrama que muestra los contenedores de LocalStack y MongoDB en funcionamiento en Docker Desktop
  3. Verifica que LocalStack esté en funcionamiento seleccionando el contenedor y revisando los registros (logs).

    Diagrama que muestra los registros del contenedor de LocalStack
  4. Crear un bucket de Amazon S3 local

    Cuando creas un bucket de S3 local usando LocalStack, básicamente estás simulando la creación de un bucket de S3 en AWS. Esto te ayuda a probar y desarrollar aplicaciones que interactúan con S3 sin necesidad de tener una cuenta de AWS real.

    Para crear un bucket de Amazon S3 local, instala la awscli-local CLI en tu sistema. El comando awslocal es un envoltorio ligero sobre la interfaz de línea de comandos de AWS para usar con LocalStack. Te ayuda a realizar pruebas y desarrollo en un entorno simulado en tu máquina local sin necesidad de acceder a los servicios reales de AWS.

    $ pip install awscli-local
    

    Crea un nuevo bucket de S3 dentro del entorno de LocalStack con el siguiente comando:

    $ awslocal s3 mb s3://mysamplebucket
    

    El comando s3 mb s3://mysamplebucket le indica a la CLI de AWS que cree un nuevo bucket de S3 (mb significa make bucket) llamado mysamplebucket.

    Puedes verificar si el bucket de S3 se ha creado seleccionando el contenedor de LocalStack en el panel de Docker Desktop y viendo los registros. Los registros indicarán que tu entorno de LocalStack está configurado correctamente y que ahora puedes usar mysamplebucket para almacenar y recuperar objetos.

    Diagrama que muestra los registros de LocalStack que destacan la creación exitosa del bucket de S3

Uso de LocalStack en el desarrollo

Una vez que te hayas familiarizado con LocalStack, es hora de verlo en acción. En esta demostración, utilizarás una aplicación de ejemplo con un frontend en React y un backend en Node.js. Esta pila de aplicaciones utiliza los siguientes componentes:

  • React: Un frontend intuitivo para acceder a la aplicación de lista de tareas (todo-list)
  • Node.js: Un backend responsable de manejar las solicitudes HTTP
  • MongoDB: Una base de datos para almacenar todos los datos de la lista de tareas
  • LocalStack: Emula el servicio Amazon S3 para almacenar y recuperar imágenes
Diagrama que muestra la pila tecnológica de la aplicación de lista de tareas de ejemplo que incluye LocalStack, servicios de frontend y backend

Conectarse a LocalStack desde una aplicación no contenedorizada

Es hora de conectar tu aplicación a LocalStack. El archivo index.js, ubicado en el directorio backend/, sirve como el punto de entrada principal para la aplicación backend.

El código interactúa con el servicio S3 de LocalStack, al cual se accede a través del endpoint definido por la variable de entorno S3_ENDPOINT_URL, típicamente establecida en http://localhost:4566 para el desarrollo local.

El S3Client del SDK de AWS está configurado para usar este endpoint de LocalStack, junto con credenciales de prueba (AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY) que también se obtienen de las variables de entorno. Esta configuración permite que la aplicación realice operaciones en el servicio S3 simulado localmente como si estuviera interactuando con el S3 real de AWS, aportando flexibilidad al código para diferentes entornos.

El código utiliza multer y multer-s3 para manejar las subidas de archivos. Cuando un usuario sube una imagen a través de la ruta /upload, el archivo se almacena directamente en el bucket de S3 simulado por LocalStack. El nombre del bucket se recupera de la variable de entorno S3_BUCKET_NAME. A cada archivo subido se le asigna un nombre único agregando la marca de tiempo actual al nombre de archivo original. Luego, la ruta devuelve la URL del archivo subido dentro del servicio S3 local, haciéndolo accesible de la misma manera que si estuviera alojado en un bucket de S3 real de AWS.

Veámoslo en acción. Comienza iniciando el servicio backend de Node.js.

  1. Cambia al directorio backend/

    $ cd backend/
    
  2. Instala las dependencias requeridas:

    $ npm install
    
  3. Configuración de variables de entorno de AWS

    El archivo .env ubicado en el directorio backend/ ya contiene credenciales de marcador de posición (placeholders) y valores de configuración que LocalStack utiliza para emular los servicios de AWS. Las variables AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY son credenciales de marcador de posición, mientras que S3_BUCKET_NAME y S3_ENDPOINT_URL son configuraciones. No se necesitan cambios, ya que estos valores ya están configurados correctamente para LocalStack.

    Tip

    Dado que estás ejecutando MongoDB en un contenedor Docker y la aplicación backend de Node se está ejecutando de forma nativa en tu host, asegúrate de que MONGODB_URI=mongodb://localhost:27017/todos esté configurada en tu archivo .env.

    MONGODB_URI=mongodb://localhost:27017/todos
    AWS_ACCESS_KEY_ID=test
    AWS_SECRET_ACCESS_KEY=test
    S3_BUCKET_NAME=mysamplebucket
    S3_ENDPOINT_URL=http://localhost:4566
    AWS_REGION=us-east-1

    Aunque el SDK de AWS normalmente podría usar variables de entorno que comiencen con AWS_, esta aplicación específica hace referencia directa a las siguientes variables S3_* en el archivo index.js (dentro del directorio backend/) para configurar S3Client.

    const s3 = new S3Client({
      endpoint: process.env.S3_ENDPOINT_URL, // Utiliza el endpoint proporcionado o recurre a los valores predeterminados
      credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID || 'default_access_key', // Valores predeterminados para el desarrollo
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || 'default_secret_key',  
      },
    });
  4. Inicia el servidor backend:

    $ node index.js
    

    Verás el mensaje de que el servicio backend se ha iniciado correctamente en el puerto 5000.

Iniciar el servicio frontend

Para iniciar el servicio frontend, abre una nueva terminal y sigue estos pasos:

  1. Dirígete al directorio frontend:

    $ cd frontend
    
  2. Instala las dependencias requeridas

    $ npm install
    
  3. Inicia el servicio frontend

    $ npm run dev
    

    Para este momento, deberías ver el siguiente mensaje:

    VITE v5.4.2  ready in 110 ms
    ➜  Local: http://localhost:5173/
    ➜  Network: use --host to expose
    ➜  press h + enter to show help
    

    Ahora puedes acceder a la aplicación a través de http://localhost:5173. Adelante, sube una imagen seleccionando un archivo de imagen y luego el botón Upload.

    Diagrama que muestra una aplicación de lista de tareas en funcionamiento

    Puedes verificar que la imagen se haya subido al bucket de S3 revisando los registros del contenedor de LocalStack:

    Diagrama que muestra los registros de LocalStack que destacan la imagen subida al bucket de S3 emulado

    El código de estado 200 significa que la operación putObject, que implica subir un objeto al bucket de S3, se ejecutó con éxito dentro del entorno de LocalStack. LocalStack registra esta entrada para proporcionar visibilidad de las operaciones que se realizan. Esto ayuda a depurar y confirmar que tu aplicación está interactuando correctamente con los servicios emulados de AWS.

    Dado que LocalStack está diseñado para simular servicios de AWS localmente, esta entrada de registro muestra que tu aplicación está funcionando como se espera al realizar operaciones en la nube en un entorno de sandbox local.

Conectarse a LocalStack desde una aplicación Node contenedorizada

Una vez que has aprendido a conectar una aplicación Node.js no contenedorizada a LocalStack, es hora de explorar los cambios necesarios para ejecutar toda la pila de aplicaciones en un entorno contenedorizado. Para lograr esto, crearás un archivo Compose especificando todos los servicios requeridos: frontend, backend, base de datos y LocalStack.

  1. Examina el archivo Docker Compose.

    El siguiente archivo Docker Compose define cuatro servicios: backend, frontend, mongodb y localstack. Los servicios backend y frontend son tus aplicaciones Node.js, mientras que mongodb proporciona una base de datos y localstack simula servicios de AWS como S3.

    El servicio backend depende de los servicios localstack y mongodb, asegurando que estén en funcionamiento antes de que este se inicie. También utiliza un archivo .env para las variables de entorno. El servicio frontend depende del backend y establece la URL de la API. El servicio mongodb utiliza un volumen persistente para el almacenamiento de datos, y localstack está configurado para ejecutar el servicio S3. Esta configuración te ayuda a desarrollar y probar tu aplicación localmente con servicios similares a los de AWS.

    services:
      backend:
        build:
          context: ./backend
          dockerfile: Dockerfile
        ports:
          - 5000:5000
        depends_on:
          - localstack
          - mongodb
        env_file:
          - backend/.env
    
      frontend:
        build:
          context: ./frontend
          dockerfile: Dockerfile
        ports:
          - 5173:5173
        depends_on:
          - backend
        environment:
          - REACT_APP_API_URL=http://backend:5000/api
    
      mongodb:
        image: mongo
        container_name: mongodb
        volumes:
          - mongodbdata:/data/db
        ports:
          - 27017:27017
    
      localstack:
        image: localstack/localstack
        container_name: localstack
        ports:
          - 4566:4566
        environment:
          - SERVICES=s3
          - GATEWAY_LISTEN=0.0.0.0:4566
        volumes:
          - ./localstack:/docker-entrypoint-initaws.d
    
    volumes:
      mongodbdata:
  2. Modifica el archivo .env bajo el directorio backend/ para que los recursos se conecten usando los nombres de red internos.

    Tip

    Según el archivo Compose anterior, la aplicación se conectaría a LocalStack usando el nombre de host localstack, mientras que MongoDB se conectaría usando el nombre de host mongodb.

    MONGODB_URI=mongodb://mongodb:27017/todos
    AWS_ACCESS_KEY_ID=test
    AWS_SECRET_ACCESS_KEY=test
    S3_BUCKET_NAME=mysamplebucket
    S3_ENDPOINT_URL=http://localstack:4566
    AWS_REGION=us-east-1
  3. Detener los servicios en ejecución

    Asegúrate de detener los servicios de Node frontend y backend del paso anterior presionando “Ctrl+C” en la terminal. También deberás detener los contenedores de LocalStack y MongoDB seleccionándolos en el panel de Docker Desktop y eligiendo el botón "Delete".

  4. Inicia la pila de la aplicación ejecutando el siguiente comando en la raíz del directorio del proyecto clonado:

    $ docker compose -f compose.yml up -d --build
    

    Después de unos momentos, la aplicación estará en funcionamiento.

  5. Crear un bucket de S3 manualmente

    El bucket de AWS S3 no se crea de antemano mediante el archivo Compose. Ejecuta el siguiente comando para crear un nuevo bucket dentro del entorno de LocalStack:

    $ awslocal s3 mb s3://mysamplebucket
    

    El comando crea un bucket de S3 llamado mysamplebucket.

    Abre http://localhost:5173 para acceder a la aplicación completa de lista de tareas y comenzar a subir imágenes al bucket de Amazon S3.

    Tip

    Para optimizar el rendimiento y reducir los tiempos de subida durante el desarrollo, considera subir archivos de imagen más pequeños. Las imágenes más grandes pueden tardar más en procesarse y podrían afectar la capacidad de respuesta general de la aplicación.

Resumen

Esta guía te ha llevado a través de la configuración de un entorno de desarrollo local utilizando LocalStack y Docker. Has aprendido a probar aplicaciones basadas en AWS de forma local, reduciendo costos y aumentando la eficiencia de tu flujo de trabajo de desarrollo.