8.9 KiB
8.9 KiB
🏗️ Архитектура приложения
Как работает автоматическое определение 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 компоненте:
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 нужны ТОЛЬКО:
# 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 (внутренние порты)
Примеры использования
Локальная разработка:
docker compose up --build
# Открой http://localhost:80
# Фронтенд будет обращаться к http://localhost:80/api
# Nginx проксирует на backend контейнер
На VPS:
docker compose up -d --build
# Открой http://185.56.162.170:80
# Фронтенд будет обращаться к http://185.56.162.170:80/api
# Nginx проксирует на backend контейнер
С доменом:
# Просто открой 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! 🚀