# Stack Docker Swarm — deploy via `docker stack deploy -c docker-compose.yml databisnisid` # # 5 service: mariadb (storage, internal), web (dashboard gunicorn, publik :5000), # scan (skan get_voters.py pada SCAN_HOURS, waktu lokal TZ), # distribute (pembayaran harian distribute.py pada DISTRIBUTE_HOUR), dan # claim (klaim reward BP harian claim_loop.py + fee 10% ke VEX_BP_FEE_WALLET). # # Catatan swarm: # - `build:` hanya untuk `docker compose build`; `docker stack deploy` memakai `image:` # (harus dibangun lebih dulu; multi-node perlu registry). # - `env_file` ⊥ didukung stack → environment inline dgn interpolasi `.env`. # - Tanpa `container_name`/`restart:` — pakai `deploy.restart_policy`. services: mariadb: image: mariadb:11 environment: MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD:-root} MARIADB_DATABASE: ${MARIADB_DATABASE:-databisnisid} MARIADB_USER: ${MARIADB_USER:-databisnis} MARIADB_PASSWORD: ${MARIADB_PASSWORD:-databisnis} volumes: - /data/db/mariadb/databisnisid/data:/var/lib/mysql networks: - appnet healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 5s timeout: 5s retries: 12 deploy: replicas: 1 placement: constraints: - node.hostname == server5.saltis.id restart_policy: condition: any web: image: git.proit.id/proitlab/databisnisid-web:latest environment: VEX_DB_BACKEND: mysql VEX_DB_HOST: mariadb VEX_DB_PORT: "3306" VEX_DB_USER: ${MARIADB_USER:-databisnis} VEX_DB_PASS: ${MARIADB_PASSWORD:-databisnis} VEX_DB_NAME: ${MARIADB_DATABASE:-databisnisid} DASH_HOST: "0.0.0.0" # wajib di container → gunicorn bind terbuka utk ingress DASH_PORT: "5000" DASH_WORKERS: "2" DATABISNIS_API: ${DATABISNIS_API:-https://api.databisnis.id} DASH_LIQUID_TTL: "60" TZ: ${TZ:-Asia/Jakarta} DISTRIBUTE_HOUR: ${DISTRIBUTE_HOUR:-10} DISTRIBUTE_WEEKDAY: ${DISTRIBUTE_WEEKDAY:-sat} DISTRIBUTE_FIRST_RUN: ${DISTRIBUTE_FIRST_RUN:-2026-08-17} ports: - published: 5000 target: 5000 networks: - appnet healthcheck: test: ["CMD", "python", "-c", "import socket,sys;sys.exit(0 if socket.create_connection(('127.0.0.1',5000),5) else 1)"] interval: 30s timeout: 5s retries: 3 start_period: 20s deploy: replicas: 1 placement: constraints: - node.hostname != server2U restart_policy: condition: any scan: image: git.proit.id/proitlab/databisnisid-scan:latest command: ["python", "scan_loop.py"] environment: VEX_DB_BACKEND: mysql VEX_DB_HOST: mariadb VEX_DB_PORT: "3306" VEX_DB_USER: ${MARIADB_USER:-databisnis} VEX_DB_PASS: ${MARIADB_PASSWORD:-databisnis} VEX_DB_NAME: ${MARIADB_DATABASE:-databisnisid} TZ: ${TZ:-Asia/Jakarta} SCAN_HOURS: ${SCAN_HOURS:-0,8,16} SCAN_RUN_ON_START: ${SCAN_RUN_ON_START:-1} networks: - appnet deploy: replicas: 1 placement: constraints: - node.hostname != server2U restart_policy: condition: any distribute: image: git.proit.id/proitlab/databisnisid-dist:latest command: ["python", "distribute_loop.py"] environment: VEX_DB_BACKEND: mysql VEX_DB_HOST: mariadb VEX_DB_PORT: "3306" VEX_DB_USER: ${MARIADB_USER:-databisnis} VEX_DB_PASS: ${MARIADB_PASSWORD:-databisnis} VEX_DB_NAME: ${MARIADB_DATABASE:-databisnisid} TZ: ${TZ:-Asia/Jakarta} DISTRIBUTE_HOUR: ${DISTRIBUTE_HOUR:-10} DISTRIBUTE_WEEKDAY: ${DISTRIBUTE_WEEKDAY:-sat} DISTRIBUTE_FIRST_RUN: ${DISTRIBUTE_FIRST_RUN:-2026-08-17} DISTRIBUTE_MAX_ATTEMPTS: ${DISTRIBUTE_MAX_ATTEMPTS:-3} DISTRIBUTE_ENABLED: ${DISTRIBUTE_ENABLED:-false} DATABISNIS_API: ${DATABISNIS_API:-https://api.databisnis.id} volumes: - /mnt/nfs/server5.saltis.id/data/databisnisid/app/config.env:/app/.env:ro networks: - appnet deploy: replicas: 1 placement: constraints: - node.hostname != server2U restart_policy: condition: any claim: image: git.proit.id/proitlab/databisnisid-claim:latest command: ["python", "claim_loop.py"] environment: VEX_DB_BACKEND: mysql VEX_DB_HOST: mariadb VEX_DB_PORT: "3306" VEX_DB_USER: ${MARIADB_USER:-databisnis} VEX_DB_PASS: ${MARIADB_PASSWORD:-databisnis} VEX_DB_NAME: ${MARIADB_DATABASE:-databisnisid} TZ: ${TZ:-Asia/Jakarta} CLAIM_RETRY_SECONDS: ${CLAIM_RETRY_SECONDS:-60} VEX_BP_FEE_WALLET: ${VEX_BP_FEE_WALLET:-bpdbsjasprod} VEX_BP_FEE_PERCENT: ${VEX_BP_FEE_PERCENT:-0.10} DATABISNIS_API: ${DATABISNIS_API:-https://api.databisnis.id} volumes: - /mnt/nfs/server5.saltis.id/data/databisnisid/app/config.env:/app/.env:ro networks: - appnet deploy: replicas: 1 placement: constraints: - node.hostname != server2U restart_policy: condition: any networks: appnet: driver: overlay