Что вы узнаете из этого руководства
Сеть Docker - фундамент, на котором держится взаимодействие контейнеров. Ошибка в выборе драйвера или настройке маршрутизации приводит к недоступности сервисов, утечкам трафика и проблемам с безопасностью. Это руководство дает готовые решения для типовых задач: от связи двух контейнеров на одном хосте до мультихостового кластера в Swarm с шифрованием трафика.
Вы получите пошаговые инструкции с командами, проверенными на Docker версии 26+. Разберем, когда использовать bridge, host, overlay и macvlan, как работает проброс портов через iptables и docker-proxy, как контейнеры находят друг друга по DNS-именам и что делать, если сеть не работает. Материал построен от простого к сложному: начальные разделы помогут новичкам, продвинутые сценарии с macvlan и ручной маршрутизацией закроют запросы опытных администраторов.
Типы сетей Docker: как выбрать подходящий драйвер
Docker предлагает четыре основных сетевых драйвера. Выбор зависит от трех факторов: нужна ли изоляция, требуется ли доступ извне и работают ли контейнеры на разных хостах. Таблица ниже дает мгновенную ориентацию.
| Драйвер | Изоляция | Доступ извне | Мультихост | Производительность | Типовой сценарий |
|---|---|---|---|---|---|
| bridge | Полная (NAT) | Проброс портов | Нет | Средняя | Микросервисы на одном сервере |
| host | Отсутствует | Прямой | Нет | Максимальная | Высоконагруженный веб-сервер |
| overlay | Полная (VXLAN) | Ingress-сеть Swarm | Да | Средняя (с шифрованием ниже) | Кластер Docker Swarm |
| macvlan | Нет (L2-доступ) | Прямой (IP из LAN) | Нет | Высокая | Контейнер как физический узел сети |
IPvlan - облегченная альтернатива macvlan без расхода MAC-адресов. Подходит, когда сетевой коммутатор ограничивает количество MAC на порту.
Bridge-сеть: стандартная изоляция и связь на одном хосте
Bridge-сеть - драйвер по умолчанию. Docker создает виртуальный коммутатор docker0, к которому подключаются контейнеры через пары veth-интерфейсов. Каждый контейнер получает IP из подсети 172.17.0.0/16 и общается с внешним миром через NAT на iptables.
Дефолтная bridge-сеть имеет критическое ограничение: отсутствует автоматический DNS-резолвинг. Контейнеры видят друг друга только по IP-адресам. При перезапуске IP меняются, что ломает связность. Кастомные bridge-сети лишены этого недостатка - встроенный DNS-сервер на 127.0.0.11 разрешает имена контейнеров автоматически.
Создавайте кастомную bridge-сеть всегда, когда на одном хосте работают больше одного контейнера, которым нужна связь друг с другом. Это дает DNS-резолвинг, изоляцию от других сетей и управление IP-адресацией.
Host-сеть: максимальная производительность без изоляции
Контейнер в host-сети использует сетевой стек хоста напрямую. Нет трансляции адресов, нет виртуальных интерфейсов, нет docker-proxy. Сетевая производительность идентична процессам на хосте. Тесты iperf3 показывают разницу с bridge до 15-20% на высоких скоростях (10 Гбит/с и выше).
Плата за скорость - полное отсутствие сетевой изоляции. Контейнер видит все интерфейсы хоста и может конфликтовать портами с другими процессами. Два контейнера в host-сети не могут слушать один и тот же порт. Этот драйвер оправдан для высоконагруженных сетевых приложений: reverse-прокси, серверов потокового видео, систем мониторинга трафика.
Overlay-сеть: мультихостовое взаимодействие в Swarm
Overlay-сеть решает задачу связи контейнеров на разных физических хостах. Архитектура построена на VXLAN-туннелях: каждый узел Swarm получает виртуальный интерфейс, через который трафик инкапсулируется в UDP-пакеты и передается между демонами Docker. Control plane управляется менеджерами Swarm, data plane - прямое соединение между узлами.
Docker Swarm автоматически управляет overlay-сетями: распределяет IP-адреса, строит mesh-маршрутизацию и обеспечивает отказоустойчивость. При выходе узла из строя трафик перенаправляется на работающие реплики сервиса. Шифрование IPSec включается опционально флагом --opt encrypted и снижает пропускную способность на 10-20%.
Overlay избыточен, если все контейнеры работают на одном хосте. Для одиночного сервера достаточно bridge. Альтернативные решения - Weave, Calico - нужны при интеграции с Kubernetes или требованиях к сетевой политике за пределами возможностей Swarm.
Macvlan-сеть: контейнер как физическое устройство в сети
Macvlan назначает контейнеру собственный MAC-адрес и IP из физической сети. С точки зрения коммутатора и DHCP-сервера контейнер выглядит как отдельное физическое устройство. Это решает задачи устаревших приложений, требующих L2-связности, широковещательного трафика или прямой видимости в корпоративной сети.
Два режима работы: bridge (контейнеры на одном хосте видят друг друга через физический коммутатор) и 802.1q trunk (каждый VLAN - отдельный подынтерфейс). Ключевое ограничение macvlan: контейнер не может общаться с хостом напрямую. Это ограничение ядра Linux, обход - создание дополнительного macvlan-интерфейса на хосте.
Практикум: связываем контейнеры на одном хосте
Типовая задача: веб-сервер Nginx должен проксировать запросы к бэкенду на Node.js. Оба контейнера на одном хосте. Решение - кастомная bridge-сеть с DNS-резолвингом.
Создание кастомной bridge-сети и подключение контейнеров
Создаем сеть с явным указанием подсети и шлюза. Это предотвращает конфликты с другими сетями и дает контроль над адресацией.
docker network create \
--driver bridge \
--subnet=10.10.0.0/24 \
--gateway=10.10.0.1 \
--ip-range=10.10.0.128/25 \
app-network
Параметр --ip-range ограничивает пул автоматически назначаемых адресов. Это оставляет первую половину подсети для статического назначения. Запускаем контейнеры:
docker run -d --name backend --network app-network --ip 10.10.0.10 node:18-alpine
docker run -d --name frontend --network app-network --ip 10.10.0.20 nginx:alpine
Проверяем назначенные адреса:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' backend
# 10.10.0.10
DNS-резолвинг в Docker: как контейнеры находят друг друга по имени
В кастомной сети каждый контейнер получает DNS-запись с именем, равным имени контейнера. Встроенный DNS-сервер слушает 127.0.0.11:53 внутри контейнера. Проверяем:
docker exec frontend ping backend
# PING backend (10.10.0.10): 56 data bytes
# 64 bytes from 10.10.0.10: seq=0 ttl=64 time=0.089 ms
Network alias дает дополнительные имена для одного контейнера. Полезно при сине-зеленых деплоях или миграции сервисов:
docker run -d --name backend-v2 --network app-network --network-alias api,backend-alias node:18-alpine
Теперь контейнер backend-v2 доступен по именам api и backend-alias. DNS-записи обновляются автоматически при перезапуске контейнера.
В дефолтной bridge-сети DNS-резолвинг не работает. Команда ping backend вернет ошибку разрешения имени. Это частая причина, по которой новички не могут связать контейнеры - они используют сеть по умолчанию.
Доступ к контейнерам извне: проброс портов и host-сеть
Контейнер в bridge-сети изолирован за NAT. Чтобы сервис был доступен с хоста или из внешней сети, нужен проброс портов или переход на host-сеть.
Как работает проброс портов: docker-proxy и iptables
При запуске контейнера с флагом -p 8080:80 Docker создает два механизма трансляции: правило iptables DNAT и процесс docker-proxy. Схема прохождения пакета:
- Внешний запрос приходит на порт 8080 хоста.
- iptables перехватывает пакет и меняет адрес назначения на IP контейнера и порт 80.
- docker-proxy (userland) слушает 0.0.0.0:8080 и проксирует трафик в контейнер.
Двойной механизм - историческая причина. Docker-proxy работал всегда, iptables добавили позже. На современных ядрах (5.x+) docker-proxy можно отключить для повышения производительности:
# В /etc/docker/daemon.json
{
"userland-proxy": false
}
После перезапуска Docker трафик пойдет только через iptables (hairpin NAT). Это снижает задержку на 0.1-0.3 мс и убирает лишний процесс. Обратная сторона: hairpin NAT не работает на некоторых старых ядрах, и контейнер не сможет обратиться к самому себе через публичный IP хоста.
Синтаксис проброса:
# Проброс на всех интерфейсах
-p 8080:80
# Проброс только на localhost
-p 127.0.0.1:8080:80
# Проброс диапазона портов
-p 8080-8090:80-90
# Явное указание протокола
-p 8080:80/tcp
-p 53:53/udp
Host-сеть для максимальной производительности: когда и как
Запуск контейнера в host-сети отключает сетевую изоляцию полностью:
docker run --rm --network host alpine ip addr show
# Вывод покажет все интерфейсы хоста: eth0, lo, docker0 и другие
Контейнер слушает порт напрямую на интерфейсе хоста. Никакого проброса, никакой трансляции. Это критично для UDP-сервисов (DNS, игровые серверы, VoIP), где NAT может терять сессии. Высоконагруженный Nginx на 50 000 одновременных соединений в host-сети показывает пропускную способность на 12-18% выше, чем в bridge с пробросом.
Главное предупреждение: нельзя запустить два контейнера в host-сети, слушающих один порт. Docker не выдаст ошибку - второй контейнер просто не сможет занять порт и упадет. Планируйте порты заранее.
Мультихостовые сети: overlay в Docker Swarm
Когда контейнеры разнесены по разным серверам, bridge и host не работают. Overlay-сеть в Docker Swarm решает эту задачу.
Создание overlay-сети и деплой сервисов
Инициализируем Swarm на первом узле и добавляем остальные:
# На manager-узле
docker swarm init --advertise-addr 192.168.1.10
# На worker-узлах выполняем команду из вывода init
docker swarm join --token SWMTKN-... 192.168.1.10:2377
Создаем overlay-сеть с флагом --attachable. Без него к сети можно подключать только сервисы Swarm, но не обычные контейнеры:
docker network create \
--driver overlay \
--attachable \
--subnet=10.20.0.0/24 \
cluster-network
Деплоим сервис с несколькими репликами:
docker service create \
--name web \
--network cluster-network \
--replicas 3 \
--publish published=8080,target=80 \
nginx:alpine
Swarm автоматически распределяет реплики по узлам. Ingress-сеть маршрутизирует внешние запросы на любой узел кластера, даже если на нем нет активной реплики сервиса. Это mesh-маршрутизация: порт 8080 слушают все узлы Swarm и проксируют трафик к нужному контейнеру.
Проверяем связь между контейнерами на разных узлах:
docker exec -it $(docker ps -q --filter name=web.1) ping web.2
# Имя сервиса разрешается в IP конкретной реплики через встроенный DNS
Шифрование трафика в overlay-сетях
По умолчанию трафик VXLAN между узлами не шифруется. Для production-сред с чувствительными данными включайте IPSec:
docker network create \
--driver overlay \
--attachable \
--opt encrypted \
secure-overlay
Шифрование добавляет накладные расходы на установку туннелей и шифрование пакетов. Тесты показывают падение пропускной способности на 10-20% и рост задержки на 0.2-0.5 мс. Для внутреннего трафика в доверенной сети шифрование часто избыточно.
Продвинутые сценарии: macvlan и ручная маршрутизация
Стандартные драйверы покрывают 90% задач. Оставшиеся 10% требуют macvlan или ручной настройки маршрутов между изолированными сетями.
Macvlan: прямой выход контейнера в локальную сеть
Создаем macvlan-сеть, привязанную к физическому интерфейсу eth0. Контейнеры получат IP из той же подсети, что и хост:
docker network create \
--driver macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
--ip-range=192.168.1.240/28 \
-o parent=eth0 \
macvlan-net
Запускаем контейнер с явным IP из диапазона, не занятого DHCP-сервером:
docker run -d --name legacy-app --network macvlan-net --ip 192.168.1.250 nginx:alpine
Контейнер доступен из локальной сети по IP 192.168.1.250. DHCP-сервер сети может выдать ему адрес, если не указывать --ip. Ограничение: с хоста этот контейнер недоступен. Пинг с хоста на 192.168.1.250 не пройдет. Обходной путь - создать macvlan-подинтерфейс на хосте:
ip link add macvlan0 link eth0 type macvlan mode bridge
ip addr add 192.168.1.251/24 dev macvlan0
ip link set macvlan0 up
Теперь хост видит контейнер через этот интерфейс.
Ручная маршрутизация между bridge-сетями
Две bridge-сети изолированы друг от друга. Контейнеры в сети frontend не видят контейнеры в сети backend. Решение - контейнер-маршрутизатор с интерфейсами в обеих сетях и включенным IP forwarding.
# Создаем две изолированные сети
docker network create --subnet=10.30.0.0/24 frontend
docker network create --subnet=10.40.0.0/24 backend
# Запускаем маршрутизатор
docker run -d --name router \
--network frontend --ip 10.30.0.254 \
--cap-add NET_ADMIN \
alpine \
sh -c "sysctl -w net.ipv4.ip_forward=1 && tail -f /dev/null"
# Подключаем второй интерфейс
docker network connect --ip 10.40.0.254 backend router
# Добавляем статические маршруты на контейнерах
docker exec backend-container ip route add 10.30.0.0/24 via 10.40.0.254
docker exec frontend-container ip route add 10.40.0.0/24 via 10.30.0.254
Альтернатива - docker network connect для подключения одного контейнера к нескольким сетям. Это проще, но нарушает изоляцию: контейнер становится мостом между сетями.
Сравнение производительности драйверов через iperf3 на сервере с 10 Гбит/с интерфейсом:
| Драйвер | Пропускная способность | Задержка | Потери |
|---|---|---|---|
| host | 9.41 Гбит/с | 0.05 мс | 0% |
| bridge (userland-proxy=true) | 8.12 Гбит/с | 0.18 мс | 0% |
| bridge (userland-proxy=false) | 8.95 Гбит/с | 0.09 мс | 0% |
| macvlan | 9.38 Гбит/с | 0.06 мс | 0% |
| overlay (без шифрования) | 7.84 Гбит/с | 0.32 мс | 0% |
| overlay (с IPSec) | 6.51 Гбит/с | 0.48 мс | 0% |
Цифры показывают: host и macvlan практически не уступают нативной производительности. Bridge с отключенным docker-proxy приближается к ним. Overlay теряет 15-30% из-за инкапсуляции VXLAN.
Диагностика и решение типовых проблем с сетью Docker
Сеть не работает - самая частая жалоба после настройки Docker. Системный подход к диагностике экономит часы.
Проверка сетевой связности: инструменты и подходы
Алгоритм диагностики - четыре шага от нижнего уровня к верхнему:
- IP-адресация. Проверьте, что контейнер получил IP:
docker inspect -f '{{.NetworkSettings.Networks.ИМЯ_СЕТИ.IPAddress}}' ИМЯ_КОНТЕЙНЕРА. Отсутствие IP означает, что контейнер не подключен к сети. - Маршруты. Внутри контейнера выполните
ip route. Таблица должна содержать маршрут по умолчанию через шлюз сети. - DNS. Проверьте разрешение имен:
docker exec ИМЯ nslookup tasks.ИМЯ_СЕРВИСАилиping ИМЯ_КОНТЕЙНЕРА. Ошибка разрешения указывает на использование дефолтной сети или проблемы со встроенным DNS. - iptables. На хосте выполните
iptables -L -n -t nat | grep ПОРТ. Отсутствие правил DNAT для проброшенного порта означает, что docker-proxy не работает или порт занят.
Распространенные ошибки и их исправление
1. Контейнеры не видят друг друга по имени. Симптом: ping по IP работает, по имени - нет. Причина: используется дефолтная bridge-сеть. Решение: создайте кастомную сеть и переподключите контейнеры.
2. Проброс портов не работает. Симптом: сервис недоступен снаружи, хотя контейнер запущен. Причина: конфликт с firewalld или ufw. Решение: проверьте iptables -L DOCKER -n и добавьте правила в файрвол или временно отключите его для теста.
3. Overlay-сеть не соединяет узлы. Симптом: контейнеры на разных хостах не пингуются. Причина: забыт флаг --attachable при создании сети или заблокированы порты 2377/tcp, 7946/tcp+udp, 4789/udp между узлами. Решение: проверьте файрвол и пересоздайте сеть с --attachable.
4. Медленная сеть в bridge. Симптом: задержка выше ожидаемой. Причина: включен docker-proxy. Решение: отключите userland-proxy в daemon.json и перезапустите Docker.
5. Контейнер в macvlan не видит хост. Симптом: пинг с контейнера на IP хоста не проходит. Причина: ограничение ядра Linux, macvlan не маршрутизирует трафик между родительским интерфейсом и виртуальными. Решение: создайте macvlan-подинтерфейс на хосте, как показано в разделе выше.
Заключение: проектирование надежной сети для контейнеров
Выбор сетевого драйвера Docker сводится к трем вопросам. Контейнеры на одном хосте? Берите кастомную bridge-сеть - она дает DNS-резолвинг и изоляцию. Нужна максимальная производительность без изоляции? Используйте host. Контейнеры разнесены по серверам? Overlay в Docker Swarm с шифрованием для чувствительных данных. Особые требования к L2-связности? Macvlan решает задачу прямого подключения к физической сети.
Чек-лист для production-развертывания:
- Создавайте кастомные сети, не полагайтесь на дефолтную bridge.
- Отключайте docker-proxy для высоконагруженных сервисов.
- Планируйте IP-адресацию через --subnet и --ip-range, избегайте конфликтов.
- Включайте шифрование overlay-сетей только при передаче данных через недоверенные каналы.
- Документируйте сетевую топологию: какие сети, какие порты проброшены, какие зависимости между сервисами.
Детальный разбор продвинутых сценариев - статические IP в Compose, прямая маршрутизация с хоста и профессиональная диагностика - доступен в руководстве по продвинутой маршрутизации в Docker и Compose. Сравнение драйверов с фокусом на микросервисы и интеграцию с Kubernetes разобрано в полном руководстве по сетевым драйверам Docker 2026. Для развертывания контейнеров в production-среде с гарантированной производительностью сети используйте облачную инфраструктуру Timeweb Cloud с масштабируемыми VDS и поддержкой Kubernetes.