Files
tiennm99bot/compose.yml
T

90 lines
4.6 KiB
YAML

services:
bot:
build:
context: .
# Or pin a prebuilt image instead of building:
# image: ghcr.io/tiennm99/miti99bot:latest
restart: unless-stopped
environment:
# --- Required ---
TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} # from @BotFather — SECRET
MONGO_URL: ${MONGO_URL} # Atlas SRV string incl. credentials — SECRET
MONGO_DATABASE: ${MONGO_DATABASE} # e.g. miti99bot
# --- Access control (optional; empty uses the default) ---
MODULES: ${MODULES} # CSV of modules; default: all modules
OWNER_ID: ${OWNER_ID} # Telegram user id for owner-only commands; default: none
ADMIN_IDS: ${ADMIN_IDS} # CSV of admin Telegram user ids; default: none
# --- Module settings (optional; empty uses the default) ---
LOL_PANDASCORE_TOKEN: ${LOL_PANDASCORE_TOKEN} # PandaScore token — SECRET; default: none (/lol* fetches fail)
GOLD_VNAPP_API_KEY: ${GOLD_VNAPP_API_KEY} # VNAppMob key — SECRET; default: fetched and cached in Mongo
STICKER_PACK_NAME: ${STICKER_PACK_NAME} # /addsticker set; default: miti99_by_miti99bot
# --- Runtime (optional; empty uses the default) ---
LOG_LEVEL: ${LOG_LEVEL} # debug|info|warn|error; default: info
# --- Fixed by this stack (not Coolify settings) ---
# The bundled renderer service below draws /wheelofnames, /gacha and
# /genshin. Its base URL is fixed to the in-network address so a stale
# platform-level value cannot point the bot elsewhere; the bot appends
# each /api/<name> route itself.
RENDERER_URL: http://renderer:3000
# --- Deliberately not declared ---
# SOURCE_COMMIT: Coolify provides it at runtime via its generated env
# file; declaring it here with Compose interpolation can override the
# runtime value with an empty string.
# PORT: the health server defaults to 8080, which the healthcheck uses.
# KV_PROVIDER: storage auto-selects mongodb because MONGO_URL is set.
# Long polling = no TELEGRAM_WEBHOOK_SECRET, no /webhook, no public domain.
# Cron is in-process only — no CRON_MODE, no /cron route, no secret.
# No stock/coin/gold URL overrides — modules use their coded default
# providers (stock: SSI/VCI/KBS; coin: Binance->Coinbase->CoinGecko;
# gold: VNAppMob).
# Long polling is outbound-only: nothing inbound to route, so no published
# ports and no public domain. `expose` only documents the health server's
# port; it publishes nothing on the host.
expose:
- "8080"
# Coolify's UI health check does not apply to Docker Compose apps; it reads
# this block instead. GET / returns text/plain "miti99bot ok". It proves the
# process is serving, not that Mongo is reachable — see
# docs/deploy-coolify-selfhosted.md. busybox wget ships in the Alpine image.
healthcheck:
test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8080/ || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
# Animation renderer (Node + Remotion + headless Chrome) from renderer/.
# Internal only: the bot reaches it over the compose network, so it has no
# published port, no public domain, and no auth token. Never publish a port
# or attach a domain to it — its API is unauthenticated.
renderer:
build:
context: ./renderer
restart: unless-stopped
environment:
# Every renderer setting carries the RENDERER_ prefix so it reads as a
# renderer setting and cannot clash with the bot's variables.
# --- Tuning (optional; empty uses the default) ---
RENDERER_MAX_CONCURRENT_RENDERS: ${RENDERER_MAX_CONCURRENT_RENDERS} # default: 1
RENDERER_RENDER_TIMEOUT_MS: ${RENDERER_RENDER_TIMEOUT_MS} # default: 15000 (floor 7000)
RENDERER_MAX_OPTIONS: ${RENDERER_MAX_OPTIONS} # default: 32 wheel options
RENDERER_MAX_OPTION_CHARS: ${RENDERER_MAX_OPTION_CHARS} # default: 40 chars per option/label
# --- Fixed by this stack (not Coolify settings) ---
NODE_ENV: production
RENDERER_HOST: 0.0.0.0
RENDERER_PORT: "3000" # keep in sync with the bot's RENDERER_URL and the healthcheck
expose:
- "3000"
healthcheck:
test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:3000/api/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
interval: 30s
timeout: 5s
retries: 3