Listado de la etiqueta: microservicios

Microservicios con Docker: lo que aprendí armando mi primera arquitectura

Arrancé con un monolito .NET en un solo contenedor. Funcionaba bien, hasta que el equipo creció y todos tocábamos el mismo código. Desplegar un cambio en la pantalla de login requería redeployar toda la aplicación. Fue entonces cuando empecé a explorar microservicios con Docker.

Monolito vs microservicios: cuándo tiene sentido el cambio

AspectoMonolito en DockerMicroservicios en Docker
Complejidad inicialBajaAlta
Deploy independienteNo — todo o nadaSí — servicio por servicio
Escalabilidad selectivaNoSí — escalar solo lo que lo necesita
Fallo aisladoUn bug afecta todoUn servicio caído no baja todo
Equipos independientesDifícilCada equipo dueño de su servicio
Overhead operacionalBajoAlto — más servicios que monitorear

Mi recomendación: empezá con el monolito. Cuando los puntos de dolor de la tabla de arriba se vuelvan reales en tu día a día, ahí es el momento de dividir.

Mi primera arquitectura de microservicios: auth + api + frontend

# docker-compose.yml — tres servicios independientes

version: '3.8'

services:
  # Servicio de autenticación (JWT, usuarios)
  auth-service:
    build: ./services/auth
    environment:
      - DB_CONNECTION=Host=postgres;Database=auth;Username=auth;Password=${AUTH_DB_PASS}
      - JWT_SECRET=${JWT_SECRET}
      - JWT_EXPIRY=1h
    depends_on:
      postgres:
        condition: service_healthy
    restart: unless-stopped
    # Sin puerto expuesto - solo accesible internamente

  # API principal de negocio
  api-service:
    build: ./services/api
    environment:
      - DB_CONNECTION=Host=postgres;Database=apidb;Username=api;Password=${API_DB_PASS}
      - AUTH_SERVICE_URL=http://auth-service:8080
      - CACHE_URL=redis:6379
    depends_on:
      - auth-service
      - redis
    restart: unless-stopped

  # Frontend React
  frontend:
    build: ./services/frontend
    environment:
      - REACT_APP_API_URL=http://api-service:8080
    restart: unless-stopped

  # Proxy - único punto de entrada externo
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/microservices.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - frontend
      - api-service

  # Infraestructura compartida
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_MULTIPLE_DATABASES: auth,apidb  # extensión para múltiples DBs
      POSTGRES_PASSWORD: ${POSTGRES_ROOT_PASS}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 10s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data

volumes:
  postgres-data:
  redis-data:

Comunicación entre servicios

Dentro de la red Docker, los servicios se llaman por nombre. La API valida tokens llamando al servicio de auth en cada request:

# En el código de api-service (.NET):
// Validar token contra auth-service
var authResponse = await _httpClient.GetAsync(
    $"{_authServiceUrl}/validate?token={token}"
);

// En el docker-compose, AUTH_SERVICE_URL = http://auth-service:8080
// Docker resuelve "auth-service" al contenedor correcto automáticamente

Deploy independiente: la ventaja real

# Actualizar solo el servicio de auth sin tocar nada más
docker compose up -d --build auth-service

# Escalar solo la API (recibe más carga)
docker compose up -d --scale api-service=3

# Rollback solo del frontend
docker compose stop frontend
docker compose rm -f frontend
TAG=anterior docker compose up -d frontend

Lo que aprendí en el proceso

La transición de monolito a microservicios no es solo técnica: es organizacional. Cada servicio necesita su propio repositorio (o al menos su propia carpeta), su propio pipeline de CI/CD y su propio dueño. La complejidad operacional sube. Por eso Docker Compose no es suficiente para microservicios en producción a escala — ese es el camino hacia Kubernetes, que vemos en el próximo artículo.


Artículo anterior: Docker en CI/CD | Serie Docker Completo | Próximo: Seguridad en Docker →


Artículo anterior: Docker en mi pipeline de CI/CD: builds reproducibles sin sorpresas | Serie Docker Completo | Próximo: Seguridad en Docker: errores que cometí y cómo los corregí →