Files
bakery-ia/docker-compose.yml
2025-07-22 20:22:27 +02:00

653 lines
19 KiB
YAML

# ================================================================
# OPTIMIZED DOCKER COMPOSE - NO ENVIRONMENT DUPLICATION
# Single source of truth: .env file only
# ================================================================
# ================================================================
# NETWORKS & VOLUMES (same as before)
# ================================================================
networks:
bakery-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
auth_db_data:
training_db_data:
forecasting_db_data:
data_db_data:
tenant_db_data:
notification_db_data:
redis_data:
rabbitmq_data:
prometheus_data:
grafana_data:
model_storage:
log_storage:
nominatim_db_data:
nominatim_data:
# ================================================================
# SERVICES - USING ONLY .env FILE
# ================================================================
services:
# ================================================================
# INFRASTRUCTURE - NO DUPLICATION
# ================================================================
redis:
image: redis:7-alpine
container_name: bakery-redis
restart: unless-stopped
# ONLY use environment substitution from .env
command: >
redis-server
--appendonly yes
--requirepass ${REDIS_PASSWORD}
--maxmemory ${REDIS_MAX_MEMORY:-512mb}
--databases 16
ports:
- "${REDIS_PORT}:6379"
volumes:
- redis_data:/data
networks:
bakery-network:
ipv4_address: 172.20.0.10
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 30s
timeout: 10s
retries: 3
rabbitmq:
image: rabbitmq:3.12-management-alpine
container_name: bakery-rabbitmq
restart: unless-stopped
# ONLY use environment substitution from .env
environment:
- RABBITMQ_DEFAULT_USER=${RABBITMQ_USER}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD}
- RABBITMQ_DEFAULT_VHOST=${RABBITMQ_VHOST}
ports:
- "${RABBITMQ_PORT}:5672"
- "${RABBITMQ_MANAGEMENT_PORT}:15672"
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
bakery-network:
ipv4_address: 172.20.0.11
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 30s
timeout: 10s
retries: 3
# ================================================================
# DATABASES - NO DUPLICATION
# ================================================================
auth-db:
image: postgres:15-alpine
container_name: bakery-auth-db
restart: unless-stopped
# ONLY reference .env variables
environment:
- POSTGRES_DB=${AUTH_DB_NAME}
- POSTGRES_USER=${AUTH_DB_USER}
- POSTGRES_PASSWORD=${AUTH_DB_PASSWORD}
- POSTGRES_INITDB_ARGS=${POSTGRES_INITDB_ARGS}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- auth_db_data:/var/lib/postgresql/data
networks:
bakery-network:
ipv4_address: 172.20.0.20
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${AUTH_DB_USER} -d ${AUTH_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
training-db:
image: postgres:15-alpine
container_name: bakery-training-db
restart: unless-stopped
environment:
- POSTGRES_DB=${TRAINING_DB_NAME}
- POSTGRES_USER=${TRAINING_DB_USER}
- POSTGRES_PASSWORD=${TRAINING_DB_PASSWORD}
- POSTGRES_INITDB_ARGS=${POSTGRES_INITDB_ARGS}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- training_db_data:/var/lib/postgresql/data
networks:
bakery-network:
ipv4_address: 172.20.0.21
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${TRAINING_DB_USER} -d ${TRAINING_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
forecasting-db:
image: postgres:15-alpine
container_name: bakery-forecasting-db
restart: unless-stopped
environment:
- POSTGRES_DB=${FORECASTING_DB_NAME}
- POSTGRES_USER=${FORECASTING_DB_USER}
- POSTGRES_PASSWORD=${FORECASTING_DB_PASSWORD}
- POSTGRES_INITDB_ARGS=${POSTGRES_INITDB_ARGS}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- forecasting_db_data:/var/lib/postgresql/data
networks:
bakery-network:
ipv4_address: 172.20.0.22
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${FORECASTING_DB_USER} -d ${FORECASTING_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
data-db:
image: postgres:15-alpine
container_name: bakery-data-db
restart: unless-stopped
environment:
- POSTGRES_DB=${DATA_DB_NAME}
- POSTGRES_USER=${DATA_DB_USER}
- POSTGRES_PASSWORD=${DATA_DB_PASSWORD}
- POSTGRES_INITDB_ARGS=${POSTGRES_INITDB_ARGS}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- data_db_data:/var/lib/postgresql/data
networks:
bakery-network:
ipv4_address: 172.20.0.23
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DATA_DB_USER} -d ${DATA_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
tenant-db:
image: postgres:15-alpine
container_name: bakery-tenant-db
restart: unless-stopped
environment:
- POSTGRES_DB=${TENANT_DB_NAME}
- POSTGRES_USER=${TENANT_DB_USER}
- POSTGRES_PASSWORD=${TENANT_DB_PASSWORD}
- POSTGRES_INITDB_ARGS=${POSTGRES_INITDB_ARGS}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- tenant_db_data:/var/lib/postgresql/data
networks:
bakery-network:
ipv4_address: 172.20.0.24
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${TENANT_DB_USER} -d ${TENANT_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
notification-db:
image: postgres:15-alpine
container_name: bakery-notification-db
restart: unless-stopped
environment:
- POSTGRES_DB=${NOTIFICATION_DB_NAME}
- POSTGRES_USER=${NOTIFICATION_DB_USER}
- POSTGRES_PASSWORD=${NOTIFICATION_DB_PASSWORD}
- POSTGRES_INITDB_ARGS=${POSTGRES_INITDB_ARGS}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- notification_db_data:/var/lib/postgresql/data
networks:
bakery-network:
ipv4_address: 172.20.0.25
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${NOTIFICATION_DB_USER} -d ${NOTIFICATION_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
# ================================================================
# LOCATION SERVICES (NEW SECTION)
# ================================================================
nominatim-db:
image: postgis/postgis:15-3.3 # Use PostGIS enabled PostgreSQL image
container_name: bakery-nominatim-db
restart: unless-stopped
environment:
- POSTGRES_DB=${NOMINATIM_DB_NAME}
- POSTGRES_USER=${NOMINATIM_DB_USER}
- POSTGRES_PASSWORD=${NOMINATIM_DB_PASSWORD}
- PGDATA=/var/lib/postgresql/data/pgdata
- POSTGRES_INITDB_ARGS="--auth-host=scram-sha-256" # Recommended for PostGIS
volumes:
- nominatim_db_data:/var/lib/postgresql/data
profiles:
- development
networks:
bakery-network:
ipv4_address: 172.20.0.30 # Assign a static IP for Nominatim to find it
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${NOMINATIM_DB_USER} -d ${NOMINATIM_DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
nominatim:
image: mediagis/nominatim:4.2 # A pre-built Nominatim image
container_name: bakery-nominatim
restart: unless-stopped
env_file: .env # Load environment variables from .env file
environment:
# Database connection details for Nominatim
- POSTGRES_HOST=nominatim-db
- POSTGRES_PORT=5432
- POSTGRES_USER=${NOMINATIM_DB_USER}
- POSTGRES_PASSWORD=${NOMINATIM_DB_PASSWORD}
- POSTGRES_DB=${NOMINATIM_DB_NAME}
- PBF_URL=${NOMINATIM_PBF_URL} # URL to your OpenStreetMap PBF data (e.g., Spain)
ports:
- "${NOMINATIM_PORT}:8080" # Expose Nominatim web interface
volumes:
- nominatim_data:/var/lib/nominatim # Persistent storage for Nominatim data and configuration
networks:
bakery-network:
ipv4_address: 172.20.0.120 # Assign a static IP for Nominatim service
depends_on:
nominatim-db:
condition: service_healthy # Ensure database is ready before Nominatim starts
# By default, mediagis/nominatim image will try to import data on first run
# if PBF_URL is set and the database is empty.
profiles:
- development
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/nominatim/status.php"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: ${NOMINATIM_MEMORY_LIMIT:-8G} # Nominatim is memory-intensive for import
cpus: '${NOMINATIM_CPU_LIMIT:-4}' # Adjust based on your system and data
# ================================================================
# MICROSERVICES - CLEAN APPROACH
# ================================================================
gateway:
build:
context: .
dockerfile: ./gateway/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/gateway:${IMAGE_TAG}
container_name: bakery-gateway
restart: unless-stopped
# ONLY load from .env file - no duplication
env_file: .env
ports:
- "${GATEWAY_PORT}:8000"
depends_on:
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
networks:
bakery-network:
ipv4_address: 172.20.0.100
volumes:
- log_storage:/app/logs
- ./gateway:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
auth-service:
build:
context: .
dockerfile: ./services/auth/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/auth-service:${IMAGE_TAG}
container_name: bakery-auth-service
restart: unless-stopped
# ONLY load from .env file - no duplication
env_file: .env
ports:
- "${AUTH_SERVICE_PORT}:8000"
depends_on:
auth-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
networks:
bakery-network:
ipv4_address: 172.20.0.101
volumes:
- log_storage:/app/logs
- ./services/auth:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
tenant-service:
build:
context: .
dockerfile: ./services/tenant/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/tenant-service:${IMAGE_TAG}
container_name: bakery-tenant-service
restart: unless-stopped
env_file: .env
ports:
- "${TENANT_SERVICE_PORT}:8000"
depends_on:
tenant-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
networks:
bakery-network:
ipv4_address: 172.20.0.105
volumes:
- log_storage:/app/logs
- ./services/tenant:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
training-service:
build:
context: .
dockerfile: ./services/training/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/training-service:${IMAGE_TAG}
container_name: bakery-training-service
restart: unless-stopped
env_file: .env
ports:
- "${TRAINING_SERVICE_PORT}: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:
ipv4_address: 172.20.0.102
volumes:
- log_storage:/app/logs
- model_storage:/app/models
- ./services/training:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: ${TRAINING_MEMORY_LIMIT:-2G}
cpus: '${TRAINING_CPU_LIMIT:-1.5}'
forecasting-service:
build:
context: .
dockerfile: ./services/forecasting/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/forecasting-service:${IMAGE_TAG}
container_name: bakery-forecasting-service
restart: unless-stopped
env_file: .env
ports:
- "${FORECASTING_SERVICE_PORT}: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:
ipv4_address: 172.20.0.103
volumes:
- log_storage:/app/logs
- model_storage:/app/models
- ./services/forecasting:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
data-service:
build:
context: .
dockerfile: ./services/data/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/data-service:${IMAGE_TAG}
container_name: bakery-data-service
restart: unless-stopped
env_file: .env
ports:
- "${DATA_SERVICE_PORT}:8000"
depends_on:
data-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
networks:
bakery-network:
ipv4_address: 172.20.0.104
volumes:
- log_storage:/app/logs
- ./services/data:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
notification-service:
build:
context: .
dockerfile: ./services/notification/Dockerfile
args:
- ENVIRONMENT=${ENVIRONMENT}
- BUILD_DATE=${BUILD_DATE}
image: bakery/notification-service:${IMAGE_TAG}
container_name: bakery-notification-service
restart: unless-stopped
env_file: .env
ports:
- "${NOTIFICATION_SERVICE_PORT}:8000"
depends_on:
notification-db:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
auth-service:
condition: service_healthy
networks:
bakery-network:
ipv4_address: 172.20.0.106
volumes:
- log_storage:/app/logs
- ./services/notification:/app
- ./shared:/app/shared
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
# ================================================================
# MONITORING - SIMPLE APPROACH
# ================================================================
prometheus:
image: prom/prometheus:v2.45.0
container_name: bakery-prometheus
restart: unless-stopped
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=${PROMETHEUS_RETENTION:-200h}'
- '--web.enable-lifecycle'
ports:
- "${PROMETHEUS_PORT}:9090"
volumes:
- ./infrastructure/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
networks:
bakery-network:
ipv4_address: 172.20.0.200
grafana:
image: grafana/grafana:10.0.0
container_name: bakery-grafana
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER}
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
- GF_DEFAULT_TIMEZONE=${TIMEZONE}
- GF_SERVER_ROOT_URL=${GRAFANA_ROOT_URL}
ports:
- "${GRAFANA_PORT}:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./infrastructure/monitoring/grafana:/etc/grafana/provisioning:ro
networks:
bakery-network:
ipv4_address: 172.20.0.201
depends_on:
- prometheus
# ================================================================
# FRONTEND - CLEAN CONFIG
# ================================================================
dashboard:
build:
context: ./frontend
dockerfile: Dockerfile.${ENVIRONMENT}
args:
- REACT_APP_API_URL=${FRONTEND_API_URL}
- REACT_APP_WS_URL=${FRONTEND_WS_URL}
- REACT_APP_ENVIRONMENT=${ENVIRONMENT}
image: bakery/dashboard:${IMAGE_TAG}
container_name: bakery-dashboard
restart: unless-stopped
ports:
- "${DASHBOARD_PORT}:3000"
depends_on:
gateway:
condition: service_healthy
networks:
bakery-network:
ipv4_address: 172.20.0.110
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/"]
interval: 30s
timeout: 10s
retries: 3
# ================================================================
# DEVELOPMENT TOOLS - OPTIONAL
# ================================================================
pgadmin:
image: dpage/pgadmin4:7.4
container_name: bakery-pgadmin
restart: unless-stopped
environment:
- PGADMIN_DEFAULT_EMAIL=${PGADMIN_EMAIL}
- PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PASSWORD}
- PGADMIN_CONFIG_SERVER_MODE=False
ports:
- "${PGADMIN_PORT}:80"
volumes:
- ./infrastructure/pgadmin/servers.json:/pgadmin4/servers.json:ro
networks:
- bakery-network
profiles:
- development
- admin
redis-commander:
image: rediscommander/redis-commander:latest
container_name: bakery-redis-commander
restart: unless-stopped
environment:
- REDIS_HOSTS=local:redis:6379:0:${REDIS_PASSWORD}
- HTTP_USER=${REDIS_COMMANDER_USER}
- HTTP_PASSWORD=${REDIS_COMMANDER_PASSWORD}
ports:
- "${REDIS_COMMANDER_PORT}:8081"
networks:
- bakery-network
profiles:
- development
- admin
depends_on:
- redis