Reverse Proxy — это прокси-сервер, который принимает запросы от клиентов и перенаправляет их на внутренние сервисы, такие как frontend и backend. Одним из самых популярных решений для reverse proxy является Nginx, который может быть использован для маршрутизации запросов между сервисами внутри Docker.
Основные задачи Reverse Proxy:
- Маршрутизация запросов: перенаправление клиентских запросов к правильному сервису.
- Упрощение конфигурации: клиент обращается к одному серверу (reverse proxy), который затем направляет запросы на различные backend и frontend сервисы.
- Изоляция: backend и frontend сервисы скрыты за прокси, клиенты взаимодействуют только с proxy-сервером.
Структура проекта:
- Frontend: простое приложение на Node.js с использованием Express для отдачи статического контента.
- Backend: Node.js приложение на Express для обработки API-запросов.
- Nginx: используется для маршрутизации запросов к frontend и backend.
Пример структуры файлов:
/my-app
/frontend
Dockerfile
server.js
index.html
package.json
/backend
Dockerfile
app.js
package.json
/nginx
nginx.conf
docker-compose.yml
Шаг 1: Настройка Frontend
frontend/server.js:
const express = require('express');
const path = require('path');
const app = express();
const PORT = 3000;
// Обслуживаем статический контент
app.use(express.static(path.join(__dirname)));
// Отправляем index.html для всех запросов
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'index.html'));
});
app.listen(PORT, () => {
console.log(`Frontend server is running on port ${PORT}`);
});
frontend/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Frontend</title>
</head>
<body>
<h1>Welcome to the Frontend</h1>
</body>
</html>
frontend/Dockerfile:
# Используем Node.js как базовый образ
FROM node:14
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем package.json и package-lock.json (если он есть)
COPY package*.json ./
# Устанавливаем зависимости
RUN npm install
# Копируем остальные файлы проекта в контейнер
COPY . .
# Открываем порт 3000
EXPOSE 3000
# Команда для запуска приложения
CMD ["node", "server.js"]
Шаг 2: Настройка Backend
backend/app.js:
const express = require('express');
const app = express();
const PORT = 4000;
// Простое API
app.get('/api', (req, res) => {
res.json({ message: 'Hello from the backend!' });
});
// Новый маршрут для корневого пути
app.get('/', (req, res) => {
res.send('Welcome to the Backend!');
});
app.listen(PORT, () => {
console.log(`Backend server is running on port ${PORT}`);
});
backend/Dockerfile:
# Используем Node.js как базовый образ
FROM node:14
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем package.json и package-lock.json (если он есть)
COPY package*.json ./
# Устанавливаем зависимости
RUN npm install
# Копируем остальные файлы проекта в контейнер
COPY . .
# Открываем порт 4000
EXPOSE 4000
# Команда для запуска приложения
CMD ["node", "app.js"]
Шаг 3: Настройка Nginx как Reverse Proxy
nginx/nginx.conf:
events {
worker_connections 1024; # Установка количества соединений
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://frontend:3000; # Прокси для frontend
}
location /api/ {
proxy_pass http://backend:4000; # Прокси для backend
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Шаг 4: Настройка Docker Compose
docker-compose.yml:
services:
frontend:
build: ./frontend
container_name: frontend
ports:
- "3000:3000" # Фронтенд работает на порту 3000
networks:
- mynetwork
backend:
build: ./backend
container_name: backend
ports:
- "4000:4000" # Бэкенд работает на порту 4000
networks:
- mynetwork
nginx:
image: nginx:alpine
container_name: nginx
ports:
- "80:80" # Nginx работает на порту 80
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf # Привязка конфигурации
networks:
- mynetwork
depends_on:
- frontend
- backend
networks:
mynetwork:
driver: bridge
Шаг 5: Файл package.json (frontend) & package.json (backend)
frontend:
{
"name": "frontend",
"version": "1.0.0",
"main": "server.js",
"dependencies": {
"express": "^4.17.1"
}
}
backend:
{
"name": "backend",
"version": "1.0.0",
"main": "app.js",
"dependencies": {
"express": "^4.17.1"
}
}
Шаг 6: Запуск приложения
- Перейдите в корневую директорию проекта
/my-app
. - Выполните команду для сборки и запуска контейнеров:
docker-compose up --build
Как это работает:
- Nginx действует как reverse proxy и принимает все запросы на порт 80.
- Запросы, начинающиеся с
/api
, перенаправляются на backend-сервис (контейнерbackend
на порту 4000). - Все остальные запросы (например, к корневому URL) перенаправляются на frontend-сервис (контейнер
frontend
на порту 3000). - Клиенты взаимодействуют с Nginx, который маршрутизирует их запросы в зависимости от URL.
Пример запросов:
- Запрос к frontend:
- Откройте в браузере
http://localhost
, и вы увидите страницу frontend, отданную через Node.js.
- Откройте в браузере
- Запрос к backend:
- Перейдите на
http://localhost/api
, и вы увидите JSON-ответ от backend-сервиса:{"message": "Hello from the backend!"}
- Перейдите на
Вывод:
Использование Nginx как reverse proxy для разделения frontend и backend приложений через Docker предоставляет эффективный способ маршрутизации запросов. Такая архитектура упрощает управление, повышает безопасность и делает приложение масштабируемым.
Проект на GitHub: https://github.com/wa-magazin/reverseproxy