Маршрутизация трафика в Docker: драйверы macvlan, ipvlan и overlay — полное практическое руководство | AdminWiki

Маршрутизация трафика в Docker: драйверы macvlan, ipvlan и overlay — полное практическое руководство

22 июля 2026 11 мин. чтения

Введение: когда стандартного bridge недостаточно

Стандартная bridge-сеть Docker решает базовую задачу: контейнеры на одном хосте видят друг друга, а наружу смотрят через NAT. Хост пробрасывает порты, трансляция адресов скрывает внутреннюю кухню. Это удобно для разработки и простых стендов, но в production-сценариях модель упирается в потолок.

Три типичные ситуации, где bridge перестаёт справляться:

  1. Контейнер должен выглядеть как полноценный узел физической сети - со своим IP, MAC-адресом, без проброса портов. Например, когда вы переносите legacy-сервис в контейнер, а остальная инфраструктура должна обращаться к нему напрямую.
  2. Среда накладывает ограничения: Wi-Fi-подключение хоста, политика безопасности порта на коммутаторе, облачный провайдер с лимитом MAC-адресов. Bridge здесь не помощник, нужен другой механизм.
  3. Контейнеры разнесены по разным физическим хостам и должны общаться в общей изолированной сети, как будто они на одной машине. Микросервисная архитектура в чистом виде.

Под эти задачи Docker предлагает три специализированных драйвера: macvlan, ipvlan и overlay. Они закрывают сценарии прямой интеграции в физическую сеть, обхода инфраструктурных ограничений и построения мультихостовых сетей. Ниже - детальный разбор каждого с пошаговыми инструкциями, которые вы сможете применить сразу.

Если вы проектируете сетевую инфраструктуру для production-кластера, рекомендую также изучить руководство по выбору сетевых драйверов под высокие нагрузки - там разобрана интеграция с Kubernetes, CNI-плагинами и оптимизация для 50k+ подключений.

Обзор сетевых драйверов Docker: macvlan, ipvlan и overlay

Каждый из трёх драйверов решает свой класс задач. Принципиальная разница - в способе взаимодействия контейнера с сетевым стеком хоста и внешней инфраструктурой. Разберём механику, сильные стороны и ограничения.

macvlan: контейнер как физическое устройство в вашей сети

Драйвер macvlan назначает контейнеру собственный MAC-адрес и IP из подсети родительского интерфейса хоста. С точки зрения коммутатора и других устройств в сети контейнер выглядит как отдельная физическая машина. Никакого NAT, никакого проброса портов - трафик идёт напрямую.

macvlan работает в трёх режимах:

  • Bridge - контейнеры в одной macvlan-сети видят друг друга через родительский интерфейс, трафик между ними коммутируется на уровне ядра.
  • Private - полная изоляция: контейнеры не могут общаться друг с другом, только с внешней сетью. Подходит для сценариев с жёсткими требованиями безопасности.
  • Passthru - прямой доступ к физическому интерфейсу, используется редко, в основном для случаев, когда нужно отдать контейнеру эксклюзивный контроль над сетевым адаптером.

Типичный пример: запуск веб-сервера в контейнере, который получает IP 192.168.1.100 из локальной сети офиса. Любой сотрудник открывает этот адрес в браузере без настройки port forwarding на хосте. Контейнер становится полноправным участником сети.

Ключевое ограничение: macvlan не работает, если хост подключен через Wi-Fi. Большинство точек доступа и драйверов беспроводных сетей блокируют фреймы с чужими MAC-адресами. Подробнее об этой проблеме и путях обхода - в разделе про ipvlan.

ipvlan: решение для сред с ограничениями по MAC-адресам

ipvlan использует общий MAC-адрес родительского интерфейса для всех контейнеров. Каждый контейнер получает уникальный IP, но на уровне L2 все фреймы идут с одним и тем же MAC. Это решает проблему сред, где нельзя плодить MAC-адреса: Wi-Fi-сети, облачные платформы с политиками безопасности портов, коммутаторы с ограничением числа MAC на порт.

Два режима работы:

  • L2 (бриджевый) - контейнеры находятся в одной подсети с хостом, работают как bridge. Хост изолирован от контейнеров на уровне ядра - напрямую пинг не пройдёт. Требуется создание дочернего ipvlan-интерфейса на хосте для связи.
  • L3 (маршрутизируемый) - контейнеры получают отдельную подсеть, хост выступает маршрутизатором между ней и внешней сетью. На внешних устройствах нужно прописать статический маршрут к подсети контейнеров через IP хоста.

Преимущество ipvlan: работает там, где macvlan блокируется. Недостаток: в L2-режиме связь хост-контейнер требует дополнительной настройки, в L3-режиме - изменения маршрутизации на внешнем оборудовании. Выбор между macvlan и ipvlan сводится к одному вопросу: разрешено ли в вашей сети появление дополнительных MAC-адресов. Если нет - ipvlan.

Практическое сравнение двух драйверов с готовыми конфигурациями docker-compose и таблицей выбора под конкретные сценарии смотрите в статье Macvlan и IPvlan в Docker: интеграция в корпоративную сеть.

overlay: мультихостовые сети для Docker Swarm

Overlay-драйвер создаёт виртуальную сеть поверх физической инфраструктуры с помощью VXLAN-туннелей. Контейнеры на разных хостах общаются так, будто подключены к одному коммутатору. Трафик инкапсулируется в UDP-пакеты и передаётся между узлами кластера.

Обязательное условие: Docker Swarm. Overlay-сеть разворачивается поверх swarm-кластера, который управляет обнаружением узлов и распределением трафика. Без swarm overlay не работает.

Ключевые возможности:

  • Прозрачная связность контейнеров на разных хостах в рамках одной подсети.
  • Встроенное шифрование трафика (опция --opt encrypted), использующее IPsec. Требует установки пакета ipsec-tools на всех узлах.
  • Поддержка как сервисов Swarm, так и обычных контейнеров (с флагом --attachable).

Типичный сценарий: микросервисное приложение, где frontend, backend и база данных разнесены по трём хостам, но должны общаться по внутренним IP в общей сети 10.0.0.0/24. Overlay даёт эту связность без ручной настройки VPN или сложной маршрутизации.

Детальный разбор архитектуры bridge, host и overlay-драйверов, включая таблицы маршрутизации и диагностику проблем доступности, - в руководстве по сетевой архитектуре Docker.

Пошаговая настройка macvlan: интеграция контейнера в физическую сеть

Переходим к практике. Задача: контейнер должен получить IP из физической сети 192.168.1.0/24 и быть доступным для всех устройств в этой сети без проброса портов.

Предварительные требования:

  • Определите родительский интерфейс хоста: ip link show - обычно это eth0, enp0s3 или ens18.
  • Узнайте подсеть и шлюз: ip route | grep default.
  • Выберите IP для контейнера вне DHCP-пула, чтобы избежать конфликтов.

Создаём macvlan-сеть:

docker network create \
  -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  --ip-range=192.168.1.224/27 \
  -o parent=eth0 \
  macnet

Флаг --ip-range ограничивает пул адресов, которые Docker будет назначать автоматически. Это страховка от пересечения с DHCP-сервером. Если планируете назначать IP только вручную, диапазон можно не указывать.

Назначение статического IP-адреса контейнеру

Запускаем контейнер с явным указанием IP:

docker run -d \
  --name web01 \
  --network macnet \
  --ip=192.168.1.100 \
  nginx:alpine

IP должен быть из подсети macvlan-сети и не входить в DHCP-пул вашего роутера. Проверяем: с любой машины в сети выполняем ping 192.168.1.100 - ответ идёт от контейнера.

Для docker-compose конфигурация выглядит так:

services:
  web:
    image: nginx:alpine
    networks:
      macnet:
        ipv4_address: 192.168.1.100

networks:
  macnet:
    driver: macvlan
    driver_opts:
      parent: eth0
    ipam:
      config:
        - subnet: 192.168.1.0/24
          gateway: 192.168.1.1

Важный нюанс: статический IP через --ip работает только для пользовательских сетей. Встроенная bridge-сеть этого не поддерживает.

Решение проблемы связи между хостом и контейнерами macvlan

После настройки macvlan вы обнаружите: контейнеры пингуют внешний мир, внешние устройства пингуют контейнеры, но хост не может достучаться до собственных контейнеров. Это не баг, а особенность архитектуры Linux: macvlan изолирует трафик между родительским интерфейсом и дочерними виртуальными интерфейсами на уровне ядра.

Решение: создать на хосте дочерний macvlan-интерфейс с IP из той же подсети. Через него хост будет общаться с контейнерами:

ip link add macvlan0 link eth0 type macvlan mode bridge
ip addr add 192.168.1.200/24 dev macvlan0
ip link set macvlan0 up

После этого ping 192.168.1.100 с хоста работает. Интерфейс macvlan0 существует до перезагрузки. Для постоянной конфигурации добавьте правила в systemd-networkd или /etc/network/interfaces в зависимости от вашего дистрибутива.

Настройка ipvlan: когда macvlan недоступен

Сценарий: хост подключен через Wi-Fi (интерфейс wlan0), macvlan не поднимается - точка доступа отбрасывает фреймы с чужими MAC. Или облачный провайдер разрешает только один MAC на виртуальную машину. Переходим на ipvlan.

Создаём ipvlan-сеть в режиме L2:

docker network create \
  -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=wlan0 \
  -o ipvlan_mode=l2 \
  ipvnet

Запускаем контейнер:

docker run -d \
  --name app01 \
  --network ipvnet \
  --ip=192.168.1.101 \
  nginx:alpine

Контейнер доступен из внешней сети, но хост его не видит - та же проблема изоляции, что и с macvlan. Решается аналогично: создаём ipvlan-интерфейс на хосте:

ip link add ipvlan0 link wlan0 type ipvlan mode l2
ip addr add 192.168.1.201/24 dev ipvlan0
ip link set ipvlan0 up

Режим L2 vs L3 в ipvlan: выбор под задачу

L2-режим подходит, когда контейнеры должны сидеть в одной подсети с хостом и внешними устройствами. Минимум изменений в инфраструктуре, но хост изолирован (лечится дочерним интерфейсом, как показано выше).

L3-режим нужен, когда вы хотите вынести контейнеры в отдельную подсеть и управлять маршрутизацией на уровне хоста. Контейнеры получают адреса из диапазона, отличного от подсети хоста. Хост автоматически становится маршрутизатором между этой подсетью и внешней сетью.

Создание L3-сети:

docker network create \
  -d ipvlan \
  --subnet=10.0.1.0/24 \
  -o parent=eth0 \
  -o ipvlan_mode=l3 \
  ipvnet-l3

Контейнеры получат адреса из 10.0.1.0/24. Чтобы внешние устройства могли до них достучаться, на роутере или других хостах нужно прописать маршрут: ip route add 10.0.1.0/24 via 192.168.1.10, где 192.168.1.10 - IP хоста Docker. L3-режим даёт чистую изоляцию и гибкость, но требует прав на сетевом оборудовании.

Overlay-сети в Docker Swarm: связь контейнеров на разных хостах

Задача: три хоста, на каждом - часть микросервисного приложения. Нужна общая внутренняя сеть, чтобы сервисы видели друг друга по IP, независимо от того, на каком узле они запущены.

Требования к инфраструктуре:

  • Открытые порты между хостами: TCP 2377 (управление swarm), TCP/UDP 7946 (обнаружение узлов), UDP 4789 (VXLAN-трафик).
  • Docker Engine на всех узлах одной версии (рекомендуется 24+).

Инициализируем swarm на первом хосте:

docker swarm init --advertise-addr 192.168.1.10

Команда выведет токен для присоединения воркеров. На остальных хостах выполняем:

docker swarm join --token SWMTKN-... 192.168.1.10:2377

Создаём overlay-сеть с возможностью подключения обычных контейнеров:

docker network create \
  -d overlay \
  --attachable \
  --subnet=10.0.0.0/24 \
  my-overlay

Флаг --attachable разрешает подключать к сети не только сервисы Swarm, но и контейнеры, запущенные через docker run. Без него сеть доступна только для docker service create.

Запускаем контейнеры на разных хостах:

# Хост 1
docker run -d --name backend --network my-overlay --ip=10.0.0.10 nginx:alpine

# Хост 2
docker run -d --name frontend --network my-overlay --ip=10.0.0.20 nginx:alpine

Проверяем связность: на хосте 2 выполняем docker exec frontend ping 10.0.0.10. Пакеты идут через VXLAN-туннель, контейнеры видят друг друга как в одной локальной сети.

Шифрование трафика в overlay-сетях

По умолчанию VXLAN-трафик между хостами идёт открытым текстом. Для защиты данных создаём сеть с шифрованием:

docker network create \
  -d overlay \
  --attachable \
  --opt encrypted \
  --subnet=10.0.1.0/24 \
  secure-overlay

Обязательное условие: на всех узлах swarm должен быть установлен пакет ipsec-tools (или strongswan для некоторых дистрибутивов). Docker использует IPsec ESP для шифрования полезной нагрузки VXLAN-пакетов. Проверить, что трафик действительно шифруется, можно через tcpdump: в дампе не должно быть читаемой полезной нагрузки.

Предупреждение: шифрование создаёт дополнительную нагрузку на CPU. Для внутренних сетей в доверенном дата-центре его часто отключают в пользу производительности. В распределённых системах, где трафик идёт через публичные каналы, шифрование обязательно.

Сравнение драйверов и критерии выбора

Выбор драйвера сводится к трём вопросам. Ответьте на них последовательно - получите однозначную рекомендацию.

Вопрос 1: контейнер должен быть доступен из физической сети без NAT и проброса портов?

Если да - macvlan или ipvlan. Если нет и достаточно bridge с пробросом портов - остаётесь на стандартном драйвере.

Вопрос 2: среда разрешает множественные MAC-адреса на порту?

Если да - macvlan. Это производительнее и проще в настройке. Если нет (Wi-Fi, облачные провайдеры, строгие политики коммутатора) - ipvlan.

Вопрос 3: контейнеры разнесены по разным хостам и должны быть в общей изолированной сети?

Если да - overlay. Требует Docker Swarm, но даёт прозрачную мультихостовую связность.

Критерий macvlan ipvlan overlay
Связь хост-контейнер по умолчанию Нет Нет Да
Работа через Wi-Fi Нет Да Да (поверх сети хоста)
Мультихостовая сеть Нет Нет Да
Изоляция от хоста Полная (L2) Полная (L2) Частичная (сеть виртуальная)
Производительность Высокая (почти нативная) Высокая Средняя (накладные расходы VXLAN)
Требования к инфраструктуре Поддержка нескольких MAC на порту Нет особых требований Swarm, открытые порты 2377/7946/4789

Драйверы можно комбинировать. Например, на хосте одновременно работают macvlan-сеть для сервисов, требующих прямого доступа из физической сети, и overlay-сеть для внутреннего взаимодействия микросервисов в swarm. Docker допускает подключение контейнера к нескольким сетям одновременно.

Типичные проблемы и их решение

За годы работы с Docker-сетями я собрал список проблем, с которыми сталкиваются администраторы. Вот решения, которые работают.

Проблема 1: macvlan не работает на Wi-Fi. Контейнеры не получают IP или не видят сеть.

Причина: драйвер беспроводного адаптера или точка доступа блокирует фреймы с MAC-адресами, отличными от MAC хоста. Решение: использовать ipvlan, который работает с одним MAC. Команды для перехода - в разделе про ipvlan выше.

Проблема 2: хост не пингует контейнеры в macvlan/ipvlan. Внешние устройства контейнеры видят, хост - нет.

Причина: изоляция на уровне ядра Linux между родительским и дочерними интерфейсами. Решение: создать на хосте дочерний macvlan/ipvlan-интерфейс с IP из той же подсети. Команды приведены в соответствующих разделах.

Проблема 3: контейнеры в overlay не видят друг друга. Пинг не проходит, сервисы не соединяются.

Причины и решения:

  • Закрыты порты 7946 (TCP/UDP) и 4789 (UDP) на фаерволе между хостами - открыть.
  • Разные версии Docker на узлах swarm - привести к одной мажорной версии.
  • Неправильно указан --advertise-addr при инициализации swarm - переинициализировать с корректным IP.

Проблема 4: конфликт IP-адресов в macvlan/ipvlan. Контейнер получает адрес, уже занятый другим устройством в сети.

Причина: DHCP-сервер не знает о статических назначениях Docker. Решение: использовать --ip-range при создании сети, чтобы ограничить пул Docker вне DHCP-диапазона. Либо назначать IP вручную через --ip, выбирая адреса из зарезервированного диапазона, исключённого из DHCP.

Для углублённого изучения безопасности и оптимизации контейнерных сред рекомендую практический гайд по продвинутому Docker - там разобраны сканирование CVE, отказ от root-привилегий и тонкая настройка cgroups для production-нагрузок.

Если вы разворачиваете контейнеры в облаке, обратите внимание на Timeweb Cloud - облачную инфраструктуру с VDS, управляемыми базами данных и Kubernetes. Провайдер не накладывает ограничений на количество MAC-адресов, что упрощает работу с macvlan.

Поделиться:
Сохранить гайд? В закладки браузера