Деплой¶
Система развёрнута по split-topology: удалённый сервер (данные + веб) и локальный сервер (воркеры + Telegram). Единый скрипт deploy.sh управляет деплоем на оба сервера.
Серверы¶
| Сервер | IP | Сервисы | Код |
|---|---|---|---|
| Удалённый | 2.59.170.200 |
nginx, api, db, redis | /opt/chat_bot/ |
| Локальный | -- | dialog-orchestrator, admin-bot, celery-*, emulator/embedding workers | рабочая директория |
graph LR
subgraph "Remote (fin-boost.com)"
NGINX[nginx :443] --> API[api :8000]
API --> DB[PostgreSQL :5432]
API --> REDIS[Redis :6379]
end
subgraph "Local"
ORCH[dialog-orchestrator]
ADMIN[admin-bot]
CELERY[celery workers]
end
ORCH -->|"5434 → 5432"| DB
ORCH -->|"6381 → 6379"| REDIS
Домен и SSL¶
| Параметр | Значение |
|---|---|
| Домен | fin-boost.com + www.fin-boost.com |
| DNS | A @ --> 2.59.170.200, CNAME www --> fin-boost.com |
| SSL | Let's Encrypt (certbot + nginx plugin) |
| Сертификат | /etc/letsencrypt/live/fin-boost.com/ |
| Nginx | 443 --> 127.0.0.1:8000, HTTP --> HTTPS redirect |
deploy.sh -- единая точка деплоя¶
./scripts/deploy.sh # Всё (local + remote)
./scripts/deploy.sh api # Только remote API (full rebuild)
./scripts/deploy.sh web # Только фронтенд (~15 сек)
./scripts/deploy.sh dialog-orchestrator # Только local orchestrator
./scripts/deploy.sh dialog-orchestrator api # Оба сервера
Full API Deploy¶
./scripts/deploy.sh api выполняет полный цикл:
flowchart TD
A[git diff --quiet HEAD] -->|clean| B[rsync кода на remote]
A -->|dirty| A1{DEPLOY_ALLOW_DIRTY=1?}
A1 -->|нет| FAIL[Деплой отменён]
A1 -->|да| B
B --> C[pg_dump backup]
C --> D["docker compose build<br>(BUILD_COMMIT baked in)"]
D --> E[alembic upgrade head]
E --> F["docker compose up -d"]
F --> G[nginx reload]
G --> H[Health check]
- Dirty Worktree Guard -- remote deploys блокируются при uncommitted файлах. Override:
DEPLOY_ALLOW_DIRTY=1 - rsync кода на
/opt/chat_bot/(excludes:.git,__pycache__,.venv,sessions/,logs/,memories/,datasets/,.env,node_modules) - Pre-migration backup --
pg_dump | gzip > /tmp/pre_deploy_{commit}_{ts}.sql.gz. Failure = non-fatal WARN - Docker build --
BUILDKIT_PROGRESS=plain,BUILD_COMMIT(git short SHA) --> DockerARG-->GIT_COMMITenv - Миграции --
alembic upgrade head - Запуск --
docker compose up -d+nginx reload+ health check
BUILD_COMMIT
Все сервисы регистрируют commit в Redis. /api/health/ready проверяет consistency -- несовпадение версий = warning.
Frontend-only Deploy (быстрый)¶
./scripts/deploy.sh web -- только фронтенд (~15 сек вместо ~3 мин):
npm ci + vite buildлокальноrsync web/dist/на удалённый серверdocker compose restart api
Работает благодаря volume mount ./web/dist:/app/web/dist:ro -- контейнер читает SPA-файлы с хоста.
Backend-only Deploy¶
Для изменений только в Python-коде (без frontend rebuild):
rsync -az --delete \
--exclude='.git' --exclude='__pycache__' --exclude='web/' \
./ root@2.59.170.200:/opt/chat_bot/
ssh root@2.59.170.200 \
"cd /opt/chat_bot && BUILD_COMMIT=\$(git rev-parse --short HEAD) \
docker compose up -d --build api"
Volume Mounts (удалённый сервер)¶
API-контейнер использует volume mounts для файлов, обновляемых без rebuild:
| Volume | Назначение |
|---|---|
./logs:/app/logs |
Централизованные логи |
./web/dist:/app/web/dist:ro |
SPA -- обновляется через rsync |
./memories:/app/memories |
Персональная память клиентов |
./.env:/app/.env:ro |
Конфигурация |
Локальный деплой¶
Локальные сервисы подключаются к удалённой БД и Redis через mapped порты:
DATABASE_URL=postgresql+asyncpg://postgres:postgres@2.59.170.200:5434/debt_collector
REDIS_URL=redis://2.59.170.200:6381/0
CELERY_BROKER_URL=redis://2.59.170.200:6381/1
Два .env файла
Remote .env: внутренние Docker-адреса (redis:6379, db:5432).
Local .env: внешние mapped порты (2.59.170.200:6381, 2.59.170.200:5434).
Деплой локальных сервисов:
BUILD_COMMIT=$(git rev-parse --short HEAD) docker compose up -d --build dialog-orchestrator
docker compose up -d --build admin-bot celery-worker celery-worker-warming celery-beat
Firewall (удалённый сервер)¶
| Порт | Доступ |
|---|---|
| 80/443 | Публичный (nginx) |
| 5432 | Только IP локального сервера |
| 6379 | Только IP локального сервера |
| 8000 | Только localhost (nginx proxy) |
GPU¶
GPU deploy-секции убраны из базового docker-compose.yml (remote сервер без GPU). На локальном сервере GPU подключается через docker-compose.override.yml (gitignored, не попадает в rsync).
Operator Suggestions (split-topology)¶
Remote API не имеет Claude CLI/SDK. Для AI suggestions:
- API пытает вызвать AI --> fallback
- Диспатчит
generate_operator_suggestionsCelery task на локальный воркер - Возвращает
source: "fallback_pending"(30s cache) - Локальный celery-worker генерирует AI suggestions
- Записывает результат в Redis (600s cache)
- Следующий poll фронтенда подхватывает AI-результат
Логи¶
./scripts/logs.sh # Все сервисы (local + remote merged)
./scripts/logs.sh api # Только remote API
./scripts/logs.sh dialog-orchestrator # Только local
./scripts/logs.sh -n 50 # Последние 50 строк
Post-Deploy Checks¶
# Remote
curl -s https://fin-boost.com/api/health/live
ssh root@2.59.170.200 "docker ps"
# Local
docker compose ps
# Автоматическая проверка
python scripts/post_deploy_check.py # Полная проверка
python scripts/post_deploy_check.py --local # Только локальные
python scripts/post_deploy_check.py --quiet # Console-only
Типичные проблемы¶
| Проблема | Причина | Решение |
|---|---|---|
| Фронт не обновился | Кеш Docker layer | Убедиться что rsync прошёл до docker compose up --build |
| 401 на всех API-запросах | Контейнер пересоздан, сессии в Redis | Перелогиниться |
| Migration failure | Ошибка при alembic upgrade | Восстановить из backup: /tmp/pre_deploy_*.sql.gz |
| Dirty worktree | Uncommitted файлы | git add && git commit или DEPLOY_ALLOW_DIRTY=1 |
| Stale Celery code | docker compose restart не пересобирает |
Использовать up -d --build или deploy.sh |