Docker macvlan і bridge вирішують різні задачі. Якщо контейнеру потрібна пряма присутність у LAN, окрема IP-адреса й власний MAC – беруть macvlan. Якщо достатньо доступу через порти хоста, краще лишатися на bridge. Нижче – де межа між цими підходами, де вони ламаються і як не ускладнити собі мережу без причини.
У homelab помилка тут типова: macvlan вмикають тільки тому, що так “гарніше” виглядає в DHCP-списку або хочеться бачити контейнер як окремий хост. На практиці це майже завжди зайве. Окрема IP потрібна не контейнеру як такому, а сервісу, який погано живе за NAT, port mapping або reverse proxy.
Нормальна відправна точка проста. Починати з bridge, а до macvlan переходити лише тоді, коли є конкретна мережева причина: broadcast discovery, жорстка прив’язка до порту 53 або 67, вимога бачити клієнта напряму на рівні LAN, або конфлікт однакових портів між кількома сервісами.
Коли вибирати bridge, а коли docker macvlan
Bridge – базовий режим Docker. Контейнер сидить у внутрішній мережі Docker, а назовні публікуються тільки потрібні порти. Docker macvlan підключає контейнер прямо до фізичної мережі, ніби це окремий вузол на комутаторі.
| Критерій | bridge | macvlan |
|---|---|---|
| IP-адреса в LAN | Ні, контейнер ховається за IP хоста | Так, окрема IP для контейнера |
| Доступ через port mapping | Так | Зазвичай не потрібен |
| Broadcast і multicast у LAN | Часто незручно або з обмеженнями | Працює природніше |
| Видимість контейнера як окремого хоста | Ні | Так |
| Складність підтримки | Низька | Вища |
| Типові проблеми | Порти, NAT, hairpin | Зв’язок host ↔ container, VLAN, DHCP-конфлікти |
Для більшості self-hosted сервісів bridge достатньо. Web-додатки, dashboards, Git-сервіси, reverse proxy, metrics stack, внутрішні API – усе це нормально працює через bridge і published ports.
Docker macvlan виправданий там, де сервіс повинен поводитися як окремий пристрій у мережі. Типові приклади – DNS-сервер на 53 порту, мережевий сервіс із discovery через broadcast, legacy-додаток із жорстко заданими адресами або контейнер, який має бути доступний без участі хоста як NAT-шлюзу.
Нетривіальна межа така: якщо причина переходу до docker macvlan лише в тому, що “не хочеться пам’ятати порти”, це слабкий аргумент. Проблема тут не в bridge, а в відсутності нормального DNS або reverse proxy.
Коли контейнеру справді потрібна окрема IP-адреса
Окрема IP-адреса потрібна нечасто. Вона має сенс, коли сервіс прив’язаний до стандартного мережевого порту, коли потрібно уникнути NAT, або коли інші вузли в LAN повинні бачити контейнер напряму як повноцінний endpoint.
Найчастіші сценарії такі:
- потрібен DNS на 53 порту, а хост уже використовує цей порт або не має його торкатися;
- контейнер слухає DHCP-подібний сервіс, де проста публікація портів не закриває весь сценарій;
- сервіс використовує broadcast або multicast для пошуку клієнтів;
- треба підняти кілька контейнерів з однаковими службовими портами без гри в нестандартні порти на хості;
- мережеві ACL, firewall або інвентаризація очікують окремий IP, а не спільний IP хоста.
У решті випадків окрема адреса тільки додає клопоту. З’являється ще один вузол у DHCP, окремі правила в firewall, окремий запис у DNS, більше шансів на плутанину з маршрутами. Для одного Pi-hole або AdGuard Home це ще терпимо. Для десятка контейнерів мережа швидко втрачає читабельність.
Особливо це помітно в невеликих homelab-сегментах, де IP-план і так щільний. Кожен додатковий macvlan-контейнер виглядає як маленький VM, але керується як контейнер. Найгірше з обох світів, якщо вибір був без реальної потреби.
Що міняє docker macvlan в мережевій схемі
У режимі docker macvlan контейнер отримує власну мережеву ідентичність у фізичному сегменті. Для комутатора і сусідніх хостів він виглядає окремим пристроєм. Docker bridge, навпаки, лишає контейнер усередині програмної мережі, а трафік назовні йде через стек хоста.
Різниця не тільки в IP. У bridge зручно керувати доступом через published ports, reverse proxy і внутрішні мережі Docker. У macvlan контейнер вилазить у LAN майже без посередників. Це спрощує деякі мережеві сервіси, але ламає звичну модель ізольованого контейнера.
На практиці головна пастка така: host і macvlan-контейнер часто не бачать один одного напряму, хоча обидва сидять в одній підмережі. Для новачка це виглядає абсурдно, але це типова поведінка схеми. Через це ламаються локальні health-check, моніторинг із хоста, резервне копіювання через localhost-подібні маршрути і просто звичка тестувати сервіс з того ж сервера.
Через це docker macvlan не варто вмикати для звичайних web-сервісів. Якщо reverse proxy, Prometheus або backup-агент працюють на тому ж хості, bridge дає передбачуваніший трафік і менше сюрпризів.
Як підняти macvlan без зайвого хаосу
Налаштування docker macvlan краще робити через окремий пул адрес поза DHCP-діапазоном. Інакше конфлікт адрес рано чи пізно трапиться. Базова схема – створити мережу macvlan, прив’язати її до фізичного інтерфейсу і видати контейнеру статичну адресу.
- Переконатися, що вибраний інтерфейс підключений до потрібного LAN або VLAN.
- Виділити підмережу чи частину діапазону, яку не роздає DHCP.
- Створити мережу macvlan у Docker.
- Запустити контейнер із фіксованою IP-адресою.
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 macvlan_lan docker run -d --name pihole --network macvlan_lan --ip 192.168.1.53 pihole/pihole:latest
Якщо потрібен зв’язок між хостом і контейнером, на хості зазвичай створюють додатковий macvlan-інтерфейс і окремий маршрут до цього сегмента.
ip link add macvlan-host link eth0 type macvlan mode bridge ip addr add 192.168.1.254/32 dev macvlan-host ip link set macvlan-host up ip route add 192.168.1.53/32 dev macvlan-host
Схема робоча, але вже видно ціну. З bridge таких обхідних маневрів не потрібно.
Деталі мереж Docker описані в офіційній документації Docker Engine networking.
Bridge у homelab зазвичай виграє
Bridge варто вважати стандартом, а не компромісом. Для більшості homelab-сервісів він дає простішу модель: один IP хоста, явні published ports, внутрішня взаємодія контейнерів через Docker network, менше сюрпризів у firewall і маршрутах.
Якщо сервіс зовнішній, його часто простіше прокинути через reverse proxy на хості або в окремому контейнері. Якщо сервіс внутрішній, published port або внутрішня мережа Docker закривають задачу без окремої IP. Так легше переносити стек між хостами, робити резервні копії конфігів і не думати, які адреси вже зайняті в LAN.
Є ще один практичний нюанс. Коли контейнерів стає багато, bridge краще масштабується в операційному сенсі. Не тому, що трафік “швидший”, а тому, що схема простіша для голови: менше IP, менше записів у DNS, менше ручних винятків у мережевих правилах.
Для сервісів на кшталт Nginx Proxy Manager, Traefik, Grafana, Gitea, Home Assistant у звичайному режимі, Immich, Jellyfin, Vaultwarden окрема LAN-адреса рідко дає реальну користь. Зате додає ще одну площину відлагодження.
Де docker macvlan найчастіше створює проблеми
Docker macvlan працює добре, поки схема проста і зрозуміла. Проблеми починаються на стику з хостом, VLAN, свічем і локальними сервісами самого сервера. Саме там більшість дивних багів і з’являється.
Host не може достукатися до контейнера
Найтиповіша ситуація. Контейнер доступний з інших машин у LAN, але не з самого Docker-хоста. Для моніторингу, backup jobs або локального reverse proxy це ламає половину сценаріїв. Доводиться створювати окремий macvlan-інтерфейс на хості або відмовлятися від схеми.
DHCP-конфлікти і випадкові дублікати IP
Якщо адреси для docker macvlan не винесені поза DHCP pool, конфлікти неминучі. Спершу все працює. Потім роутер видає ту саму IP іншому вузлу, і починається хаос, який складно відстежити.
Комутатор або hypervisor не любить зайві MAC-адреси
У віртуалізованому homelab середовищі це трапляється регулярно. Якщо Docker-хост живе всередині VM, а зверху ще є vSwitch, bridge group або портова безпека, додаткові MAC від macvlan можуть блокуватися. Формально контейнер піднявся, але трафіку немає.
Занадто багато “маленьких окремих хостів”
До 2-3 контейнерів схема ще читається. Після цього docker macvlan починає розмножувати сутності: IP, DNS-записи, ACL, статичні lease, моніторинг. Для одного DNS-сервера це нормально. Для цілого self-hosted стека вже сумнівно.
Як перевірити, що мережа працює правильно
Після налаштування треба перевірити три речі: контейнер бачиться в LAN, потрібний сервіс слухає на очікуваному IP, а маршрути між хостом і контейнером поводяться так, як задумано. Без цього docker macvlan виглядає “майже робочим”, хоча половина сценаріїв уже зламана.
- Подивитися параметри мережі Docker.
- Переконатися, що контейнер отримав правильну IP.
- Перевірити доступ із іншого вузла в тій самій підмережі.
- Окремо перевірити доступ саме з Docker-хоста.
- Звірити ARP і маршрути, якщо є дивна асиметрія.
docker network inspect macvlan_lan docker inspect pihole ping 192.168.1.53 curl http://192.168.1.53
Якщо з LAN усе відкривається, а з хоста ні – проблема майже точно в типових обмеженнях macvlan, а не в самому контейнері. Іноді це сигнал, що для конкретного сервісу bridge був би кращим вибором.
Що ставити в homelab без зайвого героїзму
Для більшості сценаріїв вибір простий: bridge за замовчуванням, docker macvlan тільки під конкретну мережеву вимогу. Якщо сервіс нормально живе за reverse proxy або published ports, окрема IP-адреса йому не потрібна.
Macvlan має сенс для DNS, discovery-сервісів, нестандартних legacy-штук і випадків, де контейнер повинен виглядати окремим вузлом у LAN. Усе інше краще лишати на bridge. Менше магії, менше ручної маршрутизації, менше шансів зламати собі моніторинг через надто “чисту” мережеву схему.