Compare commits
3 Commits
fix/temp-r
...
fix/docker
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e033b2c8d5 | ||
|
|
a4f8c37b84 | ||
| 7e980dd802 |
@@ -1,5 +1,5 @@
|
|||||||
# Сборка из корня монорепо: docker build -f Dockerfile.frontend .
|
# Сборка из корня монорепо: docker build -f Dockerfile.frontend .
|
||||||
# SPA дергает API по префиксу /api (nginx проксирует на сервис backend:3000).
|
# SPA дергает API по префиксу /api (nginx проксирует на сервис runners-calendar-backend:3000).
|
||||||
FROM node:20-alpine AS build
|
FROM node:20-alpine AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY frontend/package.json frontend/package-lock.json ./
|
COPY frontend/package.json frontend/package-lock.json ./
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ npm install
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Фронт всегда отправляет запросы на относительный префикс `**/api**`. В dev это проксирует Vite на `http://localhost:3001`, в Docker/проде — nginx фронта проксирует на backend. У бэкенда `CORS_ORIGIN` должен совпадать с origin приложения (например `http://localhost:5173`).
|
Фронт всегда отправляет запросы на относительный префикс `**/api**`. В dev это проксирует Vite на `http://localhost:3001`, в Docker/проде — nginx фронта проксирует на `runners-calendar-backend:3000`. У бэкенда `CORS_ORIGIN` должен совпадать с origin приложения (например `http://localhost:5173`).
|
||||||
|
|
||||||
## Docker: backend + frontend рядом с Postgres
|
## Docker: backend + frontend рядом с Postgres
|
||||||
|
|
||||||
@@ -36,11 +36,11 @@ npm run dev
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose -f docker-compose.stack.yml up -d --build
|
docker compose -f docker-compose.stack.yml up -d --build
|
||||||
docker compose -f docker-compose.stack.yml exec backend node dist/migrate.js
|
docker compose -f docker-compose.stack.yml exec runners-calendar-backend node dist/migrate.js
|
||||||
docker compose -f docker-compose.stack.yml exec backend node dist/seed.js
|
docker compose -f docker-compose.stack.yml exec runners-calendar-backend node dist/seed.js
|
||||||
```
|
```
|
||||||
|
|
||||||
Фронт в браузере обращается к API по префиксу `**/api**` (nginx в образе фронта проксирует на backend).
|
Фронт в браузере обращается к API по префиксу `**/api**` (nginx в образе фронта проксирует на сервис `runners-calendar-backend` в той же сети).
|
||||||
|
|
||||||
## Документация API и бэкенда
|
## Документация API и бэкенда
|
||||||
|
|
||||||
|
|||||||
4
backend/package-lock.json
generated
4
backend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "calendar-run-backend",
|
"name": "calendar-run-backend",
|
||||||
"version": "1.0.0",
|
"version": "1.2.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "calendar-run-backend",
|
"name": "calendar-run-backend",
|
||||||
"version": "1.0.0",
|
"version": "1.2.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"csv-parse": "^5.6.0",
|
"csv-parse": "^5.6.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "calendar-run-backend",
|
"name": "calendar-run-backend",
|
||||||
"version": "1.2.1",
|
"version": "1.2.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
|
|||||||
@@ -7,25 +7,6 @@ import racesRouter from "./routes/races";
|
|||||||
export function createApp(): express.Express {
|
export function createApp(): express.Express {
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// TEMP: compare Host vs Origin for 200 vs 401 debugging — remove when done
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
const host = req.headers.host;
|
|
||||||
const origin = req.headers.origin;
|
|
||||||
res.on("finish", () => {
|
|
||||||
console.log(
|
|
||||||
JSON.stringify({
|
|
||||||
tag: "temp-req-headers",
|
|
||||||
host,
|
|
||||||
origin: origin ?? null,
|
|
||||||
method: req.method,
|
|
||||||
path: req.originalUrl ?? req.url,
|
|
||||||
status: res.statusCode,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
cors({ origin: config.corsOrigin, methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"] }),
|
cors({ origin: config.corsOrigin, methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"] }),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,13 +10,14 @@
|
|||||||
# docker compose -f docker-compose.stack.yml up -d --build
|
# docker compose -f docker-compose.stack.yml up -d --build
|
||||||
#
|
#
|
||||||
# Миграции и seed (один раз после появления БД):
|
# Миграции и seed (один раз после появления БД):
|
||||||
# docker compose -f docker-compose.stack.yml exec backend node dist/migrate.js
|
# docker compose -f docker-compose.stack.yml exec runners-calendar-backend node dist/migrate.js
|
||||||
# docker compose -f docker-compose.stack.yml exec backend node dist/seed.js
|
# docker compose -f docker-compose.stack.yml exec runners-calendar-backend node dist/seed.js
|
||||||
#
|
#
|
||||||
# NPM: проброс на порт 3033. Браузер ходит на /api → nginx во фронте → backend:3000.
|
# NPM: проброс на порт 3033. Браузер ходит на /api → nginx во фронте → runners-calendar-backend:3000.
|
||||||
|
# Имя сервиса уникально в общей сети (не «backend»), чтобы не пересекаться с другими стеками.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
backend:
|
runners-calendar-backend:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.backend
|
dockerfile: Dockerfile.backend
|
||||||
@@ -40,7 +41,7 @@ services:
|
|||||||
dockerfile: Dockerfile.frontend
|
dockerfile: Dockerfile.frontend
|
||||||
container_name: runners-calendar-frontend
|
container_name: runners-calendar-frontend
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- runners-calendar-backend
|
||||||
ports:
|
ports:
|
||||||
- "3033:80"
|
- "3033:80"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ server {
|
|||||||
|
|
||||||
# Браузер ходит на тот же origin: /api/* → бэкенд с тем же префиксом /api
|
# Браузер ходит на тот же origin: /api/* → бэкенд с тем же префиксом /api
|
||||||
location /api/ {
|
location /api/ {
|
||||||
proxy_pass http://backend:3000;
|
proxy_pass http://runners-calendar-backend:3000;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
SPA всегда отправляет запросы на относительный префикс `/api` текущего origin.
|
SPA всегда отправляет запросы на относительный префикс `/api` текущего origin.
|
||||||
|
|
||||||
- В dev (`npm run dev`): Vite proxy отправляет `/api/*` на `http://localhost:3001/api/*`.
|
- В dev (`npm run dev`): Vite proxy отправляет `/api/*` на `http://localhost:3001/api/*`.
|
||||||
- В Docker/проде: nginx фронта проксирует `/api/*` на backend в той же сети.
|
- В Docker/проде: nginx фронта проксирует `/api/*` на хост `runners-calendar-backend:3000` в той же сети (уникальное имя сервиса Compose, без коллизий с чужими стеками).
|
||||||
|
|
||||||
## 2. CORS
|
## 2. CORS
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ API слушает порт: **`PORT`** (если задан), иначе **`API
|
|||||||
| `API_PORT` | Порт API-сервера | `3001` |
|
| `API_PORT` | Порт API-сервера | `3001` |
|
||||||
| `CORS_ORIGIN` | Разрешённый origin для CORS | `http://localhost:5173` |
|
| `CORS_ORIGIN` | Разрешённый origin для CORS | `http://localhost:5173` |
|
||||||
|
|
||||||
Фронтенд всегда обращается к API по префиксу `/api` на текущем origin. В локальной разработке этот префикс проксирует Vite (`frontend/vite.config.ts`) на `http://localhost:3001`; в Docker-стеке — nginx фронта проксирует на backend.
|
Фронтенд всегда обращается к API по префиксу `/api` на текущем origin. В локальной разработке этот префикс проксирует Vite (`frontend/vite.config.ts`) на `http://localhost:3001`; в Docker-стеке — nginx фронта проксирует на `runners-calendar-backend:3000`.
|
||||||
|
|
||||||
**Без mock:** при отсутствии любой из `DB_*` процесс падает при старте: `Missing required environment variable: <NAME>`.
|
**Без mock:** при отсутствии любой из `DB_*` процесс падает при старте: `Missing required environment variable: <NAME>`.
|
||||||
|
|
||||||
@@ -118,4 +118,4 @@ backend/
|
|||||||
|
|
||||||
Файл [`docker-compose.stack.yml`](../docker-compose.stack.yml) поднимает API и nginx со статикой SPA в **внешней** сети Docker (рядом с уже запущенным Postgres). Переменные — в **корневом** `.env` (шаблон [`.env.example`](../.env.example)): как минимум `DB_*`, `CORS_ORIGIN` (для выдачи фронта на порту 3033 задайте `http://localhost:3033`). Перед первым `up` файл `.env` должен существовать.
|
Файл [`docker-compose.stack.yml`](../docker-compose.stack.yml) поднимает API и nginx со статикой SPA в **внешней** сети Docker (рядом с уже запущенным Postgres). Переменные — в **корневом** `.env` (шаблон [`.env.example`](../.env.example)): как минимум `DB_*`, `CORS_ORIGIN` (для выдачи фронта на порту 3033 задайте `http://localhost:3033`). Перед первым `up` файл `.env` должен существовать.
|
||||||
|
|
||||||
Порядок после старта контейнеров: `node dist/migrate.js` и `node dist/seed.js` внутри контейнера `backend` (см. комментарии в compose-файле).
|
Порядок после старта контейнеров: `node dist/migrate.js` и `node dist/seed.js` внутри сервиса `runners-calendar-backend` (см. комментарии в compose-файле).
|
||||||
|
|||||||
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "calendar-run-frontend",
|
"name": "calendar-run-frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.3.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "calendar-run-frontend",
|
"name": "calendar-run-frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.3.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "calendar-run-frontend",
|
"name": "calendar-run-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
Reference in New Issue
Block a user