Docker: user defined networks — правильная работа с сетью

И раньше, и сейчас, если не указать дополнительных опций, контейнеры попадают в «дефолтную» виртуальную сеть, параметры которой можно узнать командой:

ip addr show docker0

В Docker 1.10 появилась возможность создавать дополнительные (user-defined) виртуальные сети. Делается это так:

docker network create my-net-1

Посмотрим детали:

docker network inspect my-net-1
[
    {
        "Name": "my-net-1",
        "Id": "05f16acf9b10ee88c992685a0ea33cb6e59fb151c4d5c23bcfea1ce32477f774",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1/16"
                }
            ]
        },
        "Containers": {},
        "Options": {}
    }
]

Диапазон IP-адресов, шлюз и другие параметры можно указать явно (см. docker network create --help).

Внешняя система автоматически подключается к такой сетке через интерфейс, начинающийся на br- и заканчивающийся первыми символами Id:

ifconfig

br-05f16acf9b10 Link encap:Ethernet  HWaddr 02:42:2c:2b:7b:1b
          inet addr:172.18.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          . . .

Теперь можно помещать изолированные группы контейнеров в отдельные сети, добавляя к docker run параметр --net.

Но это ещё не всё! В контейнерах, подключенных к user defined networks, работает внутренний DNS-сервер, благодаря которому они видят друг друга по имени. Больше не нужны ухищрения в виде dnsmasq или SkyDock, и не нужно явно указывать связи (параметр --link переведён в legacy).

Посмотрим на эту красоту в действии. Запустим два тестовых контейнера:

docker run -d --net=my-net-1 --name=c1 busybox sleep 1800
docker run -d --net=my-net-1 --name=c2 busybox sleep 1800

И попингуем один из другого:

docker exec -ti c1 ping c2

PING c2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.109 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.210 ms

Можно использовать полное (fully-qualified) имя, которое складывается из названий контейнера и сети:

docker exec -ti c1 ping c2.my-net-1

Внутренний DNS-сервер слушает локальный адрес 127.0.0.11, который автоматически прописывается в /etc/resolv.conf внутри контейнеров:

docker exec c1 cat /etc/resolv.conf

nameserver 127.0.0.11
options ndots:0
docker exec c1 nslookup c2

Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      c2
Address 1: 172.18.0.3 c2.my-net-1

Удобно.

Вы удивитесь, но можно объединить в виртуальную сеть даже контейнеры, запущенные на разных физических машинах. Такие сети называются «overlay networks», они сложнее в настройке и имеют смысл только для кластеров. Подробности — в документации.

P.S. Не забудьте удалить тестовые контейнеры командой docker rm -f c1 c2.


Все материалы по теме Docker:

Видео:

Статьи:

Устаревшее:

Комментариев: 6

  1. Сергей:

    Добрый день. Моё рабочее окружение вынуждает меня включать все контейнеры в одну сеть «my_network».

    Для каждого проекта, как правило, определяю в docker-compose.yml два сервиса: server (apache+php) и mysql. С server проблем нет, чего не скажешь о mysql. Если выполнить «docker-compose up -d» для более чем одного проекта, то появляются проблемы с доступом к базам данных разных проектов.

    В контейнере server каждого из проектов есть виртуальный хост для доступа к скрипту Adminer, который должен отображать содержимое базы данных проекта. Так вот при переходе по адресам admier.project1.dev и adminer.project2.dev я вижу содержимое одной и той же БД. Соответственно, один из проектов не может достучаться до своей БД.

    До перехода на синтаксис docker-compose v2 проблем не было. Заранее спасибо за помощь.

  2. Andrey:

    Скажите, а как можно сделать так, чтобы присвоить контейнеру ip-адрес в одной сети с хостом, а не с другими контейнерами? Ну типа сбриджевать контейнер с внешней по отношению к хосту сетью.

  3. Алексей:

    @Andrey
    Можно, но непросто. См. http://stackoverflow.com/q/35742807
    Ещё посмотрите на режим --net=host.

  4. Добрый день
    Не подскажете, как можно получить доступ к этому DNS серверу с хоста
    хочется натравить на него dnsmasq

  5. Сергей:

    Доброго времени суток!
    Не подскажете, как убрать из автозагрузки интерфейс docker0?
    И возможно ли, чтобы контейнеру IP адрес не присваивался из диапазона, а был статическим?

  6. Павел:

    Добрый день.
    Скажите пожалуйста.
    А можно ли в docker создать изолированную виртуальную сеть
    между группой контейнеров, но так, чтобы можно было запустить
    и вторую такую же группу контейнеров со своей «другой» вирт. сетью.
    При том, разные группы могли иметь одинаковые ip.
    Т.е. такая вот изолированная от внешнего мира и друг-друга сеть.

    В VirtualBox для этого можно использовать «виртуальный адаптер хоста».

Ваш комментарий