Desplegar FastAPI en Producción con Docker y Servicios Cloud

Video
15 min~5 min lectura

Reproductor de video

Concepto clave

Desplegar FastAPI en producción con Docker y servicios cloud es como construir una fábrica automatizada en lugar de un taller artesanal. En lugar de configurar manualmente cada servidor, creas contenedores estandarizados que pueden ejecutarse en cualquier infraestructura cloud. Docker actúa como el empaquetador universal de tu aplicación, encapsulando todo lo necesario para que funcione: código, dependencias, sistema operativo y configuraciones. Los servicios cloud (como AWS, Google Cloud o Azure) proporcionan la infraestructura elástica donde estos contenedores se ejecutan, escalan y se mantienen disponibles.

La clave del despliegue profesional es la reproducibilidad: cualquier desarrollador en cualquier momento debe poder desplegar exactamente la misma aplicación con los mismos resultados. Docker garantiza esto mediante imágenes inmutables, mientras que los servicios cloud ofrecen orquestación para manejar múltiples instancias, balanceo de carga y recuperación automática ante fallos. Piensa en esto como tener moldes exactos para producir piezas idénticas, en lugar de tallar cada una a mano.

Cómo funciona en la práctica

El proceso de despliegue profesional sigue un flujo estandarizado:

  1. Desarrollas tu aplicación FastAPI localmente con todas sus dependencias
  2. Creas un Dockerfile que define cómo construir la imagen de tu aplicación
  3. Construyes y pruebas la imagen Docker localmente
  4. Subes la imagen a un registro de contenedores (Docker Hub, AWS ECR, Google Container Registry)
  5. Configuras un servicio de orquestación en tu proveedor cloud (Kubernetes, ECS, Cloud Run)
  6. Defines políticas de escalado, monitoreo y seguridad
  7. Automatizas el despliegue con pipelines CI/CD

Veamos un ejemplo concreto: antes, desplegabas manualmente en un servidor VPS. Ahora, con Docker y cloud, defines una infraestructura como código que puede recrearse automáticamente. Si necesitas escalar de 10 a 1000 usuarios concurrentes, el servicio cloud provisiona automáticamente más contenedores sin intervención manual.

Código en acción

Primero, veamos un Dockerfile básico y luego su versión optimizada para producción:

# Dockerfile básico (ANTES)
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Ahora la versión optimizada para producción:

# Dockerfile optimizado (DESPUÉS)
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH

# Usuario no-root para seguridad
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Variables de entorno para producción
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PORT=8000

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

Ahora, un docker-compose.yml para orquestación local que simula producción:

version: '3.8'
services:
  api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      - db
      - redis
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  db:
    image: postgres:13-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:6-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

Errores comunes

  • Usar la imagen base incorrecta: python:3.9 ocupa ~900MB, mientras que python:3.9-slim solo ~120MB. En producción, siempre usa variantes slim o alpine para reducir superficie de ataque y costos de transferencia.
  • Ejecutar como root: Los contenedores que ejecutan procesos como root son vulnerables a escapes de contenedor. Siempre crea un usuario no-root y usa USER en el Dockerfile.
  • No manejar señales de terminación: Uvicorn necesita recibir señales SIGTERM para cerrar conexiones correctamente. Asegúrate de que tu CMD use la forma de lista (["uvicorn", ...]) en lugar de shell para propagar señales.
  • Hardcodear configuraciones: Nunca incluyas secrets en el Dockerfile. Usa variables de entorno o sistemas de gestión de secrets como AWS Secrets Manager.
  • Olvidar health checks: Sin health checks, los balanceadores de carga no saben si tu contenedor está sano, causando tráfico a instancias caídas.

Checklist de dominio

  • ✓ Mi Dockerfile usa una imagen base slim/alpine y tiene menos de 200MB
  • ✓ Los contenedores se ejecutan como usuario no-root con USER directive
  • ✓ Tengo health checks configurados para todos los servicios
  • ✓ Las configuraciones sensibles se manejan via variables de entorno o secrets managers
  • ✓ Los logs se envían a stdout/stderr para captura centralizada
  • ✓ Tengo un proceso de build multi-stage para dependencias de desarrollo vs producción
  • ✓ He probado el despliegue en un ambiente staging idéntico a producción

Despliega tu API FastAPI en Google Cloud Run con Docker

En este ejercicio, llevarás una aplicación FastAPI existente a producción en Google Cloud Run, un servicio serverless para contenedores.

  1. Prepara tu aplicación FastAPI: Asegúrate de tener un archivo main.py con una aplicación FastAPI básica que incluya un endpoint /health para health checks.
  2. Crea un Dockerfile optimizado: Basándote en el ejemplo de la lección, crea un Dockerfile que:
    • Use python:3.9-slim como base
    • Instale dependencias desde requirements.txt
    • Ejecute como usuario no-root
    • Exponga el puerto 8080 (requerido por Cloud Run)
    • Incluya health check
  3. Construye y prueba localmente:
    • Ejecuta docker build -t fastapi-cloudrun .
    • Prueba con docker run -p 8080:8080 fastapi-cloudrun
    • Verifica que http://localhost:8080/docs y http://localhost:8080/health funcionen
  4. Despliega en Google Cloud Run:
    • Instala Google Cloud SDK y autentícate (gcloud auth login)
    • Configura tu proyecto: gcloud config set project TU-PROYECTO-ID
    • Sube la imagen: gcloud builds submit --tag gcr.io/TU-PROYECTO-ID/fastapi-app
    • Despliega: gcloud run deploy fastapi-service --image gcr.io/TU-PROYECTO-ID/fastapi-app --platform managed --region us-central1 --allow-unauthenticated
  5. Verifica y monitorea:
    • Accede a la URL proporcionada por Cloud Run
    • Verifica los logs en Google Cloud Console
    • Prueba el escalado automático haciendo 100 requests concurrentes
Pistas
  • Cloud Run requiere que el contenedor escuche en el puerto definido por la variable de entorno PORT
  • Usa gcloud run deploy --help para ver todas las opciones de configuración disponibles
  • Para testing de carga, puedes usar herramientas como hey o wrk para simular tráfico concurrente

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.