← К программе курса

Модуль 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.