# Запуск через 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_.sql`. 3. **Закоммитьте оба файла** — изменённый `shared/schema.ts` и новый SQL-файл миграции: ```bash git add shared/schema.ts migrations/ git commit -m "feat: add " ``` 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/другой хост) — в бэклоге.