← До програми курсу

Модуль 8 / 18

Мережі Docker: bridge, DNS, публікація портів та IPv6

DOCKER

Зміст
01

1. Цілі та модель мережевого шляху

Після модуля ви зможете пояснити шлях пакета між network namespace, veth, bridge, firewall/NAT та host interface; використовувати вбудований DNS; безпечно публікувати порти й діагностувати IPv4/IPv6 за рівнями.

  • network driver визначає модель зв’язності
  • user-defined bridge створює ізольований L2/L3 segment одного Engine
  • вбудований DNS розпізнає container names та aliases
  • EXPOSE документує порт, publish створює host mapping
  • bind address визначає поверхню доступу
  • IPv6 address не скасовує firewall і routing requirements
02

2. Теорія: namespace, veth та bridge

Контейнер отримує власний network namespace з interfaces, routes та resolver configuration. Для bridge driver один кінець veth перебуває в namespace контейнера, інший підключений до Linux bridge хоста. Docker керує IPAM, forwarding, isolation та masquerading.

Default bridge є спільною legacy-мережею й не надає сучасного автоматичного name resolution між контейнерами. User-defined bridge дає scoped DNS, налаштовуваний subnet/MTU/options і можливість connect/disconnect без перестворення контейнера.

03

3. Теорія: вбудований DNS та service discovery

У user-defined network контейнери звертаються до embedded DNS Docker, зазвичай через 127.0.0.11. Він розпізнає container name та network-scoped aliases в адресу endpoint цієї мережі, а зовнішні запити пересилає налаштованим upstream resolvers.

IP контейнера — runtime detail. Клієнт має використовувати стабільне ім’я/alias та container port. Один container у кількох мережах може мати різні адреси й aliases. DNS resolution не доводить доступність listener: після DNS окремо перевіряють route, TCP та application protocol.

04

4. Теорія: EXPOSE, publish та bind address

EXPOSE записує metadata image і нічого не відкриває. --publish HOST_IP:HOST_PORT:CONTAINER_PORT створює mapping через firewall/NAT або routing mode. Якщо HOST_IP пропущено, порт зазвичай прив’язується до всіх адрес хоста й може стати доступним ззовні.

Для локального administrative endpoint використовуйте 127.0.0.1 або ::1 та перевіряйте реальний listener/firewall. Publish не потрібний для спілкування контейнерів однієї мережі: вони звертаються до container port напряму. -P публікує всі exposed ports на випадкові host ports і рідко підходить production.

05

5. Теорія: forwarding, NAT та host firewall

На Linux Docker створює firewall rules для bridge isolation, masquerading та published ports. Engine 29 підтримує iptables backend і експериментальний nftables backend. Не можна вручну змінювати Docker-owned chains: вони є внутрішньою реалізацією та перестворюються.

Вимкнення iptables/ip6tables у daemon майже завжди ламає network behavior. UFW може бути обійдений DNAT до його звичайних INPUT/OUTPUT rules, тому доступ контролюють з урахуванням Docker forwarding path. Для iptables backend призначений DOCKER-USER; у nftables backend цієї chain немає й потрібні окремі base chains із коректним priority.

06

6. Теорія: IPv6 та dual stack

User-defined bridge можна створити з --ipv6. Сучасний Engine може автоматично виділити ULA prefix, якщо IPv6 pool не заданий. Для production зазвичай планують власний ULA/GUA subnet, routing, neighbor discovery, DNS AAAA та firewall симетрично IPv4.

IPv6 не використовує NAT як обов’язкову модель. Gateway modes nat, routed, nat-unprotected та isolated змінюють direct routing і filtering. Routed mode потребує маршруту ззовні до container subnet; публікація й bind semantics відрізняються, тому обраний mode документують і тестують окремо.

07

7. Методичні вказівки

  • Створюйте окрему мережу для кожної application boundary
  • Використовуйте DNS alias, а не зафіксований container IP
  • Публікуйте лише потрібні ports та явний host address
  • Не застосовуйте host network як обхід DNS або firewall
  • Перевіряйте listener усередині контейнера до host NAT
  • Не змінюйте Docker-owned firewall rules вручну
  • Тестуйте IPv4 та IPv6 незалежно
  • Збирайте network inspect до видалення failed container
08

8. Лабораторна робота: DNS, publish, isolation та IPv6

Зафіксуйте host/network baseline, потім створіть user-defined bridge, web endpoint і client.

terminal
docker info --format '{{json .Plugins.Network}}' | jq
docker network ls
docker network inspect bridge
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding
ip -brief link
ip route
terminal
docker network create --driver bridge docker-m8-app
docker run --detach --name docker-m8-web --network docker-m8-app --network-alias api nginx:1.29-alpine
docker run --detach --name docker-m8-client --network docker-m8-app alpine:3.21 sleep 600
docker exec docker-m8-client cat /etc/resolv.conf
docker exec docker-m8-client nslookup docker-m8-web
docker exec docker-m8-client nslookup api
docker exec docker-m8-client wget -qO- http://api/
docker network inspect docker-m8-app

Доведіть, що EXPOSE образу не публікує порт, потім створіть окремий mapping лише на loopback.

terminal
docker port docker-m8-web
curl --fail --max-time 2 http://127.0.0.1:18088/ || true
docker run --detach --name docker-m8-published --network docker-m8-app --publish 127.0.0.1:18088:80 nginx:1.29-alpine
docker port docker-m8-published
curl --fail --silent --show-error http://127.0.0.1:18088/
docker inspect docker-m8-published --format '{{json .NetworkSettings.Ports}}' | jq

Перевірте isolation двох bridge networks та динамічне підключення endpoint.

terminal
docker network create docker-m8-backend
docker run --detach --name docker-m8-isolated --network docker-m8-backend alpine:3.21 sleep 600
docker exec docker-m8-isolated nslookup docker-m8-web || true
docker network connect docker-m8-app docker-m8-isolated
docker exec docker-m8-isolated wget -qO- http://docker-m8-web/
docker network disconnect docker-m8-app docker-m8-isolated
docker inspect docker-m8-isolated --format '{{json .NetworkSettings.Networks}}' | jq

Створіть тимчасову IPv6-enabled мережу з автоматично призначеним ULA та перевірте ICMPv6 за DNS-ім’ям.

terminal
docker network create --ipv6 docker-m8-v6
docker run --detach --name docker-m8-v6-server --network docker-m8-v6 alpine:3.21 sleep 600
docker run --rm --network docker-m8-v6 alpine:3.21 ping -6 -c 3 docker-m8-v6-server
docker network inspect docker-m8-v6 --format '{{json .IPAM.Config}}' | jq
docker inspect docker-m8-v6-server --format '{{json .NetworkSettings.Networks}}' | jq

Критерій: aliases розпізнаються; unpublished endpoint недоступний через host port; loopback mapping відповідає; окрема мережа ізольована; IPv6 endpoint отримує адресу й відповідає.

09

9. Діагностика: DNS працює, з’єднання немає

Ідіть шляхом packet послідовно: обраний context → endpoint membership → DNS → route → listener → firewall/NAT → protocol. Заміна network mode до локалізації причини знищує evidence.

terminal
docker container ls --all --filter name=docker-m8
docker network ls
docker network inspect docker-m8-app
docker exec docker-m8-client ip address
docker exec docker-m8-client ip route
docker exec docker-m8-client nslookup api
docker exec docker-m8-client wget -S -O- http://api/ 2>&1 | head -40
ss -lntp | grep 18088 || true
docker logs docker-m8-published
  • inspect Networks — чи підключений endpoint і який alias
  • resolv.conf/nslookup — чи працює DNS
  • ip route — чи існує gateway/path
  • listener має слухати потрібний address і container port
  • docker port/inspect Ports — чи існує host mapping
  • ss — чи слухається host port
  • logs — чи дійшов request до застосунку
  • MTU та asymmetric routing перевіряють після базової зв’язності
10

10. Контроль, cleanup і шпаргалка

  • Чому user-defined bridge кращий за default bridge?
  • Що розпізнає 127.0.0.11?
  • Чим EXPOSE відрізняється від --publish?
  • Чому контейнери однієї мережі використовують container port?
  • Як omission HOST_IP змінює exposure?
  • Чому UFW може не обмежити published port очікувано?
  • Що потрібне routed IPv6 network?
  • У якому порядку діагностувати connection refused?
terminal
docker container rm --force docker-m8-web docker-m8-client docker-m8-published docker-m8-isolated docker-m8-v6-server 2>/dev/null || true
docker network rm docker-m8-app docker-m8-backend docker-m8-v6
docker network ls

Модуль засвоєно, якщо ви проєктуєте network boundaries, не залежите від container IP і доводите кожну ділянку шляху DNS → route → listener → firewall → application.