| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| name: optim-ai-bre |
|
|
| |
| |
| |
| networks: |
| bre-public: |
| driver: bridge |
| bre-internal: |
| driver: bridge |
| internal: true |
|
|
| |
| |
| |
| volumes: |
| postgres-data: |
| driver: local |
| name: bre_postgres_data |
|
|
| redis-data: |
| driver: local |
| name: bre_redis_data |
|
|
| backend-logs: |
| driver: local |
| name: bre_backend_logs |
|
|
| backend-reports: |
| driver: local |
| name: bre_backend_reports |
|
|
| nginx-logs: |
| driver: local |
| name: bre_nginx_logs |
|
|
| db-backups: |
| driver: local |
| name: bre_db_backups |
|
|
| |
| |
| |
| services: |
|
|
| |
| |
| |
| |
| |
| bre-nginx: |
| image: nginx:${NGINX_VERSION:-1.25-alpine} |
| container_name: bre-nginx |
| restart: unless-stopped |
| ports: |
| - "80:80" |
| - "443:443" |
| volumes: |
| - ./docker/nginx.conf:/etc/nginx/nginx.conf:ro |
| - nginx-logs:/var/log/nginx |
| |
| |
| networks: |
| - bre-public |
| - bre-internal |
| depends_on: |
| bre-backend: |
| condition: service_healthy |
| bre-frontend: |
| condition: service_healthy |
| healthcheck: |
| test: ["CMD", "wget", "-qO-", "http://localhost/nginx-health"] |
| interval: 30s |
| timeout: 10s |
| retries: 3 |
| start_period: 15s |
| logging: |
| driver: json-file |
| options: |
| max-size: "10m" |
| max-file: "5" |
|
|
| |
| |
| |
| |
| bre-backend: |
| build: |
| context: ./src/backend |
| dockerfile: ../../docker/Dockerfile.backend |
| image: optim-ai-bre/backend:latest |
| container_name: bre-backend |
| restart: unless-stopped |
| networks: |
| - bre-internal |
| environment: |
| ASPNETCORE_ENVIRONMENT: Production |
| ASPNETCORE_URLS: http://+:8080 |
| DOTNET_RUNNING_IN_CONTAINER: "true" |
|
|
| |
| ConnectionStrings__PostgreSQL: >- |
| Host=bre-postgres;Port=5432; |
| Database=${POSTGRES_DB:-optimai_bre}; |
| Username=${POSTGRES_USER:-optimai}; |
| Password=${POSTGRES_PASSWORD}; |
| Pooling=true;Minimum Pool Size=5;Maximum Pool Size=100; |
| Connection Lifetime=300;Keepalive=60 |
| ConnectionStrings__Redis: >- |
| bre-redis:6379, |
| password=${REDIS_PASSWORD}, |
| abortConnect=false, |
| connectRetry=3, |
| connectTimeout=5000, |
| syncTimeout=5000 |
| |
| |
| Jwt__SecretKey: ${JWT_SECRET_KEY} |
| Jwt__Issuer: ${JWT_ISSUER:-OptimAI.BRE} |
| Jwt__Audience: ${JWT_AUDIENCE:-OptimAI.BRE.Clients} |
| Jwt__AccessTokenExpiryMinutes: ${JWT_ACCESS_TOKEN_EXPIRY_MINUTES:-480} |
| Jwt__RefreshTokenExpiryDays: ${JWT_REFRESH_TOKEN_EXPIRY_DAYS:-30} |
|
|
| |
| AiOptions__UseAzureOpenAI: ${USE_AZURE_OPENAI:-false} |
| AiOptions__Endpoint: ${AZURE_OPENAI_ENDPOINT:-} |
| AiOptions__ApiKey: ${AZURE_OPENAI_KEY:-} |
| AiOptions__ModelName: ${AZURE_OPENAI_MODEL:-gpt-4o} |
|
|
| |
| AllowedOrigins__0: ${APP_DOMAIN:-http://localhost} |
| AllowedOrigins__1: http://bre-frontend:3000 |
|
|
| |
| RuleEngine__MaxConcurrentExecutions: ${RULE_ENGINE_MAX_CONCURRENT:-100} |
| RuleEngine__DefaultTimeoutMs: ${RULE_ENGINE_TIMEOUT_MS:-5000} |
| RuleEngine__EnableAiByDefault: "false" |
| RuleEngine__CacheRulesTtlMinutes: ${RULE_ENGINE_CACHE_TTL_MINUTES:-5} |
|
|
| |
| Serilog__MinimumLevel__Default: ${LOG_LEVEL:-Information} |
|
|
| volumes: |
| - backend-logs:/app/logs |
| - backend-reports:/app/reports |
| depends_on: |
| bre-postgres: |
| condition: service_healthy |
| bre-redis: |
| condition: service_healthy |
| healthcheck: |
| test: ["CMD", "curl", "-f", "http://localhost:8080/health"] |
| interval: 30s |
| timeout: 15s |
| retries: 5 |
| start_period: 60s |
| logging: |
| driver: json-file |
| options: |
| max-size: "20m" |
| max-file: "10" |
|
|
| |
| |
| |
| |
| |
| bre-frontend: |
| build: |
| context: ./src/frontend/optim-ai-bre-ui |
| dockerfile: ../../../docker/Dockerfile.frontend |
| args: |
| NEXT_PUBLIC_API_URL: /api/v1 |
| image: optim-ai-bre/frontend:latest |
| container_name: bre-frontend |
| restart: unless-stopped |
| networks: |
| - bre-internal |
| environment: |
| NODE_ENV: production |
| NEXT_TELEMETRY_DISABLED: "1" |
| PORT: "3000" |
| HOSTNAME: "0.0.0.0" |
| healthcheck: |
| test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"] |
| interval: 30s |
| timeout: 10s |
| retries: 3 |
| start_period: 30s |
| logging: |
| driver: json-file |
| options: |
| max-size: "10m" |
| max-file: "5" |
|
|
| |
| |
| |
| |
| |
| bre-postgres: |
| image: postgres:${POSTGRES_VERSION:-15-alpine} |
| container_name: bre-postgres |
| restart: unless-stopped |
| networks: |
| - bre-internal |
| environment: |
| POSTGRES_DB: ${POSTGRES_DB:-optimai_bre} |
| POSTGRES_USER: ${POSTGRES_USER:-optimai} |
| POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} |
| POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C" |
| PGDATA: /var/lib/postgresql/data/pgdata |
| volumes: |
| |
| - postgres-data:/var/lib/postgresql/data |
| |
| - ./docker/postgres-init:/docker-entrypoint-initdb.d/init:ro |
| - ./database/migrations:/docker-entrypoint-initdb.d/migrations:ro |
| |
| - db-backups:/backups |
| healthcheck: |
| test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-optimai} -d ${POSTGRES_DB:-optimai_bre}"] |
| interval: 10s |
| timeout: 5s |
| retries: 10 |
| start_period: 30s |
| command: > |
| postgres |
| -c max_connections=200 |
| -c shared_buffers=256MB |
| -c effective_cache_size=768MB |
| -c maintenance_work_mem=64MB |
| -c checkpoint_completion_target=0.9 |
| -c wal_buffers=16MB |
| -c default_statistics_target=100 |
| -c random_page_cost=1.1 |
| -c effective_io_concurrency=200 |
| -c work_mem=4MB |
| -c min_wal_size=1GB |
| -c max_wal_size=4GB |
| -c log_min_duration_statement=1000 |
| -c log_line_prefix='%t [%p] %u@%d ' |
| logging: |
| driver: json-file |
| options: |
| max-size: "10m" |
| max-file: "5" |
|
|
| |
| |
| |
| |
| |
| bre-redis: |
| image: redis:${REDIS_VERSION:-7-alpine} |
| container_name: bre-redis |
| restart: unless-stopped |
| networks: |
| - bre-internal |
| command: > |
| redis-server |
| --requirepass ${REDIS_PASSWORD} |
| --maxmemory 512mb |
| --maxmemory-policy allkeys-lru |
| --save 900 1 |
| --save 300 10 |
| --save 60 10000 |
| --appendonly yes |
| --appendfsync everysec |
| --loglevel notice |
| volumes: |
| - redis-data:/data |
| healthcheck: |
| test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] |
| interval: 10s |
| timeout: 5s |
| retries: 5 |
| start_period: 10s |
| logging: |
| driver: json-file |
| options: |
| max-size: "5m" |
| max-file: "3" |
|
|
| |
| |
| |
| |
| |
| bre-db-backup: |
| image: postgres:${POSTGRES_VERSION:-15-alpine} |
| container_name: bre-db-backup |
| restart: unless-stopped |
| networks: |
| - bre-internal |
| environment: |
| PGPASSWORD: ${POSTGRES_PASSWORD} |
| POSTGRES_DB: ${POSTGRES_DB:-optimai_bre} |
| POSTGRES_USER: ${POSTGRES_USER:-optimai} |
| volumes: |
| - db-backups:/backups |
| entrypoint: > |
| sh -c ' |
| while true; do |
| TIMESTAMP=$$(date +%Y%m%d_%H%M%S) |
| BACKUP_FILE="/backups/bre_backup_$$TIMESTAMP.sql.gz" |
| echo "[$$TIMESTAMP] Starting database backup..." |
| pg_dump -h bre-postgres -U $$POSTGRES_USER -d $$POSTGRES_DB | gzip > $$BACKUP_FILE |
| echo "[$$TIMESTAMP] Backup saved: $$BACKUP_FILE" |
| # Delete backups older than 7 days |
| find /backups -name "bre_backup_*.sql.gz" -mtime +7 -delete |
| echo "[$$TIMESTAMP] Old backups cleaned. Sleeping 24h..." |
| sleep 86400 |
| done |
| ' |
| depends_on: |
| bre-postgres: |
| condition: service_healthy |
| logging: |
| driver: json-file |
| options: |
| max-size: "5m" |
| max-file: "3" |
|
|