services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine restart: unless-stopped chat-postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: ${CHAT_POSTGRES_DB} POSTGRES_USER: ${CHAT_POSTGRES_USER} POSTGRES_PASSWORD: ${CHAT_POSTGRES_PASSWORD} volumes: - chat_postgres_data:/var/lib/postgresql/data postgres-backup: image: postgres:16-alpine restart: unless-stopped depends_on: - postgres - chat-postgres environment: TZ: ${BACKUP_TZ:-Europe/Moscow} BACKUP_DIR: /backups BACKUP_INTERVAL_SECONDS: ${BACKUP_INTERVAL_SECONDS:-86400} BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-7} BACKUP_GZIP_LEVEL: ${BACKUP_GZIP_LEVEL:-6} BACKUP_INCLUDE_CHAT_DB: ${BACKUP_INCLUDE_CHAT_DB:-true} POSTGRES_HOST: postgres POSTGRES_PORT: 5432 POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} CHAT_POSTGRES_HOST: chat-postgres CHAT_POSTGRES_PORT: 5432 CHAT_POSTGRES_DB: ${CHAT_POSTGRES_DB} CHAT_POSTGRES_USER: ${CHAT_POSTGRES_USER} CHAT_POSTGRES_PASSWORD: ${CHAT_POSTGRES_PASSWORD} command: ["/bin/sh", "/scripts/pg-backup.sh"] volumes: - ./scripts/pg-backup.sh:/scripts/pg-backup.sh:ro - ./backups:/backups adminer: image: adminer:5 restart: unless-stopped depends_on: - postgres expose: - "8080" networks: - default - proxy labels: - traefik.enable=true - traefik.docker.network=proxy - traefik.http.routers.alpinbet-adminer.rule=Host(`db.antigol.ru`) - traefik.http.routers.alpinbet-adminer.entrypoints=websecure - traefik.http.routers.alpinbet-adminer.tls.certresolver=letsencrypt - traefik.http.services.alpinbet-adminer.loadbalancer.server.port=8080 dockmon: image: darthnorse/dockmon:latest restart: unless-stopped environment: TZ: Europe/Moscow PYTHONPATH: /app/backend PYTHONUNBUFFERED: 1 REVERSE_PROXY_MODE: "true" DOCKMON_EXTERNAL_URL: https://monitor.antigol.ru DOCKMON_CORS_ORIGINS: https://monitor.antigol.ru expose: - "80" volumes: - dockmon_data:/app/data - /var/run/docker.sock:/var/run/docker.sock networks: - default - proxy labels: - traefik.enable=true - traefik.docker.network=proxy - traefik.http.routers.alpinbet-dockmon.rule=Host(`monitor.antigol.ru`) - traefik.http.routers.alpinbet-dockmon.entrypoints=websecure - traefik.http.routers.alpinbet-dockmon.tls.certresolver=letsencrypt - traefik.http.services.alpinbet-dockmon.loadbalancer.server.port=80 backend: build: context: ./backend restart: unless-stopped depends_on: - postgres - redis command: npm run start:api:with-db-url environment: REDIS_URL: redis://redis:6379 POSTGRES_HOST: postgres POSTGRES_PORT: 5432 POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_SCHEMA: public PORT: 4000 JWT_SECRET: ${JWT_SECRET} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d} CORS_ORIGIN: ${CORS_ORIGIN} APP_PUBLIC_URL: ${APP_PUBLIC_URL} SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_SECURE: ${SMTP_SECURE:-false} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-} SMTP_FROM_NAME: ${SMTP_FROM_NAME:-Alpinbet} PASSWORD_RESET_TTL_MINUTES: ${PASSWORD_RESET_TTL_MINUTES:-60} APP_LATEST_VERSION: ${APP_LATEST_VERSION:-} APP_MIN_SUPPORTED_VERSION: ${APP_MIN_SUPPORTED_VERSION:-} APP_UPDATE_URL: ${APP_UPDATE_URL:-} APP_UPDATE_MESSAGE: ${APP_UPDATE_MESSAGE:-} VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY:-} VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY:-} VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:admin@example.com} FIREBASE_PROJECT_ID: ${FIREBASE_PROJECT_ID:-} FIREBASE_CLIENT_EMAIL: ${FIREBASE_CLIENT_EMAIL:-} FIREBASE_PRIVATE_KEY: ${FIREBASE_PRIVATE_KEY:-} FIREBASE_SERVICE_ACCOUNT_JSON: ${FIREBASE_SERVICE_ACCOUNT_JSON:-} SETTLEMENT_INTERVAL_MS: ${SETTLEMENT_INTERVAL_MS:-60000} PARSER_INTERNAL_SECRET: ${PARSER_INTERNAL_SECRET} VAPID_STATE_DIR: /app/runtime expose: - "4000" volumes: - backend_runtime:/app/runtime networks: - default - proxy labels: - traefik.enable=true - traefik.docker.network=proxy - traefik.http.routers.alpinbet-backend.rule=Host(`api.antigol.ru`) - traefik.http.routers.alpinbet-backend.entrypoints=websecure - traefik.http.routers.alpinbet-backend.tls.certresolver=letsencrypt - traefik.http.services.alpinbet-backend.loadbalancer.server.port=4000 backend-signals-worker: build: context: ./backend restart: unless-stopped depends_on: - postgres - redis command: npm run start:signals-worker:with-db-url environment: REDIS_URL: redis://redis:6379 POSTGRES_HOST: postgres POSTGRES_PORT: 5432 POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_SCHEMA: public PORT: 4000 JWT_SECRET: ${JWT_SECRET} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d} CORS_ORIGIN: ${CORS_ORIGIN} APP_PUBLIC_URL: ${APP_PUBLIC_URL} SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_SECURE: ${SMTP_SECURE:-false} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-} SMTP_FROM_NAME: ${SMTP_FROM_NAME:-Alpinbet} PASSWORD_RESET_TTL_MINUTES: ${PASSWORD_RESET_TTL_MINUTES:-60} APP_LATEST_VERSION: ${APP_LATEST_VERSION:-} APP_MIN_SUPPORTED_VERSION: ${APP_MIN_SUPPORTED_VERSION:-} APP_UPDATE_URL: ${APP_UPDATE_URL:-} APP_UPDATE_MESSAGE: ${APP_UPDATE_MESSAGE:-} VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY:-} VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY:-} VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:admin@example.com} FIREBASE_PROJECT_ID: ${FIREBASE_PROJECT_ID:-} FIREBASE_CLIENT_EMAIL: ${FIREBASE_CLIENT_EMAIL:-} FIREBASE_PRIVATE_KEY: ${FIREBASE_PRIVATE_KEY:-} FIREBASE_SERVICE_ACCOUNT_JSON: ${FIREBASE_SERVICE_ACCOUNT_JSON:-} SETTLEMENT_INTERVAL_MS: ${SETTLEMENT_INTERVAL_MS:-60000} PARSER_INTERNAL_SECRET: ${PARSER_INTERNAL_SECRET} VAPID_STATE_DIR: /app/runtime volumes: - backend_runtime:/app/runtime backend-push-worker: build: context: ./backend restart: unless-stopped depends_on: - postgres - redis command: npm run start:push-worker:with-db-url environment: REDIS_URL: redis://redis:6379 POSTGRES_HOST: postgres POSTGRES_PORT: 5432 POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_SCHEMA: public PORT: 4000 JWT_SECRET: ${JWT_SECRET} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d} CORS_ORIGIN: ${CORS_ORIGIN} APP_PUBLIC_URL: ${APP_PUBLIC_URL} SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_SECURE: ${SMTP_SECURE:-false} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-} SMTP_FROM_NAME: ${SMTP_FROM_NAME:-Alpinbet} PASSWORD_RESET_TTL_MINUTES: ${PASSWORD_RESET_TTL_MINUTES:-60} APP_LATEST_VERSION: ${APP_LATEST_VERSION:-} APP_MIN_SUPPORTED_VERSION: ${APP_MIN_SUPPORTED_VERSION:-} APP_UPDATE_URL: ${APP_UPDATE_URL:-} APP_UPDATE_MESSAGE: ${APP_UPDATE_MESSAGE:-} VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY:-} VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY:-} VAPID_SUBJECT: ${VAPID_SUBJECT:-mailto:admin@example.com} FIREBASE_PROJECT_ID: ${FIREBASE_PROJECT_ID:-} FIREBASE_CLIENT_EMAIL: ${FIREBASE_CLIENT_EMAIL:-} FIREBASE_PRIVATE_KEY: ${FIREBASE_PRIVATE_KEY:-} FIREBASE_SERVICE_ACCOUNT_JSON: ${FIREBASE_SERVICE_ACCOUNT_JSON:-} SETTLEMENT_INTERVAL_MS: ${SETTLEMENT_INTERVAL_MS:-60000} PARSER_INTERNAL_SECRET: ${PARSER_INTERNAL_SECRET} VAPID_STATE_DIR: /app/runtime volumes: - backend_runtime:/app/runtime chat-service: build: context: ./chat-service restart: unless-stopped depends_on: - chat-postgres command: npm run start:with-db-url environment: CHAT_POSTGRES_HOST: chat-postgres CHAT_POSTGRES_PORT: 5432 CHAT_POSTGRES_DB: ${CHAT_POSTGRES_DB} CHAT_POSTGRES_USER: ${CHAT_POSTGRES_USER} CHAT_POSTGRES_PASSWORD: ${CHAT_POSTGRES_PASSWORD} CHAT_POSTGRES_SCHEMA: public PORT: 4050 JWT_SECRET: ${JWT_SECRET} CORS_ORIGIN: ${CORS_ORIGIN} expose: - "4050" networks: - default - proxy labels: - traefik.enable=true - traefik.docker.network=proxy - traefik.http.routers.alpinbet-chat.rule=Host(`chat.antigol.ru`) - traefik.http.routers.alpinbet-chat.entrypoints=websecure - traefik.http.routers.alpinbet-chat.tls.certresolver=letsencrypt - traefik.http.services.alpinbet-chat.loadbalancer.server.port=4050 parser: build: context: . dockerfile: ./parser/Dockerfile depends_on: - redis - forecast-ocr command: npm run start env_file: - ./parser/.env environment: REDIS_URL: redis://redis:6379 BACKEND_INTERNAL_URL: http://backend:4000 PARSER_INTERNAL_SECRET: ${PARSER_INTERNAL_SECRET} FORECAST_OCR_URL: http://forecast-ocr:4010 volumes: - ./parser/data:/app/parser/data restart: unless-stopped forecast-ocr: build: context: ./forecast-ocr-service restart: unless-stopped expose: - "4010" frontend: build: context: ./frontend depends_on: - backend - chat-service environment: NUXT_PUBLIC_API_BASE: ${NUXT_PUBLIC_API_BASE} NUXT_PUBLIC_CHAT_API_BASE: ${NUXT_PUBLIC_CHAT_API_BASE} NUXT_API_BASE_INTERNAL: http://backend:4000 expose: - "3000" networks: - default - proxy labels: - traefik.enable=true - traefik.docker.network=proxy - traefik.http.routers.alpinbet-frontend.rule=Host(`antigol.ru`) - traefik.http.routers.alpinbet-frontend.entrypoints=websecure - traefik.http.routers.alpinbet-frontend.tls.certresolver=letsencrypt - traefik.http.services.alpinbet-frontend.loadbalancer.server.port=3000 downloads: build: context: ./downloads-service restart: unless-stopped expose: - "8080" volumes: - ./downloads:/app/downloads:ro networks: - default - proxy labels: - traefik.enable=true - traefik.docker.network=proxy - traefik.http.routers.alpinbet-downloads.rule=Host(`files.antigol.ru`) - traefik.http.routers.alpinbet-downloads.entrypoints=websecure - traefik.http.routers.alpinbet-downloads.tls.certresolver=letsencrypt - traefik.http.services.alpinbet-downloads.loadbalancer.server.port=8080 volumes: postgres_data: chat_postgres_data: backend_runtime: dockmon_data: networks: proxy: external: true