This commit is contained in:
2026-02-06 11:52:30 +03:00
parent 1812de0baf
commit fd7bf76abd
4 changed files with 289 additions and 6 deletions

224
situation.md Normal file
View File

@ -0,0 +1,224 @@
# Текущая ситуация проекта CourseCraft
Документ описывает состояние репозитория и способы запуска (на хосте и в Docker).
---
## Состояние проекта
### Монорепозиторий (pnpm workspaces + Turbo)
- **apps/api** — NestJS API (авторизация, курсы, генерация, платежи, поиск). Порт по умолчанию: **3125**.
- **apps/web** — Next.js 14 (App Router). Порт по умолчанию: **3080**.
- **apps/ai-service** — воркер AI-пайплайна (OpenRouter, BullMQ). Без своего HTTP-порта, подключается к Redis.
- **packages/database** — Prisma-схема и клиент. Для `prisma db push` нужен свой `.env` в `packages/database/` с `DATABASE_URL`.
- **packages/shared** — общие типы и константы.
### Порты
| Сервис | Порт | Описание |
|---------------|-------|-----------------------------|
| API | 3125 | Бэкенд, Swagger на /api/docs |
| Web | 3080 | Фронтенд |
| Postgres | 5432 | БД |
| Redis | 6395 | Очереди (на хосте 6395→6379)|
| Meilisearch | 7700 | Поиск |
### Переменные окружения
Критичные для работы:
- **Supabase:** `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY`
- **JWT:** `JWT_SECRET` (подпись токенов после обмена с Supabase)
- **БД:** `DATABASE_URL` (PostgreSQL)
- **Redis:** `REDIS_URL`, `REDIS_HOST`, `REDIS_PORT`
- **OpenRouter:** `OPENROUTER_API_KEY`
- **Meilisearch:** `MEILISEARCH_HOST`, `MEILISEARCH_API_KEY`
Корневой `.env` используется при запуске приложений на хосте и при `docker compose` (см. ниже).
---
## Запуск: два варианта
### 1. Всё в Docker (рекомендуется для сервера)
Вся инфраструктура и приложения в контейнерах; после отключения от сервера процессы не падают.
**Важно:** Compose и `.env` должны быть в **корне** проекта. Используется корневой `docker-compose.yml` (не `docker/docker-compose.yml`).
**Шаги:**
```bash
cd /usr/local/course-craft-service # или путь к репозиторию
```
Убедиться, что в корне есть `.env` с нужными ключами (Supabase, JWT_SECRET и т.д.).
```bash
docker compose --env-file .env up -d --build
```
Или через pnpm (то же самое):
```bash
pnpm docker:up
```
После первого запуска таблицы в БД создаются при старте API (entrypoint делает `prisma db push`). Данные БД/Redis/Meilisearch лежат в `docker/data/`.
**Проверка:**
- Web: `http://<хост>:3080`
- API: `http://<хост>:3125/api`
- Переменные в контейнере API:
`docker exec coursecraft-api env | grep -E "JWT_SECRET|SUPABASE"`
значения не должны быть пустыми.
**Остановка:**
```bash
docker compose down
```
**Логи:**
```bash
docker compose logs -f
# или по сервису
docker logs coursecraft-api -f
```
---
### 2. Только инфраструктура в Docker, приложения на хосте
Удобно для разработки: БД, Redis, Meilisearch в Docker; API, Web и AI-service — через pnpm.
**Шаги:**
1. Поднять только инфраструктуру (если используется корневой compose):
```bash
cd /usr/local/course-craft-service
docker compose --env-file .env up -d postgres redis meilisearch
```
Либо старый вариант только инфраструктуры из `docker/` (без api, web, ai-service).
2. Применить схему БД (один раз или после изменений в Prisma):
В корне должен быть `.env` с `DATABASE_URL`. Для Prisma также нужен `packages/database/.env`:
```bash
echo 'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/coursecraft?schema=public"' > packages/database/.env
pnpm db:push
```
3. Запуск приложений:
```bash
pnpm start
```
Или в режиме разработки:
```bash
pnpm dev
```
Доступ: Web — 3080, API — 3125 (или как задано в `.env`: PORT, скрипты next).
---
## Скрипт run.sh (деплой на сервере)
`run.sh` в корне репозитория:
1. Останавливает Docker Compose (старый путь `docker/docker-compose.yml`).
2. Делает `git pull`.
3. Выполняет `pnpm install` и `pnpm build`.
4. Поднимает Docker Compose.
5. В фоне запускает `pnpm start` (API, Web, AI-service на хосте).
То есть он смешивает: инфраструктура через Docker, приложения — процессы на хосте. Для «всё в Docker» лучше использовать только `docker compose --env-file .env up -d` из корня (или `pnpm docker:up`), без шага с `pnpm start`.
---
## Важные моменты
1. **Корневой `.env`**
При запуске `docker compose` из корня с `--env-file .env` переменные подставляются в `docker-compose.yml` и передаются в контейнеры. Без этого JWT и Supabase в API будут пустыми → 500 на `/api/auth/exchange` и т.п.
2. **Откуда запускать Compose**
Запуск только из **корня проекта** (где лежит `.env` и `docker-compose.yml`). Не из папки `docker/`.
3. **Prisma в контейнере API**
Используется образ на базе `node:20-slim` (не Alpine), чтобы не было ошибок с `libssl.so.1.1` у нативного движка Prisma.
4. **Прокси API во фронте**
Web обращается к API по относительному пути `/api/...`; Next.js проксирует запросы на бэкенд (в Docker — на сервис `api:3125`). Один билд веба работает при любом хосте.
5. **Два compose-файла**
- **Корень:** `docker-compose.yml` — основной, с `env_file: .env` и путями от корня. Использовать его для полного запуска в Docker.
- **docker/docker-compose.yml** — старый вариант (можно оставить для только инфраструктуры или выровнять с корневым при необходимости).
---
## Если в Docker 500 на `/api/auth/exchange` и `/api/courses` (а через pnpm run — всё ок)
Чаще всего API в контейнере не получает переменные окружения или получает их с ошибкой (например, из-за Windows).
**1. Запуск обязательно с `--env-file .env` из корня проекта:**
```bash
cd d:\Github\course-craft-service
docker compose --env-file .env up -d --build
```
Или через pnpm: `pnpm docker:up` (если скрипт использует `--env-file .env`).
**2. Проверка переменных в контейнере API:**
```bash
docker exec coursecraft-api env | findstr "JWT_SECRET SUPABASE DATABASE"
```
Должны быть непустые `JWT_SECRET`, `NEXT_PUBLIC_SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, `DATABASE_URL=postgresql://postgres:postgres@postgres:5432/...`. Если что-то пустое — Compose не подхватил `.env` (запуск не из корня или не указан `--env-file .env`).
**3. Windows: перевод строк в `.env`**
Если `.env` сохранён с CRLF (Windows), значения могут содержать `\r` и ломать JWT/подключения. Сохраните `.env` в кодировке UTF-8 с окончаниями строк LF (в редакторе: «Save with Encoding» → UTF-8, в Git: `git config core.autocrlf input` и пересохраните файл).
**4. Логи API при 500:**
После правок при следующей ошибке API при старте покажет явную причину, если не задан `JWT_SECRET`. Для любых необработанных ошибок смотрите логи:
```bash
docker logs coursecraft-api -f
```
Перед запросом к `/api/auth/exchange` или `/api/courses` в логах будет стек или сообщение об ошибке (БД, Supabase, JWT и т.д.).
**5. Web должен проксировать на контейнер API**
В контейнере `web` при старте должна быть переменная `API_URL=http://api:3125` (задаётся в `docker-compose.yml`). Тогда Next.js отправляет запросы на сервис `api`, а не на `localhost`. Проверка:
```bash
docker exec coursecraft-web env | findstr API_URL
```
Ожидается: `API_URL=http://api:3125`.
---
## Краткая шпаргалка
| Задача | Команда |
|---------------------|--------|
| Всё в Docker | `cd <корень> && docker compose --env-file .env up -d` или `pnpm docker:up` |
| Только инфраструктура | `docker compose --env-file .env up -d postgres redis meilisearch` |
| Схема БД (на хосте) | `packages/database/.env` с DATABASE_URL, затем `pnpm db:push` |
| Приложения на хосте | `pnpm start` или `pnpm dev` |
| Логи Docker | `docker compose logs -f` или `docker logs coursecraft-api -f` |
| Остановить Docker | `docker compose down` |