# Развёртывание через 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= -e DB_PORT=5432 -e DB_NAME= -e DB_USER= -e DB_PASS= \ -e SEED_ADMIN_EMAIL= -e SEED_ADMIN_PASSWORD= -e SEED_USER_PASSWORD= \ 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= -e DB_PORT=5432 -e DB_NAME= -e DB_USER= -e DB_PASS= \ -e SEED_ADMIN_EMAIL= -e SEED_ADMIN_PASSWORD= -e SEED_USER_PASSWORD= \ 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 |