40227-vm/docs/deployment-docker.md
2026-06-10 18:27:19 +02:00

100 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Развёртывание через 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 |