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 # Poller tuning. These were documented in .env.example but never passed # through, so setting them had no effect on the container at all. POLLER_CONCURRENCY: ${POLLER_CONCURRENCY:-12} POLLER_JOB_TIMEOUT_MS: ${POLLER_JOB_TIMEOUT_MS:-45000} POLLER_INTERVAL_MS: ${POLLER_INTERVAL_MS:-30000} POLLER_JOB_RETENTION_SEC: ${POLLER_JOB_RETENTION_SEC:-3600} POLLER_JOB_RETENTION_COUNT: ${POLLER_JOB_RETENTION_COUNT:-5000} 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, with # eviction disabled. # # volatile-lru looks tempting — it would evict only keys with an expiry, and # BullMQ's job hashes have none. But its *control* keys do: job locks and # per-queue stalled-check markers both carry TTLs, and losing one causes # duplicate processing or a stalled-job storm. BullMQ warns about this on # connect, and it is right. noeviction means Redis refuses writes when full # rather than quietly corrupting queue state: the host stays up, and the # failure is loud. Retention limits and the stale-pending sweep are what keep # us away from the ceiling in the first place. command: > redis-server --appendonly yes --maxmemory ${REDIS_MAXMEMORY:-512mb} --maxmemory-policy noeviction 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