Files
course-craft-service/situation.md
2026-02-06 11:52:30 +03:00

225 lines
10 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.

# Текущая ситуация проекта 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` |