8.0 KiB
Развёртывание
Клонируем репозиторий и поднимаем контур Compose-ом. Контуры test и prod
разделяются именем проекта (-p) и файлом окружения (--env-file) — у каждого
свои БД и volume'ы, на одной машине не пересекаются.
1. Клонировать
git clone ssh://git@<gitea-host>:2222/mpakobecex/DispelEvilBot.git
cd DispelEvilBot
2. Подготовить окружение
cp env/test.env.example env/test.env
# заполнить: BOT_TOKEN, DB_PASSWORD, CHAT_ID (основной чат), ALERT_CHAT_ID (опц.),
# ADMIN_IDS (опц.)
# плюс для админки: BOT_USERNAME, ADMIN_PUBLIC_URL (HTTPS-домен),
# ADMIN_SESSION_SECRET (openssl rand -hex 32)
Порт админки (ADMIN_HTTP_PORT) у контуров должен различаться: prod — 8101,
test — 8100 (8000 на VPS занят Portainer). ADMIN_BIND_IP по умолчанию 127.0.0.1;
чтобы nginx-proxy-manager (контейнер) видел админку, ставьте 172.17.0.1.
3. Логин в registry (если пакет приватный)
docker login git.mpakosrv.ru -u mpakobecex -p <ТОКЕН с read:package>
Если пакет сделать публичным — логин не нужен.
4. Запуск
# тестовый контур
docker compose -p test --env-file env/test.env -f docker-compose.prod.yml up -d
# прод (когда понадобится)
cp env/prod.env.example env/prod.env
docker compose -p prod --env-file env/prod.env -f docker-compose.prod.yml up -d
Логи:
docker compose -p test --env-file env/test.env -f docker-compose.prod.yml logs -f
Что происходит при старте
postgresподнимается и проходит healthcheck;migrate(Flyway) накатывает миграции изsql/— для пустой БД с нуля;botстартует (Запуск DispelEvilBot v<версия> (APP_ENV=...)), аналитика и рассылки — в нём же;adminстартует и отвечает наGET /healthz(порт на loopback хоста).
Проверка контура (сервисы, миграции, Postgres, схема аналитики):
make check E=test
Аналитика (Postgres)
События и дневные счётчики сообщений пишутся в схему analytics той же БД Postgres
(контракт — docs/events.md). Отдельного сервиса нет.
make psql E=test
# пример: события за сегодня по типам
SELECT event_type, count(*) FROM analytics.events
WHERE event_time >= current_date GROUP BY event_type;
# сообщения по дням
SELECT day, sum(count) FROM analytics.messages_daily
WHERE day >= current_date - 7 GROUP BY day ORDER BY day;
Если Postgres недоступен, бот продолжает работать: батч аналитики уходит в stdout
(WARNING) и отбрасывается. Полностью выключить можно флагом ANALYTICS_ENABLED=false.
Партиции создаются приложением при старте и раз в 6 часов; старые не удаляются.
Схема создаётся миграцией V26__analytics_schema.sql.
Админка (FastAPI)
Сервис admin — отдельный образ mpakobecex/dispelevilbot-admin, общий пакет common.
Наружу пока не публикуется: по умолчанию только loopback хоста
(127.0.0.1:${ADMIN_HTTP_PORT}). Для nginx-proxy-manager (он в контейнере) задайте
ADMIN_BIND_IP=172.17.0.1 и указывайте в NPM цель 172.17.0.1:8100 (test) /
172.17.0.1:8101 (prod). Домен и TLS — Блок 4.2.
# проверка живости
curl -s http://127.0.0.1:8100/healthz # test
curl -s http://127.0.0.1:8101/healthz # prod
Локально без Docker: pip install -r requirements-admin.txt && python -m admin
(по умолчанию 0.0.0.0:8000, переопределяется ADMIN_HOST/ADMIN_PORT).
Вход через Telegram
Админка закрыта Telegram Login Widget. Что нужно на контуре:
BOT_TOKEN— токен бота этого контура (им же проверяется подписьhash);BOT_USERNAME— username бота без@(виджет рисует кнопку);ADMIN_PUBLIC_URL— публичный HTTPS-адрес (https://debot-test.mpakosrv.ru);ADMIN_SESSION_SECRET—openssl rand -hex 32;ADMIN_IDS— Telegram-ID администраторов: ими засеваетсяbot.admin_usersпри старте (ON CONFLICT DO NOTHING, существующих не трогает).
Домен должен быть привязан к боту в @BotFather (/setdomain), а TLS — настроен на
reverse proxy. Сессия живёт 12 часов (ADMIN_SESSION_MAX_AGE), cookie подписана и
HttpOnly; в проде ставится флаг Secure. Все POST-формы проверяют CSRF-токен.
Роль администратора перечитывается из БД на каждом запросе — отключение пользователя
(enabled = false) или удаление записи сразу закрывает доступ.
Бэкап
Аналитика теперь лежит в Postgres, поэтому отдельного бэкапа событий больше нет.
Бэкап БД — стандартными средствами Postgres (pg_dump/pg_basebackup); при росте
истории следите за размером analytics и диском.
Обновление и откат
# обновление: поменять IMAGE_TAG в env/<контур>.env, затем
docker compose -p <контур> --env-file env/<контур>.env -f docker-compose.prod.yml pull
docker compose -p <контур> --env-file env/<контур>.env -f docker-compose.prod.yml up -d
Откат — вернуть предыдущий IMAGE_TAG (например, commit-sha) и повторить.
Контуры
| Контур | env-файл | БД | APP_ENV | Бот |
|---|---|---|---|---|
| test | env/test.env |
dispel_evil_test |
dev |
тестовый |
| prod | env/prod.env |
dispel_evil |
prod |
боевой |
Переменные окружения
См. env/prod.env.example / env/test.env.example (контуры).
Дашборд (позже)
Superset поднимается отдельно и читает Postgres (схема analytics) с полной историей
событий. Отдельный read-only пользователь Postgres и сам дашборд — финальный этап,
в этот контур не входят.
Перенос данных на прод (позже, короткое окно простоя)
- Остановить старого бота.
pg_dump -Fc -f dump.pgc <старая_бд>.- Поднять прод-контур (миграции создадут чистую схему).
- Загрузить данные:
pg_restore --data-only --disable-triggers -d dispel_evil dump.pgc. - Сверить: число пользователей,
SUM(money.amount), число сообщений. - Переключить бота, проверить команды.
Бэкап старой БД обязателен. Дубли в tg_users/de_users/unsubscribe при загрузке
нужно устранить до создания PK (миграция V12 делает дедуп, но при загрузке поверх
миграций дедуп — вручную).