Шаг 0.1 (завершение) плана production-готовности: - прод: ENABLE_RLS=true включён, 31 таблица ENABLE+FORCE проверена - код: fatal при NODE_ENV=production без ENABLE_RLS - .env.example + DOCKER.md: пометки об обязательности
317 lines
14 KiB
Markdown
317 lines
14 KiB
Markdown
# Запуск через Docker
|
||
|
||
Приложение поддерживает несколько режимов развёртывания через Docker Compose.
|
||
Каждый режим активируется профилями `--profile`.
|
||
|
||
---
|
||
|
||
## Режимы базы данных
|
||
|
||
| Режим | База данных | Команда |
|
||
|---|---|---|
|
||
| Внешняя (Neon, любой Postgres) | Ваш хост | `docker compose up --build` |
|
||
| Встроенная PostgreSQL | Docker-контейнер | `docker compose --profile with-postgres up --build` |
|
||
|
||
## Режимы хранилища файлов
|
||
|
||
| Режим | Хранилище | Команда |
|
||
|---|---|---|
|
||
| Локальный диск (по умолчанию) | Папка `uploads/` | *(без флагов)* |
|
||
| MinIO S3 + WebDAV | MinIO-контейнер | `--profile with-minio` |
|
||
|
||
Профили можно комбинировать. Самый полный вариант («устройство в коробке»):
|
||
```bash
|
||
docker compose --profile with-postgres --profile with-minio up --build
|
||
```
|
||
|
||
---
|
||
|
||
## Режим 1: Внешняя база, локальный диск
|
||
|
||
Файлы хранятся в папке `uploads/` (сбрасываются при пересборке).
|
||
|
||
```env
|
||
DATABASE_URL=postgresql://user:password@host/dbname?sslmode=require
|
||
JWT_SECRET=...
|
||
SESSION_SECRET=...
|
||
API_KEY_HMAC_SECRET=...
|
||
VAPID_PUBLIC_KEY=...
|
||
VAPID_PRIVATE_KEY=...
|
||
```
|
||
|
||
```bash
|
||
docker compose up --build
|
||
```
|
||
|
||
---
|
||
|
||
## Режим 2: Встроенная PostgreSQL, локальный диск
|
||
|
||
```env
|
||
# PostgreSQL
|
||
POSTGRES_DB=appdb
|
||
POSTGRES_USER=appuser
|
||
POSTGRES_PASSWORD=your-strong-db-password
|
||
DATABASE_URL=postgresql://appuser:your-strong-db-password@db:5432/appdb
|
||
|
||
# App
|
||
JWT_SECRET=...
|
||
SESSION_SECRET=...
|
||
API_KEY_HMAC_SECRET=...
|
||
VAPID_PUBLIC_KEY=...
|
||
VAPID_PRIVATE_KEY=...
|
||
```
|
||
|
||
```bash
|
||
docker compose --profile with-postgres up --build
|
||
```
|
||
|
||
---
|
||
|
||
## Режим 3: MinIO S3 + WebDAV (рекомендуется для устройств)
|
||
|
||
Файлы хранятся в MinIO — не теряются при перезапуске. WebDAV позволяет
|
||
просматривать и добавлять файлы через Windows Explorer, Finder, Cyberduck.
|
||
|
||
### Переменные окружения
|
||
|
||
```env
|
||
# PostgreSQL (если используете встроенную)
|
||
POSTGRES_DB=appdb
|
||
POSTGRES_USER=appuser
|
||
POSTGRES_PASSWORD=your-strong-db-password
|
||
DATABASE_URL=postgresql://appuser:your-strong-db-password@db:5432/appdb
|
||
|
||
# MinIO S3 — приложение видит MinIO как "minio" внутри Docker-сети
|
||
MINIO_ENDPOINT=http://minio:9000
|
||
MINIO_ACCESS_KEY=minioadmin
|
||
MINIO_SECRET_KEY=your-strong-minio-password
|
||
MINIO_BUCKET=files
|
||
|
||
# WebDAV — доступ через браузер/файловый менеджер на порту 8080
|
||
WEBDAV_USER=admin
|
||
WEBDAV_PASSWORD=your-webdav-password
|
||
|
||
# App
|
||
JWT_SECRET=...
|
||
SESSION_SECRET=...
|
||
API_KEY_HMAC_SECRET=...
|
||
VAPID_PUBLIC_KEY=...
|
||
VAPID_PRIVATE_KEY=...
|
||
```
|
||
|
||
### Запуск (всё сразу: PostgreSQL + App + MinIO + WebDAV)
|
||
|
||
```bash
|
||
docker compose --profile with-postgres --profile with-minio up --build
|
||
```
|
||
|
||
### Доступные интерфейсы
|
||
|
||
| Сервис | Адрес | Описание |
|
||
|---|---|---|
|
||
| iistwin приложение | `http://device-ip:5000` | Основной интерфейс |
|
||
| MinIO Console | `http://device-ip:9001` | Веб-интерфейс MinIO (логин: MINIO_ACCESS_KEY) |
|
||
| WebDAV | `http://device-ip:8080` | Файловый менеджер (логин: WEBDAV_USER) |
|
||
|
||
### Подключение WebDAV
|
||
|
||
**Windows Explorer:** Нажмите «Подключить сетевой диск» → введите `\\device-ip@8080\DavWWWRoot`
|
||
|
||
**macOS Finder:** Нажмите ⌘K → введите `http://device-ip:8080`
|
||
|
||
**Cyberduck / WinSCP:** Протокол WebDAV, хост `device-ip`, порт `8080`
|
||
|
||
---
|
||
|
||
## Локальные LLM через Ollama
|
||
|
||
Профиль `with-ollama` запускает [Ollama](https://ollama.com/) — локальный LLM-сервер — как отдельный контейнер. Модели **не скачиваются автоматически**: вы выбираете и загружаете их через интерфейс iistwin в разделе **Настройки → LLM Провайдеры**.
|
||
|
||
### Запуск с Ollama
|
||
|
||
```bash
|
||
# Только приложение + Ollama (внешняя БД)
|
||
docker compose --profile with-ollama up --build
|
||
|
||
# Всё сразу: PostgreSQL + App + Ollama
|
||
docker compose --profile with-postgres --profile with-ollama up --build
|
||
|
||
# Максимальная конфигурация: PostgreSQL + MinIO + WebDAV + Ollama
|
||
docker compose --profile with-postgres --profile with-minio --profile with-ollama up --build
|
||
```
|
||
|
||
При активном профиле `with-ollama` переменная `OLLAMA_BASE_URL=http://ollama:11434` передаётся в контейнер приложения автоматически через `docker-compose.yml`. Переопределить адрес можно через `.env`.
|
||
|
||
### Управление моделями через UI
|
||
|
||
После запуска откройте **Настройки → LLM Провайдеры**, добавьте провайдер типа `Ollama` с URL `http://ollama:11434` (или `http://localhost:11434` для локального запуска вне Docker) и воспользуйтесь разделом **«Модели Ollama»**:
|
||
|
||
- **Скачать модель** — введите имя (например `qwen2.5:7b`) и нажмите «Скачать». Сервер запустит `ollama pull`, скачивание занимает несколько минут.
|
||
- **Удалить модель** — нажмите кнопку удаления рядом с установленной моделью.
|
||
- **Список установленных моделей** — отображается с размером на диске.
|
||
|
||
### Рекомендуемые модели
|
||
|
||
| Тип | Модели |
|
||
|---|---|
|
||
| Эмбеддинги (RAG) | `bge-m3`, `mxbai-embed-large`, `qwen3-embedding:8b` |
|
||
| Чат / AI-боты | `qwen2.5:3b`, `qwen2.5:7b` |
|
||
|
||
### NVIDIA GPU
|
||
|
||
Для использования GPU раскомментируйте секцию `deploy` в сервисе `ollama` в файле `docker-compose.yml` и убедитесь, что на хосте установлен [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html).
|
||
|
||
### Порты
|
||
|
||
| Сервис | Порт | Описание |
|
||
|---|---|---|
|
||
| Ollama API | `11434` | REST API для управления моделями и инференса |
|
||
|
||
### Volumes
|
||
|
||
| Volume | Данные |
|
||
|---|---|
|
||
| `ollama_data` | Скачанные модели Ollama |
|
||
|
||
Для сброса данных (удаление всех скачанных моделей):
|
||
```bash
|
||
docker compose --profile with-ollama down -v
|
||
```
|
||
|
||
---
|
||
|
||
## Генерация VAPID-ключей для веб-пушей
|
||
|
||
VAPID-ключи используются для web push уведомлений. Без постоянных ключей при каждом перезапуске сервера все push-подписки браузеров становятся невалидными.
|
||
|
||
**Генерация ключей (выполнить один раз):**
|
||
```bash
|
||
npx web-push generate-vapid-keys
|
||
```
|
||
|
||
Команда выведет пару ключей:
|
||
```
|
||
Public Key:
|
||
BAxxx...
|
||
|
||
Private Key:
|
||
xxx...
|
||
```
|
||
|
||
Скопируйте значения в переменные окружения `VAPID_PUBLIC_KEY` и `VAPID_PRIVATE_KEY`. Если ключи не заданы, сервер выведет предупреждение в лог и сгенерирует временные ключи (только для текущей сессии).
|
||
|
||
---
|
||
|
||
## Sequence при старте
|
||
|
||
Независимо от режима, контейнер приложения всегда:
|
||
|
||
1. Проверяет доступность базы данных (`scripts/check-db.js`)
|
||
2. Применяет SQL-миграции из папки `migrations/` (`npm run db:migrate`)
|
||
3. Создаёт MinIO bucket если настроен S3 (автоматически)
|
||
4. Запускает сервер приложения (`npm run start`)
|
||
|
||
**Row Level Security (RLS):** при `ENABLE_RLS=true` на старте включается ENABLE+FORCE RLS
|
||
на 31 таблице с проверкой политик (schema drift, count политик) — при расхождении процесс падает.
|
||
**В production (`NODE_ENV=production`) `ENABLE_RLS=true` обязателен** — без него процесс не стартует.
|
||
В development флаг можно не задавать (политики существуют, но не активны).
|
||
|
||
---
|
||
|
||
## Изменение схемы базы данных
|
||
|
||
При добавлении новых таблиц или колонок в `shared/schema.ts` необходимо
|
||
создать SQL-файл миграции, который будет применён на всех серверах автоматически.
|
||
|
||
### Шаги
|
||
|
||
1. **Внесите изменения** в `shared/schema.ts`.
|
||
|
||
2. **Сгенерируйте миграцию** (создаёт SQL-файл в папке `migrations/`):
|
||
```bash
|
||
npm run db:generate
|
||
```
|
||
Команда создаст файл вида `migrations/0004_<name>.sql`.
|
||
|
||
3. **Закоммитьте оба файла** — изменённый `shared/schema.ts` и новый SQL-файл миграции:
|
||
```bash
|
||
git add shared/schema.ts migrations/
|
||
git commit -m "feat: add <description>"
|
||
```
|
||
|
||
4. **При деплое новой версии** (`docker compose pull && docker compose up -d`)
|
||
`db:migrate` автоматически применит новую миграцию, не затрагивая уже существующие данные.
|
||
|
||
> **Важно:** SQL-файлы миграций нельзя редактировать после коммита — только добавлять новые.
|
||
> Применённые миграции отслеживаются в таблице `__drizzle_migrations` в самой БД.
|
||
|
||
### Проверка миграций после деплоя
|
||
|
||
Чтобы убедиться, что все миграции применились корректно, выполните в PostgreSQL:
|
||
|
||
```sql
|
||
SELECT * FROM "__drizzle_migrations" ORDER BY created_at;
|
||
```
|
||
|
||
Ожидаемый результат: строки `0000_baseline`, `0001_sync_missing_columns`, …, `0007_sync_missing_columns_v2` (плюс все последующие).
|
||
Если строки отсутствуют или возникла ошибка — смотрите логи контейнера: `docker compose logs app`.
|
||
|
||
---
|
||
|
||
## Хранение данных (volumes)
|
||
|
||
| Volume | Данные |
|
||
|---|---|
|
||
| `postgres_data` | База данных PostgreSQL |
|
||
| `minio_data` | Файлы (загруженные через iistwin) |
|
||
| `ollama_data` | Скачанные LLM-модели |
|
||
|
||
Для полного сброса данных:
|
||
```bash
|
||
docker compose --profile with-postgres --profile with-minio --profile with-ollama down -v
|
||
```
|
||
|
||
---
|
||
|
||
## Быстрый справочник
|
||
|
||
| Цель | Команда |
|
||
|---|---|
|
||
| Только приложение (внешняя БД + диск) | `docker compose up --build` |
|
||
| + встроенная PostgreSQL | `docker compose --profile with-postgres up --build` |
|
||
| + MinIO + WebDAV (без PostgreSQL) | `docker compose --profile with-minio up --build` |
|
||
| + локальные LLM (Ollama) | `docker compose --profile with-ollama up --build` |
|
||
| Всё сразу | `docker compose --profile with-postgres --profile with-minio --profile with-ollama up --build` |
|
||
|
||
---
|
||
|
||
## Бэкапы PostgreSQL (production)
|
||
|
||
**Автоматические (на сервере, cron):**
|
||
- 3:00 — `pg_dump -Fc | gzip` → `/opt/crm/backups/crm-YYYYMMDD-HHMMSS.dump.gz` (скрипт `/opt/crm/scripts/backup-db.sh`), ротация 14 дней;
|
||
- 3:30 — CSV-экспорт основных таблиц → `/opt/crm/backups/csv/YYYYMMDD-HHMMSS/` (скрипт `/opt/crm/scripts/backup-csv.sh`), 7 копий;
|
||
- логи: `/var/log/crm-backup.log`.
|
||
|
||
**RPO/RTO:**
|
||
- RPO (точка потери данных): до 24 часов (дамп раз в сутки). Для уменьшения — чаще расписание или WAL-архивация (не настроено).
|
||
- RTO (время восстановления): ~15–30 минут (остановка app, pg_restore ~11 МБ дампа за минуты, запуск).
|
||
|
||
**Восстановление из дампа:**
|
||
```bash
|
||
docker compose stop app document-worker
|
||
docker exec crm-db-1 psql -U appuser -d postgres -c 'DROP DATABASE appdb'
|
||
docker exec crm-db-1 psql -U appuser -d postgres -c 'CREATE DATABASE appdb'
|
||
zcat /opt/crm/backups/crm-<дата>.dump.gz | docker exec -i crm-db-1 pg_restore -U appuser -d appdb --no-owner --no-privileges
|
||
docker compose up -d
|
||
```
|
||
|
||
**Проверка восстановления:** выполнена 2026-09-07 — дамп за 03:00 восстановлен в scratch-БД без ошибок (125 таблиц, данные консистентны). Повторять такую проверку после изменений схемы бэкапа.
|
||
|
||
**Не входит в pg_dump (бэкапить отдельно):**
|
||
- файлы MinIO (`minio_data`) — tar volume вручную;
|
||
- модели Ollama (`ollama_data`) — tar volume вручную;
|
||
- `/app/data` (`crm_data` — JSON-конфиги финансов, google-токены).
|
||
|
||
**Известный риск:** бэкапы лежат на том же VPS — при отказе диска/сервера потеряются вместе с продом. Требуется выгрузка наружу (S3/другой хост) — в бэклоге.
|