Реверс-проксі Docker через Nginx Proxy Manager закриває просту, але неприємну задачу: винести кілька контейнерів назовні під нормальними доменами, видати HTTPS і не писати руками конфіг Nginx на кожен сервіс. У цьому сценарії один контейнер приймає зовнішній трафік, термінує TLS, отримує сертифікати Let’s Encrypt і прокидує запити у потрібні Docker-сервіси.
Для homelab це працює добре, якщо сервісів небагато і потрібна зрозуміла веб-панель замість labels, шаблонів і власної автоматики. Межа підходу з’являється пізніше: коли контейнерів стає багато, зростає кількість правил, а проксі починає жити окремим життям від Docker-оточення.
Результат після налаштування такий: кожен self-hosted сервіс відкривається за своїм доменом або субдоменом, трафік йде через один reverse proxy, сертифікати оновлюються автоматично, а внутрішні порти сервісів не треба публікувати в інтернет напряму.
Схема, яка не ламається на другий день
Найпростіша схема для реверс-проксі Docker – окрема Docker network, у якій одночасно знаходяться Nginx Proxy Manager і контейнери, до яких він має звертатися. Тоді проксі бачить upstream не через IP хоста, а напряму за іменем контейнера або сервісу в мережі Docker.
Саме тут часто роблять першу помилку: проксі контейнер запускають в одній мережі, застосунки – в іншій, а потім намагаються прокидати трафік через localhost або IP хоста. Працює нестабільно. Після перезапусків і змін адрес починаються 502, а діагностика перетворюється на дрібний біль.
Практичний варіант для homelab такий:
- створити окрему зовнішню мережу Docker для reverse proxy;
- підключити до неї Nginx Proxy Manager;
- підключати до тієї ж мережі лише ті сервіси, які треба публікувати;
- зовні відкрити тільки 80 і 443 на хості з проксі.
docker network create proxy
Запуск Nginx Proxy Manager у Docker
Nginx Proxy Manager для цього сценарію зазвичай запускають через Docker Compose. Потрібні три речі: порти 80 і 443 для HTTP/HTTPS, порт панелі керування, а також постійне сховище для конфігів і сертифікатів.
Нижче мінімальна схема без зайвих надбудов. Вона підходить для старту і не вимагає зовнішньої бази даних.
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- proxy
networks:
proxy:
external: true
Після запуску панель буде доступна на порту 81. Далі в неї додаються proxy host записи для кожного сервісу. Офіційний сайт проєкту – Nginx Proxy Manager.
Окремий нюанс. Якщо на хості вже працює інший Nginx, Apache або Traefik і слухає 80/443, контейнер не підніметься. Тут або переносити старий сервіс, або міняти роль вузла. Два фронтові проксі на одних портах без додаткової схеми не живуть.
Як підключити self-hosted сервіс до reverse proxy
Щоб реверс-проксі Docker бачив контейнер, сервіс треба під’єднати до тієї ж мережі proxy. Сам сервіс при цьому може лишатися і в своїй внутрішній мережі. Це нормальна практика: одна мережа для зв’язку з базою або кешем, друга – для фронтового проксі.
Приклад з умовним застосунком, який слухає порт 3000:
services:
app:
image: your-app-image
container_name: app
restart: unless-stopped
networks:
- internal
- proxy
networks:
internal:
proxy:
external: true
Далі в панелі Nginx Proxy Manager створюється запис:
- Domain Names – домен або субдомен сервісу
- Scheme – http
- Forward Hostname / IP – app
- Forward Port – 3000
Критичний момент – у полі upstream краще вказувати ім’я контейнера або сервісу в Docker network, а не IP. Docker DNS вирішує цю задачу сам. Інакше після recreation контейнера адреса зміниться, а проксі залишиться дивитися в порожнечу.
HTTPS і Let's Encrypt без ручного шаманства
HTTPS у Nginx Proxy Manager вмикається на рівні конкретного proxy host. Для домену має вже існувати коректний DNS-запис, який дивиться на зовнішню адресу хоста з проксі. Після цього панель може запросити сертифікат Let’s Encrypt і прив’язати його до правила.
Типовий порядок такий:
- створити DNS A-запис або AAAA-запис на потрібний домен;
- дочекатися, поки домен резолвиться в правильну адресу;
- створити proxy host у панелі;
- увімкнути отримання сертифіката Let’s Encrypt;
- примусово редіректити HTTP на HTTPS.
Якщо домен не дивиться на ваш вузол, сертифікат не видасться. Якщо провайдер блокує 80 порт або він не проброшений на маршрутизаторі, HTTP challenge теж зламається. У домашніх мережах це одна з найчастіших причин, чому все ніби налаштовано, а сертифікат не приходить.
На практиці реверс-проксі Docker через Nginx Proxy Manager особливо зручний для сервісів на кшталт Grafana, Gitea, Nextcloud, Home Assistant або внутрішніх адмінок. Але тільки поки домени йдуть через один вузол і не потрібні складні правила маршрутизації.
DNS, NAT loopback і чому з дому все інколи не відкривається
Якщо сервіс відкривається з мобільного інтернету, але не відкривається з локальної мережі за тим самим доменом, проблема часто не в проксі. Найчастіше винен NAT loopback, який на частині домашніх маршрутизаторів працює погано або не працює зовсім.
Тоді є три робочі варіанти:
- локальний DNS у домашній мережі, який віддає внутрішню адресу reverse proxy;
- маршрутизатор з нормальною підтримкою hairpin NAT;
- окремий split-horizon DNS для LAN і зовнішнього доступу.
Саме через це в homelab краще рано підняти локальний DNS, ніж нескінченно шукати проблему в контейнерах. Коли доменні імена однаково працюють і ззовні, і зсередини, половина дрібних збоїв просто зникає.
Де зазвичай ламається реверс-проксі Docker
Реверс-проксі Docker найчастіше ламається не в TLS і не в самому Nginx Proxy Manager. Збій зазвичай сидить у мережі Docker, DNS, пробросі портів або в налаштуванні самого застосунку, який не довіряє заголовкам від проксі.
502 Bad Gateway
Зазвичай причина одна з трьох: контейнер не в тій мережі, вказане неправильне ім’я upstream, або сервіс слухає не той порт. Іноді застосунок стартує довше за проксі, але це рідше.
Сертифікат не випускається
Тут перевіряють DNS, доступність 80 порту ззовні, проброс портів на маршрутизаторі й відсутність іншого процесу на 80/443. Якщо домен за Cloudflare або іншим proxy-сервісом, інколи заважає їхній режим проксування.
Редірект-луп після входу в сервіс
Багато self-hosted застосунків треба окремо вчити, що вони працюють за reverse proxy і зовнішній URL у них вже https. Якщо цього не зробити, виникають циклічні редіректи, змішаний контент або поламані callback URL.
WebSocket працює криво
Nginx Proxy Manager зазвичай з цим справляється, але окремі адмінки й realtime-сервіси дуже чутливі до таймаутів і буферизації. На малій інсталяції все гаразд. Під навантаженням починаються дивні обриви, які виглядають як проблема застосунку.
Нетривіальне, але важливе спостереження: у homelab Nginx Proxy Manager часто використовують як універсальний фронт для всього підряд, включно з сервісами, яким зовнішній доступ не потрібен. Це погана звичка. Кожен зайвий опублікований хост збільшує поверхню атаки, навіть якщо на ньому стоїть HTTPS і базова авторизація.
Як перевірити, що все налаштовано правильно
Після налаштування не треба одразу довіряти зеленому замку в браузері. Перевірка має пройти по шару DNS, TLS і реального проксування до контейнера. Інакше можна отримати сертифікат на домен, який відкриває не той сервіс або взагалі стару адресу.
- Перевірити, куди резолвиться домен.
- Переконатися, що 80 і 443 доступні ззовні.
- Відкрити домен по HTTPS і перевірити сертифікат.
- Переглянути логи контейнера Nginx Proxy Manager.
- Перевірити логи самого застосунку.
docker ps docker logs nginx-proxy-manager docker network inspect proxy
Якщо домен відкриває сервіс, сертифікат валідний, а контейнер доступний за іменем у мережі proxy – реверс-проксі Docker налаштований коректно.
Коли Nginx Proxy Manager вже тісний
Для кількох self-hosted сервісів це хороший компроміс. Панель зрозуміла, сертифікати виписуються без ручної рутини, базовий reverse proxy закривається швидко. Але коли інфраструктура росте, веб-інтерфейс починає заважати автоматизації.
Після десятка-другого сервісів зручніше стають підходи, де правила живуть поруч із контейнерами і керуються декларативно. Тут зазвичай дивляться в бік Traefik або окремого Nginx з git-керованими конфігами. Бо головна проблема вже не в тому, як прокинути ще один субдомен, а в тому, як не втратити контроль над усією схемою.
Офіційний сайт Docker – Docker. Документація Let’s Encrypt – Let's Encrypt.