193 lines
8.9 KiB
Markdown
193 lines
8.9 KiB
Markdown
# 🏗️ Архитектура приложения
|
||
|
||
## Как работает автоматическое определение API URL
|
||
|
||
### ❌ Старый подход (проблемный):
|
||
```
|
||
.env файл: FRONTEND_API_URL=http://185.56.162.170:8080/api
|
||
└─ Нужно обновлять для каждого окружения (dev, staging, prod)
|
||
└─ Нужно пересобирать контейнер при смене IP/домена
|
||
└─ Хранит хардкод конфигурации
|
||
```
|
||
|
||
### ✅ Новый подход (умный):
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ БРАУЗЕР ПОЛЬЗОВАТЕЛЯ │
|
||
│ http://185.56.162.170:80 или http://my-domain.com │
|
||
└────────────────────────┬────────────────────────────────────────┘
|
||
│ (window.location = текущий адрес)
|
||
│
|
||
┌────▼─────┐
|
||
│ NGINX │ (Gate для всех запросов)
|
||
│ :80 │
|
||
└────┬─────┘
|
||
│
|
||
┌────────────┬────────────┐
|
||
│ │ │
|
||
GET / │ GET /api/* GET /static/*
|
||
│ │ │
|
||
┌──▼──┐ ┌────▼──┐ ┌──▼──────┐
|
||
│FRONT│ │ BACK │ │ STATIC │
|
||
│END │ │ END │ │ CACHE │
|
||
└─────┘ └───────┘ └─────────┘
|
||
|
||
Фронтенд код:
|
||
- ✅ Использует window.location.origin для определения хоста
|
||
- ✅ Обращается к /api (относительный путь, не айпи)
|
||
- ✅ Nginx проксирует /api на backend контейнер
|
||
- ✅ Работает везде без переконфигурирования!
|
||
```
|
||
|
||
## Как это использовать в коде
|
||
|
||
### В App.js или любом React компоненте:
|
||
|
||
```javascript
|
||
import API_CONFIG from './api/config';
|
||
|
||
function MyComponent() {
|
||
useEffect(() => {
|
||
// Автоматически определится правильный API URL
|
||
// Локально: http://localhost:3000/api/users
|
||
// На VPS: http://185.56.162.170:80/api/users
|
||
// С доменом: http://my-domain.com/api/users
|
||
|
||
API_CONFIG.fetch('users')
|
||
.then(data => console.log(data));
|
||
}, []);
|
||
}
|
||
```
|
||
|
||
## Преимущества
|
||
|
||
| Параметр | Старый подход | Новый подход |
|
||
|----------|---------------|-------------|
|
||
| Нужно менять .env | ✅ Да | ❌ Нет |
|
||
| Нужно пересобирать образ | ✅ Да | ❌ Нет |
|
||
| Работает на localhost | ✅ Да | ✅ Да |
|
||
| Работает на IP адресе | ✅ Да | ✅ Да |
|
||
| Работает на домене | ✅ Да | ✅ Да |
|
||
| CORS проблемы | ✅ Иногда | ❌ Нет |
|
||
| Безопасность | ⚠️ Хардкод | ✅ Динамично |
|
||
|
||
## Docker сетевая архитектура
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Docker Network: pg-admin-network (bridge) │
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ │
|
||
│ │ pg-admin-db │ │pg-admin-cache│ │
|
||
│ │ Port: 5432 │ │ Port: 6379 │ │
|
||
│ │ (internal) │ │ (internal) │ │
|
||
│ └──────────────┘ └──────────────┘ │
|
||
│ △ △ │
|
||
│ │ │ │
|
||
│ └──────┬─────────────┘ │
|
||
│ │ │
|
||
│ ┌──────▼──────────┐ │
|
||
│ │ pg-admin-api │ │
|
||
│ │ Port: 3000 │ │
|
||
│ │ (internal) │ │
|
||
│ └────────┬────────┘ │
|
||
│ │ │
|
||
│ ┌─────────────┼──────────────┐ │
|
||
│ │ │ │ │
|
||
│ ▼ ▼ ▼ │
|
||
│ ┌──────────┐ ┌────────────┐ ┌───────────┐ │
|
||
│ │frontend │ │pg-admin-ui │ │ DATABASE │ │
|
||
│ │ │ │ Port: 3000 │ │ Postgres │ │
|
||
│ │Port: 80 │ │(internal) │ │ 15-alpine │ │
|
||
│ └────┬─────┘ └────────────┘ └───────────┘ │
|
||
│ │ │
|
||
└──────┼──────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌──────────────┐
|
||
│ pg-admin-proxy (Nginx)
|
||
│ Listen: 80 (EXTERNAL)
|
||
└──────────────┘
|
||
│
|
||
├─ GET / → frontend:3000
|
||
├─ GET /api/* → backend:3000
|
||
└─ GET /static/* → cache 365 дней
|
||
|
||
Все контейнеры видят друг друга по имени (DNS):
|
||
- backend может подключиться к postgres:5432
|
||
- backend может подключиться к redis:6379
|
||
- Nginx может подключиться к frontend:3000 и backend:3000
|
||
```
|
||
|
||
## Переменные окружения (только на VPS)
|
||
|
||
Теперь в .env нужны ТОЛЬКО:
|
||
|
||
```env
|
||
# Development / Production
|
||
NODE_ENV=production
|
||
|
||
# Пароли (генерируются openssl)
|
||
DB_PASSWORD=...
|
||
JWT_SECRET=...
|
||
REDIS_PASSWORD=...
|
||
|
||
# Остальное опционально
|
||
LOG_LEVEL=info
|
||
RATE_LIMIT_MAX_REQUESTS=100
|
||
```
|
||
|
||
**НЕ нужны больше:**
|
||
- ❌ FRONTEND_API_URL
|
||
- ❌ CORS_ORIGIN (используется * по умолчанию)
|
||
- ❌ FRONTEND_PORT
|
||
- ❌ API_PORT (внутренние порты)
|
||
- ❌ DB_PORT (внутренние порты)
|
||
|
||
## Примеры использования
|
||
|
||
### Локальная разработка:
|
||
```bash
|
||
docker compose up --build
|
||
# Открой http://localhost:80
|
||
# Фронтенд будет обращаться к http://localhost:80/api
|
||
# Nginx проксирует на backend контейнер
|
||
```
|
||
|
||
### На VPS:
|
||
```bash
|
||
docker compose up -d --build
|
||
# Открой http://185.56.162.170:80
|
||
# Фронтенд будет обращаться к http://185.56.162.170:80/api
|
||
# Nginx проксирует на backend контейнер
|
||
```
|
||
|
||
### С доменом:
|
||
```bash
|
||
# Просто открой https://my-domain.com
|
||
# Фронтенд будет обращаться к https://my-domain.com/api
|
||
# Все работает автоматически!
|
||
```
|
||
|
||
## Безопасность
|
||
|
||
✅ **Защищено:**
|
||
- ✅ БД не открыта наружу
|
||
- ✅ Redis не открыт наружу
|
||
- ✅ API не открыт напрямую (только через Nginx)
|
||
- ✅ Все запросы проходят через Nginx (централизованный контроль)
|
||
- ✅ Нет хардкода IP адресов в коде
|
||
- ✅ Пароли не в git
|
||
|
||
⚠️ **Нужно настроить:**
|
||
- SSH ключи (вместо пароля)
|
||
- UFW файрвол (только необходимые порты)
|
||
- SSL/HTTPS (Let's Encrypt)
|
||
- Rate limiting (уже включен)
|
||
- Логирование (уже включено)
|
||
|
||
---
|
||
|
||
**Готово к production! 🚀**
|