Docker reverse proxy: Nginx, порти та доступ до контейнерів у локальній мережі
Reverse proxy – це єдина вхідна точка для кількох вебсервісів. Він приймає запит з браузера, визначає домен або шлях і передає його потрібному контейнеру. Так не потрібно відкривати в локальну мережу десяток портів: назовні доступний тільки Nginx на 80/443, а застосунки залишаються у внутрішній Docker-мережі.
Що часто називають «світчем» у Docker
- Публікація портів:
8081:80. Windows отримує порт 8081 і передає його в контейнер на 80. Сервіс відкривається якhttp://IP_ПК:8081. - Reverse proxy: один Nginx на 80/443 розподіляє запити за доменами або шляхами – наприклад,
php.local.testдо PHP,api.local.testдо Python.
Не призначайте постійні IP контейнерам лише для маршрутизації. У Docker Compose сервіси знаходять один одного за іменами php-app та python-api через вбудований DNS. Це і є нормальна внутрішня комутація контейнерів.
Схема стенду
Браузер / локальна мережа
|
Windows:80, 443
|
reverse-proxy (Nginx)
| |
php-app:80 python-api:8000Лише reverse proxy має секцію ports. Застосунки використовують expose, тобто доступні тільки іншим контейнерам у приватній мережі.
1. Структура проєкту на D:
D:\docker-proxy-lab\
├── compose.yaml
├── proxy\default.conf
├── php-app\index.html
└── python-api\
├── Dockerfile
├── requirements.txt
└── app.pyNew-Item -ItemType Directory -Force D:\docker-proxy-lab\proxy
New-Item -ItemType Directory -Force D:\docker-proxy-lab\php-app
New-Item -ItemType Directory -Force D:\docker-proxy-lab\python-api
Set-Location D:\docker-proxy-lab2. Compose: три сервіси, одна мережа
Створіть D:\docker-proxy-lab\compose.yaml:
services:
proxy:
image: nginx:1.27-alpine
ports:
- "80:80"
volumes:
- ./proxy/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php-app
- python-api
networks: [web]
restart: unless-stopped
php-app:
image: nginx:1.27-alpine
volumes:
- ./php-app:/usr/share/nginx/html:ro
expose: ["80"]
networks: [web]
restart: unless-stopped
python-api:
build: ./python-api
expose: ["8000"]
networks: [web]
restart: unless-stopped
networks:
web:
driver: bridgeЯкщо порт 80 зайнятий IIS або іншою програмою Windows, для тесту замініть mapping на 8080:80. Тоді користуйтеся адресою http://localhost:8080.
3. Конфігурація Nginx reverse proxy
У D:\docker-proxy-lab\proxy\default.conf:
server {
listen 80;
server_name php.local.test;
location / {
proxy_pass http://php-app:80;
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;
}
}
server {
listen 80;
server_name api.local.test;
location / {
proxy_pass http://python-api:8000;
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. Тестові застосунки
У D:\docker-proxy-lab\php-app\index.html:
<h1>PHP / static application</h1>
<p>Запит прийшов через Docker reverse proxy.</p>У D:\docker-proxy-lab\python-api\requirements.txt:
Flask==3.1.1У D:\docker-proxy-lab\python-api\app.py:
from flask import Flask, jsonify
app = Flask(__name__)
@app.get("/")
def index():
return jsonify(service="python-api", status="ok")
@app.get("/health")
def health():
return jsonify(status="healthy")У D:\docker-proxy-lab\python-api\Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["flask", "--app", "app", "run", "--host=0.0.0.0", "--port=8000"]5. Локальні доменні імена
Відкрийте Блокнот від імені адміністратора і додайте в C:\Windows\System32\drivers\etc\hosts:
127.0.0.1 php.local.test
127.0.0.1 api.local.testТепер один Nginx на одному порту розрізняє два сайти за HTTP-заголовком Host.
6. Запуск і тест
Set-Location D:\docker-proxy-lab
docker compose up --build -d
docker compose ps
curl.exe http://php.local.test
curl.exe http://api.local.test/healthВідкрийте http://php.local.test та http://api.local.test. Браузер іде на один порт Windows, а Nginx обирає правильний контейнер.
Як дати доступ локальній мережі
Для прямого тесту окремого сервісу використайте mapping "8081:80". Дізнайтеся IP ПК командою ipconfig, після чого адреса буде схожа на http://192.168.1.50:8081. Дозвольте цей TCP-порт у Windows Defender Firewall лише для профілю Private і вимкніть правило після тесту.
Якщо сервіс має бути доступний тільки на цьому ПК, прив’яжіть mapping до loopback: "127.0.0.1:8081:80". Для суто внутрішніх контейнерів взагалі не задавайте ports – залишайте лише expose.
Навіщо це потрібно
- один вхідний порт замість десятків портів застосунків;
- розподіл сервісів за доменами або шляхами;
- єдине місце для HTTPS, логів, rate limiting і правил безпеки;
- застосунки не стають напряму видимими з мережі;
- схема легко переноситься на VPS або внутрішній сервер.
Для навчального середовища Nginx достатній. Для автоматичного HTTPS у кількох доменах можна окремо розглянути Traefik або Caddy, але розуміння базового Nginx reverse proxy корисне у будь-якому стеку.