Files
iistwin/DOCKER.md
Ильяс Султанов 960f28d3de docs(backups): стратегия бэкапов PostgreSQL (RPO/RTO), проверка восстановления
Шаг 1.8 плана production-готовности: дамп 2026-09-07 03:00 восстановлен
в scratch-БД без ошибок (125 таблиц), процедура задокументирована в DOCKER.md
2026-09-08 00:15:27 +03:00

13 KiB
Raw Blame History

Запуск через 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

Профили можно комбинировать. Самый полный вариант («устройство в коробке»):

docker compose --profile with-postgres --profile with-minio up --build

Режим 1: Внешняя база, локальный диск

Файлы хранятся в папке uploads/ (сбрасываются при пересборке).

DATABASE_URL=postgresql://user:password@host/dbname?sslmode=require
JWT_SECRET=...
SESSION_SECRET=...
API_KEY_HMAC_SECRET=...
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY=...
docker compose up --build

Режим 2: Встроенная PostgreSQL, локальный диск

# 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=...
docker compose --profile with-postgres up --build

Режим 3: MinIO S3 + WebDAV (рекомендуется для устройств)

Файлы хранятся в MinIO — не теряются при перезапуске. WebDAV позволяет просматривать и добавлять файлы через Windows Explorer, Finder, Cyberduck.

Переменные окружения

# 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)

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 — локальный LLM-сервер — как отдельный контейнер. Модели не скачиваются автоматически: вы выбираете и загружаете их через интерфейс iistwin в разделе Настройки → LLM Провайдеры.

Запуск с Ollama

# Только приложение + 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.

Порты

Сервис Порт Описание
Ollama API 11434 REST API для управления моделями и инференса

Volumes

Volume Данные
ollama_data Скачанные модели Ollama

Для сброса данных (удаление всех скачанных моделей):

docker compose --profile with-ollama down -v

Генерация VAPID-ключей для веб-пушей

VAPID-ключи используются для web push уведомлений. Без постоянных ключей при каждом перезапуске сервера все push-подписки браузеров становятся невалидными.

Генерация ключей (выполнить один раз):

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)

Изменение схемы базы данных

При добавлении новых таблиц или колонок в shared/schema.ts необходимо создать SQL-файл миграции, который будет применён на всех серверах автоматически.

Шаги

  1. Внесите изменения в shared/schema.ts.

  2. Сгенерируйте миграцию (создаёт SQL-файл в папке migrations/):

    npm run db:generate
    

    Команда создаст файл вида migrations/0004_<name>.sql.

  3. Закоммитьте оба файла — изменённый shared/schema.ts и новый SQL-файл миграции:

    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:

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-модели

Для полного сброса данных:

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 МБ дампа за минуты, запуск).

Восстановление из дампа:

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/другой хост) — в бэклоге.