Как устроен роутинг (маршрутизация) трафика в Docker?

Ответ

Маршрутизация трафика в Docker обеспечивается его сетевой подсистемой, которая под капотом использует возможности Linux: network namespaces, virtual bridge interfaces и iptables.

Основные сетевые драйверы и их работа:

  1. bridge (драйвер по умолчанию):

    • Docker создает виртуальный мост docker0 (или пользовательский br-xxx).
    • Каждый контейнер подключается к этому мосту через свою виртуальную пару интерфейсов (veth).
    • Контейнеры получают IP-адреса из подсети моста (например, 172.17.0.0/16).
    • Роутинг между контейнерами: Происходит на уровне L2 через мост. Контейнеры могут общаться по IP друг друга.
    • Роутинг наружу (интернет): Трафик из контейнера, направленный не в локальную подсеть, через правила iptables в таблице nat маскарадится (SNAT) на IP-адрес хоста.
  2. host: Контейнер использует сетевой неймспейс хоста. Нет изоляции, контейнер «видит» все сетевые интерфейсы и порты хоста. Роутинг происходит по правилам хоста.

  3. overlay: Используется в Docker Swarm и Kubernetes для связи контейнеров на разных физических хостах.

    • Создается overlay-сеть (например, 10.0.0.0/24).
    • На каждом хосте создается виртуальный интерфейс (типа VXLAN), который инкапсулирует трафик между хостами.
    • Встроенный DNS позволяет контейнерам находить друг друга по имени сервиса.

Практический пример и проверка:

# Создаем пользовательскую bridge-сеть
docker network create --driver bridge my-app-net

# Запускаем контейнер в этой сети
docker run -d --name web --network my-app-net nginx

# Проверяем маршрутизацию внутри контейнера
docker exec web ip route
# Вывод будет примерно: default via 172.19.0.1 dev eth0 ...
# Где 172.19.0.1 — это IP шлюза (bridge-интерфейса на хосте).

# Проверяем правила iptables, которые Docker добавил для NAT и изоляции
sudo iptables -t nat -L -n | grep docker

Таким образом, Docker полностью управляет маршрутизацией, изоляцией и NAT, абстрагируя это от пользователя, но понимание механизмов необходимо для диагностики проблем.

Ответ 18+ 🔞

А, ну это же про то, как докер трафик гоняет! Ёпта, тема, конечно, важная, но если не копнуть, то кажется, будто там магия какая-то, а не технологии.

Смотри, вся их движуха крутится вокруг сетевой подсистемы линукса. Не пугайся, я объясню без зауми. По сути, докер юзает три кита: неймспейсы сети (это чтобы контейнеры друг друга не видели, если не надо), виртуальные мосты (типа виртуальных свитчей) и нашего старого знакомого — iptables (да-да, тот самый файрвол, который всех пугает).

Вот как это всё, блядь, работает на практике:

  1. bridge (стандартная тема, которую все используют):

    • Докер создаёт у себя в системе виртуальный свитч, назовём его docker0. Выглядит как сетевая карта, но только в программе.
    • Каждый новый контейнер цепляется к этому свитчу своей виртуальной сетево́й парой — это как две виртуальные сетевухи, соединённые проводом, одна торчит в контейнере, другая — в свитче.
    • Контейнеру выдают айпишник из подсети этого моста, например, 172.17.0.2.
    • Как контейнеры друг друга находят: Всё просто — они в одной локальной сети! Мост работает на уровне L2, так что контейнер 172.17.0.2 спокойно шлёт пакеты на 172.17.0.3, будто они в одной квартире.
    • А как контейнер в интернет выходит? Вот тут вступает iptables. Докер настраивает правило, которое называется MASQUERADE (маскарад). Грубо говоря, когда твой контейнер лезет в интернет за видосиками с котиками, хост подменяет обратный адрес контейнера на свой собственный внешний IP. А когда ответ приходит — хост его умно перенаправляет обратно в контейнер. Хитрая жопа, но работает.
  2. host: Тут всё проще некуда. Контейнер просто живёт в сетевом пространстве хоста. Никаких виртуальных мостов, никакого NAT. Контейнеру доступны ВСЕ сетевые интерфейсы хоста, как будто он не в контейнере, а просто процесс. Удобно для производительности, но доверия ебать ноль с точки зрения изоляции.

  3. overlay: Это уже для больших игрушек, типа Docker Swarm или Kubernetes, когда контейнеры раскиданы по разным физическим серверам.

    • Создаётся общая виртуальная сеть поверх всех хостов.
    • Трафик между серверами заворачивается в специальную VXLAN-инкапсуляцию — как письмо в конверт.
    • И самое вкусное — встроенный DNS. Контейнеры могут находить друг друга просто по имени сервиса, а не по айпишникам. Красота!

Давай на живом примере, а то одни слова:

# Создаём свою сетку, чтобы не париться с дефолтной
docker network create --driver bridge my-app-net

# Запускаем в ней контейнер с nginx, назовём его 'web'
docker run -d --name web --network my-app-net nginx

# Теперь залезем внутрь и посмотрим, как он маршруты видит
docker exec web ip route
# Увидишь что-то типа: default via 172.19.0.1 dev eth0 ...
# Это адрес шлюза — по сути, это IP-адрес того самого виртуального моста на хосте.

# А теперь главное — посмотрим, какую черную магию докер наворотил в iptables
sudo iptables -t nat -L -n | grep docker

Вот тут ты и увидишь все эти правила для NAT и изоляции, которые докер нагородил. Сам от себя охуеешь, сколько всего там.

Короче, вывод такой: Docker — он, конечно, молодец, всю эту ебучую рутину с сетями берёт на себя. Но если что-то перестаёт работать, а оно всегда перестаёт в самый неподходящий момент, без понимания, что там под капотом, ты будешь как слепой котёнок. Так что держи эту схему в голове, и проблем будет вполовину меньше.