docker stuff almost complete
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -68,3 +68,6 @@ node_modules/
|
|||||||
*.pem
|
*.pem
|
||||||
credentials.json
|
credentials.json
|
||||||
migrations/
|
migrations/
|
||||||
|
|
||||||
|
|
||||||
|
*.tar.gz
|
||||||
203
docker-compose-py.yaml
Normal file
203
docker-compose-py.yaml
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
# ============================================================
|
||||||
|
# VoxPopuli - docker-compose.yaml
|
||||||
|
# Orquesta la app + toda la infraestructura de datos/mensajería
|
||||||
|
# - MySQL → API Usuarios (8000)
|
||||||
|
# - MongoDB → API Reportes (8001)
|
||||||
|
# - MongoDB → API Notificaciones(8002)
|
||||||
|
# - MongoDB → API Moderación (8003)
|
||||||
|
# - PostgreSQL → API Métricas (8004) ← faltaba esto
|
||||||
|
# - RabbitMQ → cola de mensajes entre microservicios
|
||||||
|
# ============================================================
|
||||||
|
# Uso rápido:
|
||||||
|
# cp .env.example .env # ajusta credenciales
|
||||||
|
# docker compose up --build
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
name: voxpopuli
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# INFRAESTRUCTURA
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: voxpopuli_mysql
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword}
|
||||||
|
MYSQL_DATABASE: voxpopuli_users
|
||||||
|
MYSQL_USER: ${MYSQL_USER:-voxpopuli}
|
||||||
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-voxpopuli_pass}
|
||||||
|
ports:
|
||||||
|
- "${MYSQL_PORT:-3306}:3306"
|
||||||
|
volumes:
|
||||||
|
- mysql_data:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-rootpassword}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks:
|
||||||
|
- voxpopuli_net
|
||||||
|
|
||||||
|
mongodb-reports:
|
||||||
|
image: mongo:7.0
|
||||||
|
container_name: voxpopuli_mongo_reports
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER:-admin}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:-admin_password}
|
||||||
|
MONGO_INITDB_DATABASE: voxpopuli_reports
|
||||||
|
command: mongod --auth
|
||||||
|
ports:
|
||||||
|
- "${MONGO_REPORTS_PORT:-27017}:27017"
|
||||||
|
volumes:
|
||||||
|
- mongo_reports_data:/data/db
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok", "--username", "${MONGO_USER:-admin}", "--password", "${MONGO_PASSWORD:-admin_password}", "--authenticationDatabase", "admin"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 20s
|
||||||
|
networks:
|
||||||
|
- voxpopuli_net
|
||||||
|
|
||||||
|
mongodb-notifications:
|
||||||
|
image: mongo:7.0
|
||||||
|
container_name: voxpopuli_mongo_notifications
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER:-admin}
|
||||||
|
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD:-admin_password}
|
||||||
|
MONGO_INITDB_DATABASE: voxpopuli_notifications
|
||||||
|
command: mongod --auth
|
||||||
|
ports:
|
||||||
|
- "${MONGO_NOTIFICATIONS_PORT:-27018}:27017"
|
||||||
|
volumes:
|
||||||
|
- mongo_notifications_data:/data/db
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok", "--username", "${MONGO_USER:-admin}", "--password", "${MONGO_PASSWORD:-admin_password}", "--authenticationDatabase", "admin"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 20s
|
||||||
|
networks:
|
||||||
|
- voxpopuli_net
|
||||||
|
|
||||||
|
# PostgreSQL para la API de Métricas
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: voxpopuli_postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-voxpopuli}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-voxpopuli_pass}
|
||||||
|
POSTGRES_DB: voxpopuli_metrics
|
||||||
|
ports:
|
||||||
|
- "${POSTGRES_PORT:-5432}:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-voxpopuli} -d voxpopuli_metrics"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 20s
|
||||||
|
networks:
|
||||||
|
- voxpopuli_net
|
||||||
|
|
||||||
|
rabbitmq:
|
||||||
|
image: rabbitmq:3.13-management
|
||||||
|
container_name: voxpopuli_rabbitmq
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-voxpopuli}
|
||||||
|
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS:-voxpopuli_pass}
|
||||||
|
ports:
|
||||||
|
- "${RABBITMQ_AMQP_PORT:-5672}:5672"
|
||||||
|
- "${RABBITMQ_MGMT_PORT:-15672}:15672"
|
||||||
|
volumes:
|
||||||
|
- rabbitmq_data:/var/lib/rabbitmq
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
networks:
|
||||||
|
- voxpopuli_net
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# APLICACIÓN
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: voxpopuli-app:latest
|
||||||
|
container_name: voxpopuli_app
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
# MySQL - Usuarios
|
||||||
|
MYSQL_URL: mysql+pymysql://${MYSQL_USER:-voxpopuli}:${MYSQL_PASSWORD:-voxpopuli_pass}@mysql/voxpopuli_users
|
||||||
|
# MongoDB - Reportes
|
||||||
|
MONGODB_URL: mongodb://${MONGO_USER:-admin}:${MONGO_PASSWORD:-admin_password}@mongodb-reports:27017
|
||||||
|
MONGODB_DB: voxpopuli_reports
|
||||||
|
# MongoDB - Notificaciones
|
||||||
|
MONGODB_NOTIFICATIONS_URL: mongodb://${MONGO_USER:-admin}:${MONGO_PASSWORD:-admin_password}@mongodb-notifications:27017
|
||||||
|
MONGODB_NOTIFICATIONS_DB: voxpopuli_notifications
|
||||||
|
# PostgreSQL - Métricas
|
||||||
|
POSTGRES_URL: postgresql://${POSTGRES_USER:-voxpopuli}:${POSTGRES_PASSWORD:-voxpopuli_pass}@postgres:5432/voxpopuli_metrics
|
||||||
|
# RabbitMQ
|
||||||
|
RABBITMQ_URL: amqp://${RABBITMQ_USER:-voxpopuli}:${RABBITMQ_PASS:-voxpopuli_pass}@rabbitmq:5672/
|
||||||
|
# App
|
||||||
|
HOST: 0.0.0.0
|
||||||
|
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||||
|
ports:
|
||||||
|
- "8000:8000" # API Usuarios
|
||||||
|
- "8001:8001" # API Reportes
|
||||||
|
- "8002:8002" # API Notificaciones
|
||||||
|
- "8003:8003" # API Moderación
|
||||||
|
- "8004:8004" # API Métricas
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
mongodb-reports:
|
||||||
|
condition: service_healthy
|
||||||
|
mongodb-notifications:
|
||||||
|
condition: service_healthy
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
rabbitmq:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- voxpopuli_net
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/')"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 20s
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# VOLÚMENES
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
volumes:
|
||||||
|
mysql_data:
|
||||||
|
mongo_reports_data:
|
||||||
|
mongo_notifications_data:
|
||||||
|
postgres_data:
|
||||||
|
rabbitmq_data:
|
||||||
|
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
# RED INTERNA
|
||||||
|
# ──────────────────────────────────────────
|
||||||
|
networks:
|
||||||
|
voxpopuli_net:
|
||||||
|
driver: bridge
|
||||||
30
dockerdotenv.env
Normal file
30
dockerdotenv.env
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# ============================================================
|
||||||
|
# VoxPopuli - Variables de entorno para Docker
|
||||||
|
# Copia este archivo como .env y ajusta los valores
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# ── MySQL (API Usuarios) ─────────────────────────────────────
|
||||||
|
MYSQL_ROOT_PASSWORD=rootpassword
|
||||||
|
MYSQL_USER=voxpopuli
|
||||||
|
MYSQL_PASSWORD=voxpopuli_pass
|
||||||
|
MYSQL_PORT=3306
|
||||||
|
|
||||||
|
# ── MongoDB (Reportes + Notificaciones) ──────────────────────
|
||||||
|
MONGO_USER=admin
|
||||||
|
MONGO_PASSWORD=admin_password
|
||||||
|
MONGO_REPORTS_PORT=27017
|
||||||
|
MONGO_NOTIFICATIONS_PORT=27018
|
||||||
|
|
||||||
|
# ── PostgreSQL (API Métricas) ────────────────────────────────
|
||||||
|
POSTGRES_USER=voxpopuli
|
||||||
|
POSTGRES_PASSWORD=voxpopuli_pass
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
# ── RabbitMQ ─────────────────────────────────────────────────
|
||||||
|
RABBITMQ_USER=voxpopuli
|
||||||
|
RABBITMQ_PASS=voxpopuli_pass
|
||||||
|
RABBITMQ_AMQP_PORT=5672
|
||||||
|
RABBITMQ_MGMT_PORT=15672
|
||||||
|
|
||||||
|
# ── App ──────────────────────────────────────────────────────
|
||||||
|
LOG_LEVEL=info
|
||||||
63
dockerfile
Normal file
63
dockerfile
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# ============================================================
|
||||||
|
# VoxPopuli - Dockerfile
|
||||||
|
# Microservicios FastAPI: Usuarios (8000), Reportes (8001),
|
||||||
|
# Notificaciones (8002), Moderación (8003), Métricas (8004)
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# --- Stage 1: Builder ---
|
||||||
|
FROM python:3.11-slim AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# Instalar dependencias del sistema necesarias para compilación
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc \
|
||||||
|
libffi-dev \
|
||||||
|
libssl-dev \
|
||||||
|
default-libmysqlclient-dev \
|
||||||
|
pkg-config \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copiar e instalar dependencias Python en un directorio aislado
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --upgrade pip && \
|
||||||
|
pip install --prefix=/install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
|
||||||
|
# --- Stage 2: Runtime ---
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
LABEL maintainer="Hokzaap S. de R.L. de C.V."
|
||||||
|
LABEL description="VoxPopuli - Infraestructura de Voz Ciudadana"
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Instalar únicamente librerías de runtime
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
default-libmysqlclient-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN mkdir -p /app/logs/
|
||||||
|
|
||||||
|
# Copiar paquetes instalados desde el builder
|
||||||
|
COPY --from=builder /install /usr/local
|
||||||
|
|
||||||
|
# Copiar código fuente
|
||||||
|
COPY src/ ./src/
|
||||||
|
|
||||||
|
# Variables de entorno con valores por defecto (sobreescribibles via .env o compose)
|
||||||
|
ENV HOST=0.0.0.0 \
|
||||||
|
LOG_LEVEL=info \
|
||||||
|
PYTHONUNBUFFERED=1 \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PYTHONPATH=/app/src
|
||||||
|
|
||||||
|
# Puertos expuestos por los cinco microservicios
|
||||||
|
EXPOSE 8000 8001 8002 8003 8004
|
||||||
|
|
||||||
|
# Healthcheck básico contra la API de Usuarios
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
|
||||||
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/')" || exit 1
|
||||||
|
|
||||||
|
# Punto de entrada
|
||||||
|
CMD ["python", "src/main.py"]
|
||||||
@@ -35,6 +35,11 @@ class Settings(BaseSettings):
|
|||||||
default=os.getenv("RABBITMQ_URI", "localhost")
|
default=os.getenv("RABBITMQ_URI", "localhost")
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
postgres_url: str = Field(
|
||||||
|
default=os.getenv("POSTGRES_URL", "postgresql://voxpopuli:voxpopuli_pass@localhost:5432/voxpopuli_metrics"),
|
||||||
|
description="Base de datos PostgreSQL para métricas"
|
||||||
|
)
|
||||||
|
|
||||||
# JWT Configuration
|
# JWT Configuration
|
||||||
jwt_secret_key: str = Field(
|
jwt_secret_key: str = Field(
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from core.config import ConfSettings
|
|||||||
|
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
|
|
||||||
|
#settings = ConfSettings()
|
||||||
|
|
||||||
class MetricModel(Base):
|
class MetricModel(Base):
|
||||||
"""Modelo SQLAlchemy para métricas en Postgres"""
|
"""Modelo SQLAlchemy para métricas en Postgres"""
|
||||||
@@ -28,7 +29,7 @@ class MetricsRepositoryPostgres(MetricsRepository):
|
|||||||
"""Implementación de repositorio de métricas con PostgreSQL"""
|
"""Implementación de repositorio de métricas con PostgreSQL"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
db_url = f"postgresql://voxpopuli:voxpopuli_pass@localhost:5432/voxpopuli_metrics"
|
db_url = f"postgresql://voxpopuli:voxpopuli_pass@postgres:5432/voxpopuli_metrics"
|
||||||
self.engine = create_engine(db_url, echo=False)
|
self.engine = create_engine(db_url, echo=False)
|
||||||
Base.metadata.create_all(self.engine)
|
Base.metadata.create_all(self.engine)
|
||||||
self.SessionLocal = sessionmaker(bind=self.engine)
|
self.SessionLocal = sessionmaker(bind=self.engine)
|
||||||
|
|||||||
Reference in New Issue
Block a user