Сеть в контейнерах: путь пакета от процесса до сети
В Linux-контейнере сетевой пакет не телепортируется наружу: он проходит через сетевое пространство имён, виртуальную пару интерфейсов и мост Docker, а иногда ещё и через NAT. Разбираем маршрут на примере Docker Engine и показываем, где искать сбой.

Когда процесс в Linux-контейнере обращается к внешнему серверу, пакет обычно проходит через сетевое пространство имён контейнера, виртуальный интерфейс, мост на хосте и правила маршрутизации или NAT. При входящем соединении опубликованный порт запускает обратную цепочку. Ниже — путь пакета в Docker Engine на Linux с драйвером bridge: это не схема для Docker Desktop на macOS или Windows и не универсальное описание Kubernetes CNI.
Сначала — изоляция, а не отдельный компьютер
Контейнер использует сетевое пространство имён Linux — отдельный набор сетевых интерфейсов, маршрутов и сетевых настроек. У него есть собственный интерфейс, обычно называемый eth0, и маршрут по умолчанию. Но это не обязательно отдельная физическая сеть и не виртуальная машина со своей операционной системой: сетевую передачу обеспечивает ядро хоста.
При подключении к bridge-сети Docker создаёт пару виртуальных Ethernet-интерфейсов. Один конец находится в пространстве имён контейнера, второй — на хосте. Это похоже на виртуальный кабель: кадр, отправленный через один конец, появляется на другом.
Контейнерная сеть — это не один «виртуальный роутер». Это цепочка из интерфейсов, таблиц маршрутизации и правил фильтрации; пакет теряется там, где перестаёт совпадать с ожидаемым маршрутом или правилом.
Сетевое пространство имён1 — механизм Linux, который позволяет процессам видеть собственный набор сетевых интерфейсов и маршрутов.
Исходящий пакет: из контейнера в интернет
- Приложение открывает соединение. Ядро контейнера выбирает исходящий интерфейс по таблице маршрутизации. Для адреса вне локальной подсети это обычно
eth0и шлюз — адрес Docker-моста. Проверка: внутри контейнера командаip routeпоказывает маршрут по умолчанию. - Пакет покидает пространство имён. Он проходит через конец виртуальной пары на хосте. Проверка: на хосте виден соответствующий виртуальный интерфейс, а на интерфейсе контейнера можно увидеть трафик через
tcpdump, если утилита доступна и хватает прав. - Мост доставляет пакет дальше. Если адресат находится в той же bridge-сети, мост пересылает трафик между подключёнными портами. Для внешнего адреса хост маршрутизирует пакет через свой сетевой интерфейс.
- При необходимости применяется SNAT. Чтобы внешний сервер мог ответить на частный адрес контейнера, Docker обычно настраивает преобразование исходного адреса для исходящего трафика. На стороне внешней сети соединение выглядит как пришедшее от адреса хоста. Проверка: сопоставьте захват пакетов на интерфейсе контейнера и внешнем интерфейсе хоста.
Точный набор правил зависит от конфигурации Docker, ядра и используемой реализации фильтрации. Встречаются iptables и nftables; Docker может управлять правилами через совместимый слой. Поэтому поиск только в одной таблице или утилите не всегда показывает всю картину. Отключение управления правилами Docker способно сломать маршрутизацию и публикацию портов, если замену не настроили отдельно.
Входящий пакет: что меняет публикация порта
Внутренний порт контейнера сам по себе не становится доступен снаружи. Публикация порта задаёт правило: соединение, пришедшее на выбранный адрес и порт хоста, нужно направить на адрес контейнера и его порт. В типичном варианте Docker применяет DNAT — меняет адрес назначения, после чего хост маршрутизирует пакет к контейнеру.
Например, если сервис слушает порт 8080 внутри контейнера, настройка публикации связывает его с выбранным портом хоста. Важно различать три вещи: порт, на котором слушает приложение; порт контейнера; опубликованный порт хоста. Если приложение слушает только 127.0.0.1 внутри контейнера, обращение к адресу контейнера может не попасть в него: обычно сервис должен слушать подходящий интерфейс, часто 0.0.0.0.
Публикация не означает, что пакет всегда проходит одним и тем же путём. На результат влияют адрес, на который привязан порт, правила фильтрации, маршруты и настройки прокси. Доступность с самого хоста также может отличаться от доступа из внешней сети. Проверяйте соединение отдельно с хоста, из соседнего контейнера и с внешней машины.
Почему два контейнера могут видеть друг друга не одинаково
В одной пользовательской bridge-сети Docker предоставляет контейнерам сетевую связность и разрешение имён по именам контейнеров или сетевых псевдонимов. Это позволяет обращаться к сервису по имени, не фиксируя его меняющийся IP-адрес. В стандартной bridge-сети поведение с DNS-именами отличается: полагаться на разрешение имён контейнеров там не стоит без отдельной настройки.
Сеть также задаёт границу связности. Контейнеры в разных сетях не становятся доступными друг другу автоматически. Их можно подключить к общей сети или настроить маршрутизацию, но это меняет модель доступа. Не публикуйте порт на хост только ради связи между контейнерами в одной сети: публикация нужна для доступа через адрес хоста, а не для внутреннего обнаружения сервиса.
Что ломается первым
- Приложение слушает не тот адрес. Внутри контейнера порт опубликован, но сервис привязался к loopback. Проверьте адрес прослушивания и логи приложения.
- Порт опубликован не на том адресе или порту. Сверьте конфигурацию контейнера и фактическое подключение с хоста. Публикация на loopback хоста ограничивает доступ по сравнению с привязкой ко всем интерфейсам.
- Контейнеры находятся в разных сетях. Имя сервиса может не разрешаться, а прямой маршрут отсутствовать. Проверьте, подключены ли оба контейнера к одной пользовательской сети.
- Правила фильтрации блокируют трафик. Особенно часто это проявляется после ручного изменения firewall или настройки Docker без управления его правилами. Сверяйте маршрут и правила на хосте, а не только настройки приложения.
- Ожидания от IPv6 не совпадают с конфигурацией. Наличие IPv4-связности не доказывает, что для сети настроен IPv6-маршрут, адресация и фильтрация. Проверяйте протокол отдельно.
Как локализовать обрыв
Идите по маршруту, а не меняйте параметры наугад. Сначала проверьте, слушает ли приложение нужный адрес и порт. Затем — маршрут и DNS внутри контейнера. После этого наблюдайте пакет на интерфейсе контейнера, виртуальной паре и внешнем интерфейсе хоста. Если он исчезает между двумя точками, проверяйте соответствующий участок: мост, маршрутизацию, фильтрацию или преобразование адресов.
Для воспроизводимой диагностики зафиксируйте образ и версию Docker Engine, имя сети, адреса контейнеров, протокол и направление соединения. Запишите, откуда именно выполняется проверка: с хоста и из другого контейнера результаты могут различаться. Не публикуйте дамп трафика без проверки: в нём могут оказаться передаваемые приложением данные.
Что делать дальше
На следующем шаге проверьте один реальный запрос от приложения: убедитесь, что оно слушает ожидаемый адрес, проследите пакет от интерфейса контейнера до интерфейса хоста и сопоставьте результат с правилами Docker. Если используете Docker Desktop, Kubernetes или сеть с собственным CNI, изучите именно их документацию: путь пакета там отличается от описанного bridge-сценария Linux.
1 Network namespace — изолированный сетевой контекст Linux, в котором находятся интерфейсы, маршруты и связанные настройки сети.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: Docker Docs: Bridge network driver, Linux man-pages: network_namespaces(7)
Частые вопросы
Контейнеру нужен опубликованный порт, чтобы выйти в интернет?
Почему контейнеры не находят друг друга по имени?
Почему порт опубликован, но сервис недоступен?
Docker обязательно использует iptables?
Одинаково ли работает эта схема в Docker Desktop?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.