Curso-lenguaje-python/catch-all/05_redis_flask_docker
2024-06-16 18:00:16 +02:00
..
.dockerignore Add new exercise 2024-06-16 18:00:16 +02:00
app.py Add new exercise 2024-06-16 18:00:16 +02:00
config.py Add new exercise 2024-06-16 18:00:16 +02:00
docker-compose.yaml Add new exercise 2024-06-16 18:00:16 +02:00
Dockerfile Add new exercise 2024-06-16 18:00:16 +02:00
README.md Add new exercise 2024-06-16 18:00:16 +02:00
requirements.txt Add new exercise 2024-06-16 18:00:16 +02:00

Crear una API Caching con Redis, Flask y Docker

Prueba 1: Sin Redis

Primero vamos a hacer una prueba de la aplicación sin redis.

Vamos al directorio donde queremos trabajar, creamos un entorno virtual y lo activamos:

python3 -m venv venv
source venv/bin/activate

Ahora instalamos las dependencias en nuestro entorno:

(venv) pip install Flask redis flask_caching requests

Y guardamos estas dependencias en un archivo requirements.txt:

(venv) pip freeze > requirements.txt

Vamos a crear un archivo app.py con el siguiente contenido:

import requests
from flask import Flask, request, jsonify

app = Flask(__name__)


@app.route("/universities")
def get_universities():
    API_URL = "http://universities.hipolabs.com/search?country="
    search = request.args.get('country')
    r = requests.get(f"{API_URL}{search}")
    return jsonify(r.json())


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=5000)

Ahora vamos a ejecutar la aplicación:

export FLASK_APP=app.py
export FLASK_ENV=development
flask run

Y si nos vamos a postman podremos comprobar cuanto tarda en responder la petición:

Prueba 2: Dockerizar nuestra aplicación

Vamos a dockerizar nuestra aplicación, para ello vamos a crear un archivo Dockerfile con el siguiente contenido:

FROM python:3.12-alpine AS builder

WORKDIR /app

COPY . .

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 5000

CMD ["python", "app.py"]

Vamos a crear también un archivo docker-compose.yaml con el siguiente contenido:

version: '3.8'

services:
  api:
    container_name: app-python-flask-with-redis
    build: .
    env_file:
      - .env
    ports:
      - '5000:5000'
    depends_on:
      - redis

  redis:
    image: redis:7.0-alpine
    container_name: redis-python
    ports:
      - '6379:6379'

Incluimos también el contenedor de Redis. Lanzamos nuestra aplicación con el comando:

docker-compose up -d --build

Si vemos docker ps veremos que tenemos dos contenedores corriendo. También podemos revisar los logs del contenedor de la aplicación con docker logs app-python-flask-with-redis.

Comprobamos que nuestra aplicación sigue funcionando en docker igual que lo hacía en local.

Prueba 3: Añadir Redis a nuestra aplicación

Ahora vamos a añadir Redis a nuestra aplicación. Vamos a modificar el archivo app.py para que use Redis:

import requests
from flask import Flask, jsonify, request
from flask_caching import Cache

app = Flask(__name__)
app.config.from_object('config.BaseConfig')
cache = Cache(app)

@app.route("/universities")
@cache.cached(timeout=30, query_string=True)
def get_universities():
    API_URL = "http://universities.hipolabs.com/search?country="
    search = request.args.get('country')
    r = requests.get(f"{API_URL}{search}")
    return jsonify(r.json())

if __name__ == '__main__':
    app.run(host='0.0.0.0')

Y vamos a crear un archivo config.py con el siguiente contenido:

import os

class BaseConfig(object):
    CACHE_TYPE = os.environ['CACHE_TYPE']
    CACHE_REDIS_HOST = os.environ['CACHE_REDIS_HOST']
    CACHE_REDIS_PORT = os.environ['CACHE_REDIS_PORT']
    CACHE_REDIS_DB = os.environ['CACHE_REDIS_DB']
    CACHE_REDIS_URL = os.environ['CACHE_REDIS_URL']
    CACHE_DEFAULT_TIMEOUT = os.environ['CACHE_DEFAULT_TIMEOUT']

Este fichero recoge las variables de entorno que vamos a usar en nuestra aplicación. Vamos a crear un archivo .env con el siguiente contenido:

# .e
CACHE_TYPE=redis
CACHE_REDIS_HOST=redis
CACHE_REDIS_PORT=6379
CACHE_REDIS_DB=0
CACHE_REDIS_URL=redis://redis:6379/0
CACHE_DEFAULT_TIMEOUT=300

Al finalizar la práctica, tendremos esta estructura:

.
├── app.py
├── config.py
├── docker-compose.yaml
├── Dockerfile
├── .env
└── requirements.txt

Volvemos a lanzar nuestra aplicación con docker-compose up -d --build y comprobamos que todo sigue funcionando correctamente.

Volvemos a lanzar la misma petición desde postman y comprobamos que la respuesta es mucho más rápida que antes:

Podemos probar con otros países, la primera vez tardará más porque no estará en caché, pero las siguientes veces será mucho más rápido.

Esta es la magia de Redis, una base de datos en memoria que nos permite almacenar datos en caché y acelerar nuestras aplicaciones 🚀