# Развёртывание через Docker (на хосте)

Альтернативный способ запуска для локального стека и портируемого деплоя.
На боевой VM Flatlogic **Docker не используется** — там PM2 + локальный PostgreSQL
+ Cloudflare tunnel (см. [`deployment-vm.md`](./deployment-vm.md)).

Проект состоит из двух приложений:

- `frontend/` — Vite + React + TypeScript (SPA). Сборка → `frontend/dist/`.
- `backend/` — Express + Sequelize на TypeScript/ESM. Сборка → `backend/dist/`.

## Файлы

В корне репозитория:

| Файл | Назначение | Порт |
|---|---|---|
| `Dockerfile` | прод single-image: компилированный бэк отдаёт API **и** SPA (из `public`) | 8080 |
| `Dockerfile.dev` | staging-реплика VM: nginx + фронт `vite preview` (3001) + бэк (3000), `dev_stage` | 8080 |
| `docker/docker-compose.yml` | локальный стек: PostgreSQL + app (из `Dockerfile`), `NODE_ENV=development` | 8080 |

Все стейджи на `node:24-alpine`, `npm ci`. Нативный `bcrypt` собирается тулчейном
(`python3 make g++`) в builder-стейдже, в рантайм копируется готовый `node_modules`
(без перекомпиляции). `rolldown` (бандлер Vite) имеет musl-биндинги, поэтому alpine
подходит.

## 1. Быстрый старт — docker compose (рекомендуется)

Поднимает PostgreSQL + приложение одной командой. Бэкенд в `development` отдаёт API
и SPA на одном порту (логин работает по http).

```bash
cd docker
docker compose up --build
# открыть http://localhost:8080
```

Параметры (env заданы в `docker-compose.yml`, меняйте под себя):

- `SECRET_KEY=local_dev_secret_change_me`
- `DB_*` указывают на сервис `db` (Postgres 16, БД/пользователь `app_local`)
- `SEED_ADMIN_EMAIL`, `SEED_ADMIN_PASSWORD`, `SEED_USER_PASSWORD`

Остановить и удалить (вместе с данными БД):

```bash
docker compose down -v
```

## 2. Прод single-image (`Dockerfile`)

Один контейнер: компилированный бэкенд на `NODE_ENV=production` слушает 8080 и
отдаёт и `/api`, и собранный SPA (фронт кладётся в `public`).

```bash
docker build -t schoolchain:prod .

docker run --rm -p 8080:8080 \
  -e NODE_ENV=production \
  -e PORT=8080 \
  -e SECRET_KEY=<секрет> \
  -e ALLOWED_ORIGINS=https://<ваш-домен> \
  -e DB_HOST=<host> -e DB_PORT=5432 -e DB_NAME=<db> -e DB_USER=<user> -e DB_PASS=<pass> \
  -e SEED_ADMIN_EMAIL=<email> -e SEED_ADMIN_PASSWORD=<pass> -e SEED_USER_PASSWORD=<pass> \
  schoolchain:prod
```

> В `NODE_ENV=production` обязательны `SECRET_KEY` и `ALLOWED_ORIGINS`, а cookie
> идут с флагом `Secure` (нужен HTTPS-фронт перед контейнером). Команда запуска
> (`npm run start:production`) сама прогоняет миграции и сидеры перед стартом —
> БД должна быть доступна.

## 3. Staging-реплика VM (`Dockerfile.dev`)

Повторяет схему VM в одном образе: nginx (8080) → фронт `vite preview` (3001) + бэк
(3000), `NODE_ENV=dev_stage`, source maps. Запускать за HTTPS (в `dev_stage`
cookie — `Secure`).

```bash
docker build -t schoolchain:staging -f Dockerfile.dev .
docker run --rm -p 8080:8080 \
  -e SECRET_KEY=<секрет> \
  -e DB_HOST=<host> -e DB_PORT=5432 -e DB_NAME=<db> -e DB_USER=<user> -e DB_PASS=<pass> \
  -e SEED_ADMIN_EMAIL=<email> -e SEED_ADMIN_PASSWORD=<pass> -e SEED_USER_PASSWORD=<pass> \
  schoolchain:staging
```

## 4. `.dockerignore`

Исключает `node_modules`, `dist`, `public`, `**/.env` (чтобы не запекать dev-секреты
в образ — окружение задаётся при запуске), `.git`, логи.

## 5. NODE_ENV — что выбрать

| `NODE_ENV` | Где | Особенности |
|---|---|---|
| `development` | локальный `docker compose` | http-логин работает; нет требований к `ALLOWED_ORIGINS`; cookie без `Secure` |
| `dev_stage` | `Dockerfile.dev` (staging) | прод-подобный, но мягкий; нужен HTTPS (`Secure` cookie); рефлектит origin |
| `production` | `Dockerfile` (прод) | обязательны `SECRET_KEY` + `ALLOWED_ORIGINS`; `Secure` cookie; строгий CORS |
