Network containers
If you are working your way through the user guide, you just built and ran a simple application. You’ve also built in your own images. This section teaches you how to network your containers.
Launch a container on the default network
Docker includes support for networking containers through the use of network drivers. By default, Docker provides two network drivers for you, the bridge and the overlay drivers. You can also write a network driver plugin so that you can create your own drivers but that is an advanced task.
Every installation of the Docker Engine automatically includes three default networks. You can list them:
The network named bridge is a special network. Unless you tell it otherwise, Docker always launches your containers in this network. Try this now:

Inspecting the network is an easy way to find out the container’s IP address.
You can remove a container from a network by disconnecting the container. To do this, you supply both the network name and the container name. You can also use the container ID. In this example, though, the name is faster.
While you can disconnect a container from a network, you cannot remove the builtin bridge network named bridge . Networks are natural ways to isolate containers from other containers or other networks. So, as you get more experienced with Docker, create your own networks.
Create your own bridge network
Docker Engine natively supports both bridge networks and overlay networks. A bridge network is limited to a single host running Docker Engine. An overlay network can include multiple hosts and is a more advanced topic. For this example, create a bridge network:
The -d flag tells Docker to use the bridge driver for the new network. You could have left this flag off as bridge is the default value for this flag. Go ahead and list the networks on your machine:
If you inspect the network, it has nothing in it.
Add containers to a network
To build web applications that act in concert but do so securely, create a network. Networks, by definition, provide complete isolation for containers. You can add containers to a network when you first run a container.
Launch a container running a PostgreSQL database and pass it the —net=my_bridge flag to connect it to your new network:
If you inspect your my_bridge you can see it has a container attached. You can also inspect your container to see where it is connected:
Now, go ahead and start your by now familiar web application. This time don’t specify a network.

Which network is your web application running under? Inspect the application to verify that it is running in the default bridge network.
Then, get the IP address of your web
Now, open a shell to your running db container:
After a bit, use CTRL-C to end the ping and notice that the ping failed. That is because the two containers are running on different networks. You can fix that. Then, use the exit command to close the container.
Docker networking allows you to attach a container to as many networks as you like. You can also attach an already running container. Go ahead and attach your running web app to the my_bridge .

Open a shell into the db application again and try the ping command. This time just use the container name web rather than the IP address.
The ping shows it is contacting a different IP address, the address on the my_bridge which is different from its address on the bridge network.
Next steps
Now that you know how to network containers, see how to manage data in containers.
Русские Блоги
Связь между хостами Docker-контейнера: прямая маршрутизация
Обзор
Что касается собственной сети Docker по умолчанию, разные контейнеры Docker на одном хосте могут напрямую связываться с мостом docker0, и это нормально, а контейнеры Docker на разных хостах могут быть сопоставлены только с портами на хосте. Для связи иногда этот метод неудобен и даже не соответствует нашим требованиям, поэтому необходимо напрямую использовать собственные IP-адреса для связи между контейнерами Docker, расположенными на разных физических машинах. Кроме того, если мы настроим контейнеры Docker на разных физических хостах, мы неизбежно столкнемся с проблемами связи между хостами с контейнерами Docker. В этой статье мы попробуем.
Заметка: Эта статья была впервые опубликована в моем публичном аккаунтеCodeSheep , МожетНажмите Илисканирование НижеБыть осторожен Приходите подписаться ↓ ↓ ↓
Структура ситуации
Как показано на рисунке ниже, у нас есть два физических хоста 1 и 2. Мы запускаем контейнер centos на каждом хосте. После успешного запуска два контейнера запускаются на двух хостах соответственно. Распределение IP-адресов по умолчанию выглядит следующим образом Как показано на рисунке, это также сеть по умолчанию самого Docker.
Как контейнеры Docker на двух хостах могут напрямую общаться через IP-адреса?
Одно из решений, которое приходит на ум, — использовать соответствующий хостДобавить маршрут Для достижения прямой связи между двумя контейнерами centos. Давай попробуем
Принцип анализа схемы
Поскольку IP-адрес контейнера используется для маршрутизации, необходимо запретить контейнерам на разных хостах использовать один и тот же IP-адрес. По этой причине мы должны назначить разные подсети разным хостам, чтобы гарантировать это. Итак, мы строим схему маршрутизации для связи между двумя контейнерами, как показано на следующем рисунке.
Конфигурация следующая:
- IP-адрес хоста 1: 192.168.145.128.
- IP-адрес хоста 2: 192.168.145.129.
- Подсеть, назначенная контейнеру Docker на хосте 1: 172.17.1.0/24
- Подсеть, назначенная контейнеру Docker на хосте 2: 172.17.2.0/24
После этой конфигурации контейнеры Docker на двух хостах определенно не будут использовать один и тот же IP-адрес, чтобы избежать конфликтов IP.
Мы следующиеОпределите два правила маршрутизации Кому:
- Все пакеты с адресом назначения 172.17.1.0/24 пересылаются на хост 1
- Все пакеты с адресом назначения 172.17.2.0/24 пересылаются на хост 2.
Таким образом, процесс передачи пакетов данных между двумя контейнерами выглядит следующим образом:
- Пакет данных, отправленный из контейнера 1 в контейнер 2, сначала отправляется на «шлюз» docker0 контейнера 1, а затем пакет данных должен быть отправлен на хост 2 путем поиска маршрута хоста 1. После того, как пакет данных достигает хоста 2, он пересылается на докер0 хоста 2. , И, наконец, он передает пакет данных в container2; обратный принцип тот же, поэтому я не буду повторять его.
Это то, что мы думаем о плане, давайте попробуем его на практике, чтобы убедиться, что он осуществим.
Фактический тест
- 0x01. Настройте docker0 на хосте 1 и хосте 2 соответственно.
Редактировать на хосте 1 /etc/docker/daemon.json Файл, добавить контент: "bip" : "ip/netmask"
Редактировать на хосте 2 /etc/docker/daemon.json Файл, добавить контент: "bip" : "ip/netmask"
- 0x02. Перезапустите службу докеров.
На обоих хостах 1 и 2 выполните следующие команды, чтобы перезапустить службу Docker, чтобы измененный сегмент сети docker0 вступил в силу.
- 0x03. Добавить правила маршрутизации
Добавьте правила маршрутизации на хосте 1 следующим образом:
Добавьте правила маршрутизации на хосте 2 следующим образом:
- 0x04. Настроить правила iptables
Добавьте следующие правила на хост 1:
Добавьте следующие правила на хост 2:
- 0x05. Запустить контейнер
Запустите контейнер centos на хосте 1:
Запустите контейнер centos на хосте 2:
- 0x06. Прямая связь между контейнерами
Хорошо, теперь два контейнера могут пинговать друг друга
постскриптум
В этой статье обсуждается возможное решение для прямой связи между контейнерами Docker между разными хостами в локальной сети. Конечно, есть много готовых решений для межузловой контейнерной коммуникации. Типичными примерами являются фланелевые. МоиПерсональное частное облако Эта схема тоже используется.
Другие статьи автора о практике SpringBt находятся здесь:
Если вам интересно, вы также можете потратить некоторое время на то, чтобы прочитать некоторые статьи автора о контейнеризации и микросервисах:
Управление сетевыми интерфейсами в Docker
Есть такие сетевые приложения, которым необходимо иметь выход во внешний мир не одним портом, а сразу большой группой. Примерами таких приложений могут являться различные программы работающие с потоковыми видео/аудио каналами. Например различные PBX решения, такие как Asterisk или FreeSWITCH.
Собственно, с попыток контейнеризировать Asterisk всё и началось. Есть готовые образы на Docker HUB, хорошим примером является dougbtv/asterisk.
Дальнейший текст можно считать вольным переводом документации по настройке сети в docker .
Не использовать контейнеризацию сетевой подсистемы
Это один из очень простых способов предоставить доступ к контейнеру. Если создать контейнер с опцией —net=host , то контейнер будет запущен с сетевой подсистемой хост-системы. Это крайне просто в реализации, но могут возникнуть другие проблемы. Например, придется создавать алиасы на необходимый внешний интерфейс с другими IP-адресами, а в приложения в контейнерах запускать с привязкой именно на этот адрес, а не на 0.0.0.0 . Все проблемы можно решить с помощью создания простого скрипта, который будет “разруливать” эти проблемы:
- создавать алиас на интерфейс
- передавать адрес в контейнер в какой-нибудь переменной
- контейнер будет использовать эту переменную для запуска приложения
Но есть и положительная сторона — нет необходимости узнавать адрес назначаемый контейнеру.
И как дополнение — контейнер имеет доступ к хостовой подсистеме, может управлять ею, может иметь доступ к своему внешнему API. Это сомнительная необходимость, в частности со стороны безопасности.
Проброс одного порта
Проброс одного порта в docker существовал изначально и делался крайне просто с помощью ключа -p или опции EXPOSE в Dockerfile . Например для запуска контейнера с mysql достаточно было указать порт внутри контейнера и порт для хост машины -p <host port>:<container port> (ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort):
Подробне про это можно прочитать в официальной документации тут.
Просмотреть проброшенные порты можно с помощью docker port :
Проброс группы портов
Проброс группы портов был востребован очень давно, но был добавлен в исходный код только 1 ноября 2014. Этот функционал уже доступен в docker версии 1.4.1 .
Пример совсем не похож на реальность, но на то он и пример. Необходимо пробросить 5 портов, 2000-2005 или 3000-3005. Сделаем это опцией —expose , но в одном случае ключ -P (публиковать проброшенные порты на хост-систему) будет установлен в состояние по умолчанию — false , а в другом изменим его состояние на true .
После этого в iptables в цепочках FORWARD и DOCKER увидим следующее:
Как видно из вывода iptables — сервис docker создает правила для проброса портов с хост-системы в контейнер и обратно. Но, стоит учесть то, что при использовании автоматической публикации портов в хост-систему он использует свободные порты из диапазона 49153-65535.
Теперь сделаем тоже самое, но с диапазоном портов 3000-3005 и без публикации портов в хост-систему:
После этого мы не уивидим никаких дополнительных правил для проброса портов, лишь правила для bridge-интерфейса docker0 :
Теперь docker не создал правил для проброса портов. Сделаем это сами и всего лишь одной строкой для каждой цепочки:
Маршрутизация в контейнер
Можно сделать всё на много проще. На сетевом интерфейсе хост-системы уже включен ip_forward (это требуется при первичной настройке docker ) и этого достаточно.
Допустим на хост-системе есть 2 сетевых интерфейса с ip-адресами: 10.10.10.10 и 172.172.172.172. Для доступа к контейнерам из внешней сети достаточно на роутерах во внешней сети указать маршрут на сеть docker через один из ip адресов хост-системы. Но тут встает другая проблема — закрепить IP-адрес за контейнером.
Для назначения статическиого адреса контейнеру создадим контейнер со своей сетевой подсистемой, но никак не связанной с хостовой. Для этого используется ключ —net=none :
Далее, следуя инструкциям из документации назначим IP-адрес контейнеру:
Теперь внутри контейнера ubuntu_none установлен IP-адрес 192.168.10.2. Таким образом был назначен необходимый IP-адрес.
Скрипт для запуска контейнеров со постоянным IP-адресом
Эта часть не совсем относится к настройке сети в контейнерах docker , а скорее к автоматизации описанного ранее.
Почитать подробнее про ностройку сети в docker можно тут — Network Configuration.
Надеюсь весь описанный материал покрывает все стандартные варианты запуска приложений, понятен и не вызывает вопросов. Если вопросы есть, то задавайте их в комментариях.
Change default route in docker container
I have a docker container that is connected to two networks, the default bridge and a custom bridge. Via the default, it is linked to another container only in the default network and via the custom bridge, it gets an IP address in local network.
This works pretty well from the internal network, however, I have a routing problem:
How can I change the default route to 192.169.130.3 such that it persists a restart?
I can change it while container1 is running with
but that is gone after a restart. How can I change that?
Update: Apparently, the lexicographical order of the networks could also be part of the issue. I will test it when I get a chance.
3 Answers 3
If I understand the question, the problem is : when restarting a container connected to multiple bridges, how to prefer a bridge to use for default route ?
I searched available options and made some tests, I did not found any docker command line option to specify a default route or to prefer a bridge as default when the container is connected to multiple bridges. When I restart a container connected to the default bridge ( bridge ) and a custom bridge (your homenet ), the default route is automatically set to use the default bridge (gateway 172.17.0.1 ). This corresponds to the behavior you describe.
Solution 1: Specify a start script in the run command that is in charge to change the default route and start the service(s) you container has to run:
This script has to be available inside the container, it can be on a shared folder ( -v option) or loaded at image building with a Dockerfile.
Note: before connecting the container to your custom bridge ( docker network connect homenet container1 ), your_start_script.sh will crash because the default route does not correspond to any available network.
I tested to log the output of ip route inside container1 run with —restart always , after connecting it to the custom bridge it has the wanted default route.
Solution 2: Set container default route from host on container start events
Where route_setting.sh contains your instructions for changing the container’s default route:
This solution avoids giving special permissions to the container and transfers the route changing responsibility to the host.