version: '3.8' services: nginx: build: context: . dockerfile: nginx/Dockerfile ports: - "${HTTP_PORT:-80}:80" - "${HTTPS_PORT:-443}:443" volumes: - certs_data:/certs depends_on: backend: condition: service_healthy restart: unless-stopped networks: - app-network backend: build: context: ./backend dockerfile: Dockerfile environment: NODE_ENV: production TZ: ${TZ:-UTC} DATABASE_URL: postgresql://mikrotik:${DB_PASSWORD:-mikrotik_secure_pw}@postgres:5432/mikrotik_manager REDIS_URL: redis://redis:6379 INFLUXDB_URL: http://influxdb:8086 INFLUXDB_TOKEN: ${INFLUXDB_TOKEN:-mytoken123456789} INFLUXDB_ORG: ${INFLUXDB_ORG:-mikrotik-manager} INFLUXDB_BUCKET: ${INFLUXDB_BUCKET:-metrics} # Leave unset to auto-generate & persist strong secrets on first boot # (stored in the app_data volume). Set them to pin your own values. JWT_SECRET: ${JWT_SECRET:-} ENCRYPTION_KEY: ${ENCRYPTION_KEY:-} CORS_ORIGIN: ${CORS_ORIGIN:-https://localhost,http://localhost,https://127.0.0.1,http://127.0.0.1} PORT: 3001 NETFLOW_BIND_PORT: 2055 ports: # NetFlow/IPFIX collector — UDP goes straight to the backend (nginx not involved). # Host port must match the netflow_collector_port app setting (default 2055). - "${NETFLOW_PORT:-2055}:2055/udp" depends_on: postgres: condition: service_healthy redis: condition: service_healthy influxdb: condition: service_healthy volumes: - backups_data:/app/backups - certs_data:/certs - app_data:/app/data cap_add: - NET_RAW restart: unless-stopped networks: - app-network healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3001/api/health"] interval: 15s timeout: 10s retries: 5 start_period: 30s postgres: image: postgres:15-alpine environment: TZ: ${TZ:-UTC} POSTGRES_DB: mikrotik_manager POSTGRES_USER: mikrotik POSTGRES_PASSWORD: ${DB_PASSWORD:-mikrotik_secure_pw} volumes: - postgres_data:/var/lib/postgresql/data restart: unless-stopped networks: - app-network healthcheck: test: ["CMD-SHELL", "pg_isready -U mikrotik -d mikrotik_manager"] interval: 10s timeout: 5s retries: 5 start_period: 10s redis: image: redis:7-alpine # A memory ceiling so a runaway producer can never take the host down. The # eviction policy is deliberately volatile-lru rather than allkeys-*: BullMQ # job data carries no TTL and must never be evicted (that would silently # destroy queued work), while the poller's caches and in-flight claims all # set one and are safe to drop. If pressure ever exhausts the volatile keys # Redis refuses writes instead of evicting queue state — loud, and survivable. command: > redis-server --appendonly yes --maxmemory ${REDIS_MAXMEMORY:-512mb} --maxmemory-policy volatile-lru volumes: - redis_data:/data restart: unless-stopped networks: - app-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 influxdb: image: influxdb:2.7 environment: DOCKER_INFLUXDB_INIT_MODE: setup DOCKER_INFLUXDB_INIT_USERNAME: admin DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_ADMIN_PASSWORD:-admin_password_123} DOCKER_INFLUXDB_INIT_ORG: ${INFLUXDB_ORG:-mikrotik-manager} DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUXDB_BUCKET:-metrics} DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUXDB_TOKEN:-mytoken123456789} volumes: - influxdb_data:/var/lib/influxdb2 restart: unless-stopped networks: - app-network healthcheck: test: ["CMD", "influx", "ping"] interval: 15s timeout: 10s retries: 10 start_period: 30s volumes: postgres_data: redis_data: influxdb_data: backups_data: certs_data: app_data: networks: app-network: driver: bridge