Files
pg-adx/ARCHITECTURE.md
2026-03-18 16:09:47 +07:00

8.9 KiB
Raw Blame History

🏗️ Архитектура приложения

Как работает автоматическое определение 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! 🚀