# 🐳 De lo Local se Aprende: Desplegando tu Primera App con Docker y DynamoDB Local

Si estás comenzando en el mundo del backend o querés practicar cómo construir aplicaciones que eventualmente puedan desplegarse en la nube, esta guía es para vos.

<mark>No necesitás una cuenta de AWS ni pagar por infraestructura. En este post te muestro cómo levantar </mark> **<mark>una aplicación de votación con Flask</mark>** <mark>usando </mark> **<mark>Docker y DynamoDB Local</mark>**<mark>, simulando un entorno cloud en tu propia máquina.</mark>

## **¿Qué vamos a construir?**

Una pequeña app REST que te permite enviar votos, consultarlos, eliminarlos y almacenarlos usando una base de datos NoSQL como DynamoDB. Y todo esto lo vamos a ejecutar de forma local.

![](https://github.com/roxsross/workshop-ecs/raw/master/docs/1.png align="left")

---

## **Requisitos previos**

Antes de comenzar, asegurate de tener instalado:

* Docker y Docker Compose que viene incluidas en [Docker Desktop](https://docs.docker.com/desktop/)
    
* Python 3.x
    
* (Opcional) [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
    
* Revisar la documentación sobre [DynamoDB](https://aws.amazon.com/es/dynamodb/)
    
* [Sobre DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html)
    
* Toda la Fuerza de la IA: Amazon Q, ChatGPT, deepseek, RoxsGPT 🤭
    

---

## 🐍 Configurar un entorno virtual en Python (opcional pero recomendado)

Para mantener tu entorno limpio y evitar conflictos de dependencias entre proyectos, podés crear un entorno virtual usando `venv`. Es una buena práctica, sobre todo cuando trabajás con Flask u otras librerías.

#### 1\. Crear el entorno virtual

Desde la raíz del proyecto, ejecutá:

```bash
python3 -m venv venv
```

Esto creará una carpeta llamada `venv` con un entorno aislado de Python.

#### 2\. Activar el entorno virtual

* En Linux/macOS:
    

```bash
source venv/bin/activate
```

* En Windows (CMD):
    

```yaml
venv\Scripts\activate
```

* En PowerShell:
    

```powershell
venv\Scripts\Activate.ps1
```

Una vez activado, verás el prefijo `(venv)` en tu consola.

#### 3\. Instalar dependencias

Con el entorno activo, podés instalar las librerías del proyecto (por ejemplo, Flask y Boto3):

```bash
pip install -r requirements.txt
```

> ⚠️ Si no tenés un archivo `requirements.txt`, podés instalar manualmente con `pip install flask boto3` y luego generar el archivo con `pip freeze > requirements.txt`.

---

## 🗃️ ¿Qué es DynamoDB (y por qué lo usamos en este proyecto)?

**Amazon DynamoDB** es un servicio de base de datos NoSQL de alto rendimiento ofrecido por AWS. A diferencia de una base relacional (como MySQL o PostgreSQL), **DynamoDB almacena los datos en forma de tablas con claves primarias, pero sin esquemas rígidos**, lo que lo hace ideal para aplicaciones modernas y escalables.

#### 🚀 Características clave:

* Es **serverless**: no necesitás preocuparte por servidores ni escalabilidad.
    
* Permite consultas ultra rápidas a gran escala.
    
* Se usa mucho en arquitecturas modernas, como microservicios y apps serverless.
    

### 🤓 ¿Y qué es DynamoDB Local?

Para no depender de internet ni gastar créditos de AWS mientras aprendés, podés correr **DynamoDB Local** en tu máquina, que emula el comportamiento real del servicio. ¡Perfecto para desarrollos y pruebas locales!

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">En este proyecto, usamos DynamoDB para <strong>almacenar los votos de forma rápida y simple</strong>, sin necesidad de configurar un servidor de base de datos tradicional.</div>
</div>

---

## 🧱 Arquitectura de la aplicación

Tu stack ahora se compone de **tres componentes principales**:

1. **Frontend (HTML + JS)**
    
    * Vive dentro del servicio Flask (`vote`) en la carpeta `templates/`.
        
    * Permite a los usuarios votar y ver resultados desde el navegador.
        
2. **Backend (Flask + Python)**
    
    * Expone una API REST (`/api/votes`, `/api/stats`, etc.).
        
    * Sirve el HTML y recibe interacciones del usuario.
        
    * Se comunica con DynamoDB Local a través de Boto3.
        
3. **DynamoDB Local (Base de datos NoSQL)**
    
    * Ejecutada en un contenedor independiente ó puedes correrlo local.
        
    * Guarda votos persistidos.
        
    * Inicializada al inicio con `init_`[`db.py`](http://db.py).
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746113473391/fe4f6f99-6caf-4f7f-9b59-7c5714208758.png align="center")

---

## 🔁 Flujo de interacción

1. El usuario entra a [`http://localhost:8080`](http://localhost:8080) y ve la interfaz de votación.
    
2. Al hacer clic en “Votar por Gatos”, el navegador llama al endpoint `/api/cats`.
    
3. Flask procesa la petición y actualiza DynamoDB Local.
    
4. La interfaz recupera los votos actualizados con `/api/getvotes` y muestra los resultados.
    
5. Todo esto corre **localmente con Docker**, sin conexión a AWS real.
    

---

## 💻 Repositorio del Código

Cloná este repositorio desde **GitHub**:

[https://github.com/roxsross/workshop-ecs](https://github.com/roxsross/workshop-ecs)

Y accedé a la carpeta del proyecto:

```bash
git clone https://github.com/roxsross/workshop-ecs
cd workshop-ecs
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Aunque el repositorio está preparado para usarse con ECS, en este blog nos vamos a enfocar únicamente en su ejecución local.</div>
</div>

---

## ⚙️ Entendiendo los servicios

Esta aplicación se compone de dos contenedores definidos en `docker-compose.yml`:

* **vote**: aplicación en Flask que maneja los votos.
    
* **vote-db**: contenedor que ejecuta DynamoDB Local.
    

La app se compone de dos servicios definidos en `compose.yml`:

* **vote**: Servicio en Flask que recibe y gestiona los votos.
    
* **vote-db**: Contenedor que ejecuta DynamoDB Local.
    

```yaml
services:
  vote:
    build:
      context: .
    ports:
      - "8080:8080"
    environment:
      - DDB_AWS_REGION=us-east-1
      - DDB_TABLE_NAME=votes
      - ENV=local
    depends_on:
      - vote-db

  vote-db:
    image: amazon/dynamodb-local
    ports:
      - "8000:8000"
    environment:
      - AWS_ACCESS_KEY_ID=FAKE
      - AWS_SECRET_ACCESS_KEY=FAKE
```

El contenedor de Flask se comunica con DynamoDB Local utilizando credenciales falsas, ya que este modo de ejecución no necesita autenticación real.

Para manejos de variables de entorno te recomiendo lo siguiente: [https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/](https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/)

---

## 🧱 Construir los Contenedores

Usá el siguiente comando para construir los servicios con Docker Compose:

```bash
docker compose build
```

---

## 🔌 Inicializar DynamoDB Local

Primero levantá el servicio de base de datos:

```yaml
docker compose up vote-db -d
```

Luego, ejecutá el script `init_`[`db.py`](http://db.py) para crear la tabla y pre-cargar datos:

```yaml
python init_db.py
```

📋 Ejemplo de salida esperada:

```yaml
INFO - Creando tabla votes...
INFO - Tabla creada correctamente.
INFO - Inicializando contador para 'cats'
INFO - Inicializando contador para 'dogs'
```

> Este paso es clave para que la app funcione correctamente.

---

## 🚀 Levantar la Aplicación

Ahora sí, levantá todo el stack local:

```yaml
docker compose up -d
```

La aplicación Flask estará disponible en:  
👉 [http://localhost:8080](http://localhost:8080)

---

## 🔗 Endpoints Disponibles

Podés interactuar con la app vía API REST:

### 1\. `GET /api/votes`

Obtiene todos los votos almacenados.

```yaml
curl http://localhost:8080/api/getvotes
```

---

### 2\. `GET /api/cats`

Gestionar un voto a la opción gatos

```yaml
curl -X GET http://localhost:8080/api/cats
```

---

### 3\. `GET /api/dogs`

Elimina un voto por ID.

```yaml
curl -X GET http://localhost:8080/api/dogs
```

### 4\. `GET /api/reset`

Reinicia los votos de "cats" y "dogs" a 0.

```yaml
curl -X POST http://localhost:8080/api/reset
```

### 5\. `GET /api/history`

Obtiene el historial de votos para una entidad específica (por ejemplo, "cats" o "dogs"). Puedes limitar el número de registros con el parámetro limit

```yaml
curl -X GET "http://localhost:8080/api/history/cats?limit=5"
```

### 6\. `GET /api/stats`

Devuelve estadísticas como el total de votos, la distribución de votos y el líder actual.

```yaml
curl -X GET http://localhost:8080/api/stats
```

---

## 🧪 Probar la Conexión con AWS CLI (opcional)

Si querés ver las tablas directamente desde AWS CLI:

```yaml
export AWS_ACCESS_KEY_ID=FAKE
export AWS_SECRET_ACCESS_KEY=FAKE
aws dynamodb list-tables --endpoint-url http://localhost:8000
```

---

## 🧹 Apagar y Limpiar los Contenedores

Cuando termines, podés apagar todo con:

```yaml
docker compose down
```

Y si querés eliminar volúmenes:

```yaml
docker compose down --volumes
```

---

## 🐳 ¿Docker te parece complejo?

No te preocupes, al principio a todos nos pasó. Pero te prometo que con práctica se vuelve una de tus herramientas favoritas.

Si querés dar tus primeros pasos y entender bien cómo funciona, te dejo este workshop oficial para empezar:

👉 [Iniciá con Docker – Workshop oficial de Docker](https://docs.docker.com/get-started/workshop/)

<mark>Animate a practicar, romper cosas, reconstruir y aprender. ¡Así se crece! 💪🚀</mark>

---

## 🎥 Mirá el video corriendo el ejercicio

%[https://www.youtube.com/watch?v=FJoIbOs03Vc] 

---

## 🌱 Reflexión Final

Empezar en local no significa quedarse atrás.  
💻 Aprender a levantar tu propia app, gestionar una base de datos y simular un entorno cloud es una habilidad **clave**.

<mark>Lo que construís en tu máquina hoy... 🔥 mañana puede escalar a producción en AWS, ECS o donde vos decidas.</mark>

---

## 📁 Recursos

* Código fuente: [https://github.com/roxsross/workshop-ecs](https://github.com/roxsross/workshop-ecs)
    
* [Documentación oficial de](https://github.com/roxsross/workshop-ecs) [Dynam](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html)[oDB Local](https://github.com/roxsross/workshop-ecs)
    

---

## **Conclusión**

Empezar a desarrollar en local es uno de los mejores caminos para aprender cómo funcionan los servicios reales. Esta guía te permite practicar la interacción entre una aplicación en Flask y una base de datos NoSQL como DynamoDB, sin necesidad de subir nada a la nube.

**Lo que hoy ejecutás en tu laptop/Notebook, mañana puede escalar a servicios como AWS ECS o Fargate. Pero antes de despegar, es importante entender cómo funciona todo desde el piso.**

---

## 📲 Seguime y sumate a la comunidad

Si te gustó esta guía, compartila con tu comunidad. Y si querés más contenido como este, podés seguirme en mi canal de Youtube 295DEVOPS, donde subo tutoriales y workshops enfocados en DevOps, cloud y desarrollo práctico.

* 💜 YouTube (tutoriales y charlas): [295DEVOPS](https://www.youtube.com/@295devops)
    
* 🐦 Twitter/X: [@roxsross](https://twitter.com/roxsross)
    
* 📸 Instagram: [@roxsross](https://instagram.com/roxsross)
    
* 📝 Blog: blog.295devops.com
    
* 🐙 GitHub: [github.com/roxsross](https://github.com/roxsross)
    

¡Gracias por llegar hasta acá! Y recordá: **lo que hoy probás en local, mañana lo podés escalar a lo grande**

Nos vemos!
