Files
bakery-ia/docker-compose.yml
2025-07-19 17:49:03 +02:00

674 lines
19 KiB
YAML

# ================================================================
# UPDATED DOCKER COMPOSE - PROPER AUTHENTICATION ARCHITECTURE
# ================================================================
networks:
bakery-network:
driver: bridge
volumes:
postgres_auth_data:
postgres_training_data:
postgres_forecasting_data:
postgres_data_data:
postgres_tenant_data:
postgres_notification_data:
redis_data:
rabbitmq_data:
prometheus_data:
grafana_data:
services:
# ================================================================
# INFRASTRUCTURE SERVICES
# ================================================================
# Redis - For caching, sessions, and rate limiting
redis:
image: redis:7-alpine
container_name: bakery-redis
command: redis-server --appendonly yes --requirepass redis_pass123
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- bakery-network
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 30s
timeout: 10s
retries: 3
# RabbitMQ - Message broker
rabbitmq:
image: rabbitmq:3-management
container_name: bakery-rabbitmq
environment:
- RABBITMQ_DEFAULT_USER=bakery
- RABBITMQ_DEFAULT_PASS=forecast123
- RABBITMQ_DEFAULT_VHOST=/
ports:
- "5672:5672"
- "15672:15672"
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
- bakery-network
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 30s
timeout: 10s
retries: 3
# ================================================================
# DATABASE SERVICES
# ================================================================
# Auth Database
auth-db:
image: postgres:15
container_name: bakery-auth-db
environment:
- POSTGRES_DB=auth_db
- POSTGRES_USER=auth_user
- POSTGRES_PASSWORD=auth_pass123
volumes:
- postgres_auth_data:/var/lib/postgresql/data
networks:
- bakery-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U auth_user -d auth_db"]
interval: 10s
timeout: 5s
retries: 5
# Tenant Database
tenant-db:
image: postgres:15
container_name: bakery-tenant-db
environment:
- POSTGRES_DB=tenant_db
- POSTGRES_USER=tenant_user
- POSTGRES_PASSWORD=tenant_pass123
volumes:
- postgres_tenant_data:/var/lib/postgresql/data
networks:
- bakery-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tenant_user -d tenant_db"]
interval: 10s
timeout: 5s
retries: 5
# Training Database
training-db:
image: postgres:15
container_name: bakery-training-db
environment:
- POSTGRES_DB=training_db
- POSTGRES_USER=training_user
- POSTGRES_PASSWORD=training_pass123
volumes:
- postgres_training_data:/var/lib/postgresql/data
networks:
- bakery-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U training_user -d training_db"]
interval: 10s
timeout: 5s
retries: 5
# Forecasting Database
forecasting-db:
image: postgres:15
container_name: bakery-forecasting-db
environment:
- POSTGRES_DB=forecasting_db
- POSTGRES_USER=forecasting_user
- POSTGRES_PASSWORD=forecasting_pass123
volumes:
- postgres_forecasting_data:/var/lib/postgresql/data
networks:
- bakery-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U forecasting_user -d forecasting_db"]
interval: 10s
timeout: 5s
retries: 5
# Data Database
data-db:
image: postgres:15
container_name: bakery-data-db
environment:
- POSTGRES_DB=data_db
- POSTGRES_USER=data_user
- POSTGRES_PASSWORD=data_pass123
volumes:
- postgres_data_data:/var/lib/postgresql/data
networks:
- bakery-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U data_user -d data_db"]
interval: 10s
timeout: 5s
retries: 5
# Notification Database
notification-db:
image: postgres:15
container_name: bakery-notification-db
environment:
- POSTGRES_DB=notification_db
- POSTGRES_USER=notification_user
- POSTGRES_PASSWORD=notification_pass123
volumes:
- postgres_notification_data:/var/lib/postgresql/data
networks:
- bakery-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U notification_user -d notification_db"]
interval: 10s
timeout: 5s
retries: 5
# ================================================================
# MICROSERVICES
# ================================================================
# API Gateway - Enhanced with Redis caching
gateway:
build:
context: .
dockerfile: ./gateway/Dockerfile
container_name: bakery-gateway
environment:
# Service Discovery
- AUTH_SERVICE_URL=http://auth-service:8000
- TENANT_SERVICE_URL=http://tenant-service:8000
- TRAINING_SERVICE_URL=http://training-service:8000
- FORECASTING_SERVICE_URL=http://forecasting-service:8000
- DATA_SERVICE_URL=http://data-service:8000
- NOTIFICATION_SERVICE_URL=http://notification-service:8000
# Authentication & Caching
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
- REDIS_URL=redis://:redis_pass123@redis:6379/0
# CORS Configuration
- CORS_ORIGINS=http://localhost:3000,http://localhost:3001,https://panaderia.vercel.app
# Service Configuration
- SERVICE_NAME=gateway
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
# Rate Limiting
- RATE_LIMIT_CALLS_PER_MINUTE=60
- RATE_LIMIT_BURST=10
ports:
- "8000:8000"
depends_on:
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
tenant-service:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./gateway:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# Auth Service - Enhanced with proper JWT handling
auth-service:
build:
context: .
dockerfile: ./services/auth/Dockerfile
container_name: bakery-auth-service
environment:
# Database
- DATABASE_URL=postgresql+asyncpg://auth_user:auth_pass123@auth-db:5432/auth_db
# Redis for sessions and rate limiting
- REDIS_URL=redis://:redis_pass123@redis:6379/1
# Message Queue
- RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/
# JWT Configuration
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
- JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
- JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
# Security Configuration
- PASSWORD_MIN_LENGTH=8
- MAX_LOGIN_ATTEMPTS=5
- LOCKOUT_DURATION_MINUTES=30
# Service Configuration
- SERVICE_NAME=auth-service
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
ports:
- "8001:8000"
depends_on:
auth-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./services/auth:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# Tenant Service - New enhanced service
tenant-service:
build:
context: .
dockerfile: ./services/tenant/Dockerfile
container_name: bakery-tenant-service
environment:
# Database
- DATABASE_URL=postgresql+asyncpg://tenant_user:tenant_pass123@tenant-db:5432/tenant_db
# Redis for caching
- REDIS_URL=redis://:redis_pass123@redis:6379/2
# Message Queue
- RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/
# Service Discovery
- AUTH_SERVICE_URL=http://auth-service:8000
# JWT Configuration (for token verification)
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
# Service Configuration
- SERVICE_NAME=tenant-service
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
ports:
- "8005:8000"
depends_on:
tenant-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./services/tenant:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# Training Service - Enhanced with tenant isolation
training-service:
build:
context: .
dockerfile: ./services/training/Dockerfile
container_name: bakery-training-service
environment:
# Database
- DATABASE_URL=postgresql+asyncpg://training_user:training_pass123@training-db:5432/training_db
# Redis for job queuing and caching
- REDIS_URL=redis://:redis_pass123@redis:6379/3
# Message Queue
- RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/
# Service Discovery
- AUTH_SERVICE_URL=http://auth-service:8000
- DATA_SERVICE_URL=http://data-service:8000
- TENANT_SERVICE_URL=http://tenant-service:8000
# JWT Configuration
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
# ML Configuration
- MODEL_STORAGE_PATH=/app/models
- MAX_TRAINING_TIME_MINUTES=30
- MIN_TRAINING_DATA_DAYS=30
- PROPHET_SEASONALITY_MODE=additive
# Service Configuration
- SERVICE_NAME=training-service
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
ports:
- "8002:8000"
depends_on:
training-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
data-service:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./services/training:/app
- ./shared:/app/shared
- ./models:/app/models # Persistent model storage
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# Forecasting Service - Enhanced with proper auth
forecasting-service:
build:
context: .
dockerfile: ./services/forecasting/Dockerfile
container_name: bakery-forecasting-service
environment:
# Database
- DATABASE_URL=postgresql+asyncpg://forecasting_user:forecasting_pass123@forecasting-db:5432/forecasting_db
# Redis for caching predictions
- REDIS_URL=redis://:redis_pass123@redis:6379/4
# Message Queue
- RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/
# Service Discovery
- AUTH_SERVICE_URL=http://auth-service:8000
- TRAINING_SERVICE_URL=http://training-service:8000
- DATA_SERVICE_URL=http://data-service:8000
# JWT Configuration
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
# ML Configuration
- MODEL_STORAGE_PATH=/app/models
- PREDICTION_CACHE_TTL_HOURS=6
# Service Configuration
- SERVICE_NAME=forecasting-service
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
ports:
- "8003:8000"
depends_on:
forecasting-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
training-service:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./services/forecasting:/app
- ./shared:/app/shared
- ./models:/app/models # Shared model storage
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# Data Service - Enhanced with external API integration
data-service:
build:
context: .
dockerfile: ./services/data/Dockerfile
container_name: bakery-data-service
environment:
# Database
- DATABASE_URL=postgresql+asyncpg://data_user:data_pass123@data-db:5432/data_db
# Redis for API caching
- REDIS_URL=redis://:redis_pass123@redis:6379/5
# Message Queue
- RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/
# Service Discovery
- AUTH_SERVICE_URL=http://auth-service:8000
- TENANT_SERVICE_URL=http://tenant-service:8000
# External API Keys
- AEMET_API_KEY=${AEMET_API_KEY:-eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1YWxmYXJvQGdtYWlsLmNvbSIsImp0aSI6ImRjZWVmNTEwLTdmYzEtNGMxNy1hODZkLWQ4NzdlZDc5ZDllNyIsImlzcyI6IkFFTUVUIiwiaWF0IjoxNzUyODMwMDg3LCJ1c2VySWQiOiJkY2VlZjUxMC03ZmMxLTRjMTctYTg2ZC1kODc3ZWQ3OWQ5ZTciLCJyb2xlIjoiIn0.C047gaiEhWhH4ItDgkHSwg8HzKTzw87TOPRTRf8j-2w}
- MADRID_OPENDATA_API_KEY=${MADRID_OPENDATA_API_KEY:-your-madrid-opendata-key}
# JWT Configuration
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
# Data Configuration
- WEATHER_CACHE_TTL_HOURS=1
- TRAFFIC_CACHE_TTL_HOURS=1
- DATA_RETENTION_DAYS=365
# Service Configuration
- SERVICE_NAME=data-service
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
ports:
- "8004:8000"
depends_on:
data-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./services/data:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# Notification Service - Enhanced with WhatsApp and Email
notification-service:
build:
context: .
dockerfile: ./services/notification/Dockerfile
container_name: bakery-notification-service
environment:
# Database
- DATABASE_URL=postgresql+asyncpg://notification_user:notification_pass123@notification-db:5432/notification_db
# Redis for queue management
- REDIS_URL=redis://:redis_pass123@redis:6379/6
# Message Queue
- RABBITMQ_URL=amqp://bakery:forecast123@rabbitmq:5672/
# Service Discovery
- AUTH_SERVICE_URL=http://auth-service:8000
- TENANT_SERVICE_URL=http://tenant-service:8000
# Email Configuration
- SMTP_HOST=${SMTP_HOST:-smtp.gmail.com}
- SMTP_PORT=${SMTP_PORT:-587}
- SMTP_USER=${SMTP_USER:-your-email@gmail.com}
- SMTP_PASSWORD=${SMTP_PASSWORD:-your-app-password}
- SMTP_FROM_NAME=Bakery Forecast
# WhatsApp Configuration (Twilio)
- WHATSAPP_ACCOUNT_SID=${WHATSAPP_ACCOUNT_SID:-your-twilio-sid}
- WHATSAPP_AUTH_TOKEN=${WHATSAPP_AUTH_TOKEN:-your-twilio-token}
- WHATSAPP_FROM_NUMBER=${WHATSAPP_FROM_NUMBER:-whatsapp:+14155238886}
# JWT Configuration
- JWT_SECRET_KEY=${JWT_SECRET_KEY:-your-super-secret-jwt-key-change-in-production}
- JWT_ALGORITHM=HS256
# Service Configuration
- SERVICE_NAME=notification-service
- SERVICE_VERSION=1.0.0
- LOG_LEVEL=INFO
ports:
- "8006:8000"
depends_on:
notification-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
networks:
- bakery-network
volumes:
- ./services/notification:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# ================================================================
# MONITORING SERVICES
# ================================================================
# Prometheus - Metrics collection
prometheus:
image: prom/prometheus:latest
container_name: bakery-prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
ports:
- "9090:9090"
volumes:
- ./infrastructure/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
networks:
- bakery-network
depends_on:
- gateway
- auth-service
- tenant-service
- training-service
- forecasting-service
- data-service
- notification-service
# Grafana - Metrics visualization
grafana:
image: grafana/grafana:latest
container_name: bakery-grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3002:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./infrastructure/monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
- ./infrastructure/monitoring/grafana/datasources:/etc/grafana/provisioning/datasources
networks:
- bakery-network
depends_on:
- prometheus
# ================================================================
# FRONTEND SERVICES (Optional for development)
# ================================================================
# React Dashboard
dashboard:
build:
context: ./frontend
dockerfile: Dockerfile.dev
container_name: bakery-frontend
environment:
- REACT_APP_API_URL=http://localhost:8000/api/v1
- REACT_APP_WS_URL=ws://localhost:8000/ws
ports:
- "3000:3000"
depends_on:
- gateway
networks:
- bakery-network
volumes:
- ./frontend:/app
- /app/node_modules
command: npm start
# ================================================================
# ENVIRONMENT VARIABLES TEMPLATE
# ================================================================
# Create a .env file with these variables:
#
# # JWT Secret (CHANGE IN PRODUCTION!)
# JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production-min-32-chars
#
# # External API Keys
# AEMET_API_KEY=your-aemet-api-key-here
# MADRID_OPENDATA_API_KEY=your-madrid-opendata-key-here
#
# # Email Configuration (Gmail example)
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USER=your-email@gmail.com
# SMTP_PASSWORD=your-app-specific-password
#
# # WhatsApp/Twilio Configuration
# WHATSAPP_ACCOUNT_SID=your-twilio-account-sid
# WHATSAPP_AUTH_TOKEN=your-twilio-auth-token
# WHATSAPP_FROM_NUMBER=whatsapp:+14155238886