Несколько дней назад, чтобы решить противоречие между ежедневной работой и разработкой и тестированием в локальной среде, в системе Windows с помощью docker была встроена тестовая среда на базе Linux:С Docker кодируйте под win10 и тестируйте под Linux одним щелчком мыши. В этой статье в основном рассказывается, как создать среду, которая в основном соответствует производственной среде, с помощью локального докера, а также запустить и протестировать наш код одним щелчком мыши. Docker официально рекомендует запускать только один сервис на контейнер[1], но наш проект может состоять из нескольких сервисов, для которых может потребоваться поддержка промежуточного программного обеспечения, такого как mysql, redis и т. д., поэтому обычно мы разделяем разные сервисы проекта на разные контейнеры. Хотя этот подход имеет преимущества низкой связанности и высокой степени изоляции, он также увеличивает сложность связи между службами.
Способы связи между контейнерами Docker можно разделить на:volume共享通信
,网络通信
По дальности связи его также можно разделить на:同主机通信
и跨主机通信
Ждать. В этой статье в основном обсуждается метод сетевого взаимодействия между контейнерами.
1. Сетевая модель Docker
Классификация сетевых моделей Docker:
- bridge: модель сетевого драйвера по умолчанию в Docker, которая по умолчанию использует этот тип драйвера, если он не указан при запуске контейнера;
- host: Прервать сетевую изоляцию между контейнером Docker и хостом и напрямую использовать сетевое окружение хоста.Эта модель применима только к Docker 17.6 и выше;
- overlay: он может подключать несколько демонов докеров или обеспечивать связь между службами кластера, он подходит для связи между контейнерами докеров на разных хостах;
- macvlan: вы можете назначить MAC-адрес док-контейнеру, чтобы он работал как настоящая физическая машина;
- none: То есть сетевой драйвер отключен, и вам нужно вручную настроить конфигурацию сетевого драйвера;
- plugins: использование подключаемых модулей сетевых драйверов сторонних производителей;
Выше приведены несколько сетевых моделей, поддерживаемых Docker. Все они имеют уникальные характеристики и область применения. Чтобы более подробно понять принцип работы сети Docker, ниже для исследования выбрано несколько важных сетевых моделей.
2. bridge
2.1 Мост Docker по умолчанию
Как показано выше, в Dockerbridge
Схематическая диаграмма режима драйвера, где синие модули представляют сетевые карты на хосте. Виртуальный мост автоматически создается на хосте при запуске Docker.docker0
, пара создается автоматически при создании док-контейнера с использованием сетевого режима по умолчанию.veth pair
интерфейс, один конец подключен к контейнеру докера (как показано в контейнереeth0
), один конец подключен к виртуальному мостуdocker0
вверх (как показано на рисункеveth
). этоveth pair
Это виртуальное сетевое устройство, в основном используемое для сетевого взаимодействия в разных пространствах имен (имеется в виду сетевая изоляция), и оно всегда существует парами. Здесь это можно представить как пару из двух виртуальных сетевых карт, соединенных виртуальными сетевыми кабелями, один конец которых подключен к докер-контейнеру, а другой конец подключен к виртуальному сетевому мосту.docker0
.
Таким образом, разные докер-контейнеры могут общаться друг с другом через IP-адреса, а также могут получать доступ к сети на хосте через виртуальный мост.eth0
(Добавить правила iptables для передачи доступа, выдаваемого контейнером докеров, к целевому адресу черезподмена адресаСпособ изменения хоста для доступа к целевому адресу).
Если вы хотите получить доступ к докер-контейнеру из внешней сети, вам нужно добавить параметр '-p [порт хоста]: [порт контейнера]" для сопоставления портов при запуске контейнера докеров. Принцип заключается в доступе к данным [ порт хоста] путем изменения правил iptables.Перенаправляется на [порт контейнера] контейнера докера, но этот подход также имеет недостаток, заключающийся в том, что он занимает ограниченные ресурсы порта хоста.
на хосте с помощью командыdocker network ls
Вы можете просмотреть существующую сеть в докере:
docker network ls
# 输出结果:
NETWORK ID NAME DRIVER SCOPE
e79b7548b225 bridge bridge local
666d5f1f459d host host local
d0d785cf4794 none null local
затем по командеdocker network inspect bridge
Просмотрите подробную конфигурацию мостовой сети:
docker network inspect bridge
# 输出结果:
[
{
"Name": "bridge",
"Id": "e79b7548b225c3c80d0f70d0de0b5911ed70a7f39ac20f75a8ae71c5cef05b3a",
"Created": "2019-05-17T13:01:27.6581642Z",
"Scope": "local",
"Driver": "bridge", # bridge驱动模式
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16", # 子网,docker容器的IP范围
"Gateway": "172.17.0.1" # 网关,即docker0
}
]
},
...
省略
...
# 两个docker容器(一个mysql容器,一个Web服务容器)的网络配置
"Containers": {
# mysql容器
"d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679": {
"Name": "mysqld5.7",
"EndpointID": "32e900f33367e3570c416c43a5618bd7a742cf94f36799e92895951ed1784736",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16", # 容器的IP
"IPv6Address": ""
},
# 基于tornado的Web服务容器
"dd292d535d16bbfe5382e29486756f4dddfea8e9b10af769db61618d739c5c4e": {
"Name": "test_demo",
"EndpointID": "eaf8e294f7b54aa50c6e6b30ac91f63b1a0ccbc5b56d6fbdcfeacd0471b15eb3",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16", # 容器的IP
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
Из приведенной выше информации о конфигурации видно, что IP-адрес шлюза докер-моста — «172.17.0.1», т. е.docker0
, а подсеть докера — «172.17.0.0/16», докер назначит контейнеру IP-адрес «172.17.0.0/16», как вmysql容器
IP "172.17.0.2/16",test_demo容器
IP-адрес «172.17.0.3/16». По мере прохождения различных контейнеровveth pair
подключен к виртуальному мостуdocker0
, поэтому контейнеры могут взаимодействовать друг с другом через IP, но не могут взаимодействовать через имя контейнера:
# 在test_demo容器中访问mysqld5.7容器(通过IP)
ping 172.17.0.2 -c 3
# 输出结果:
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.147 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.185 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.209 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2057ms
rtt min/avg/max/mdev = 0.147/0.180/0.209/0.027 ms
# 在test_demo容器中访问mysqld5.7容器(通过容器名)
ping mysqld5.7
# 输出结果:
ping: mysqld5.7: Name or service not known
Итак, мост по умолчаниюbridge
Контейнеры в сети могут быть связаны между собой только по IP и не могут разрешать имена или псевдонимы через DNS. Если мы развернем веб-службу в контейнере1 и mysql в контейнере2, веб-служба в контейнере1 часто должна подключаться к mysql контейнера2, который может быть подключен только по IP, но докер не может гарантировать, что IP-адрес после перезапуска контейнера будет Таким образом, лучший способ — подключиться через псевдонимы, добавить DNS-сервер в сеть и сопоставить имя контейнера с IP-адресом, избавляя от необходимости вручную изменять IP-адрес веб-службы, подключенной к mysql.
Чтобы реализовать взаимосвязь различных контейнеров через имена или псевдонимы контейнеров, docker предоставляет следующее:
-
Добавлять при запуске контейнера докеров
--link
Параметр, но в настоящее время от него отказались. Основная причина отказа в том, что его нужно создать на обоих подключенных контейнерах.--link
вариант, когда количество соединяемых между собой контейнеров велико, сложность операции значительно возрастет; -
После запуска контейнера докеров войдите в контейнер и измените
/etc/host
Конфигурационный файл, недостаток в том, что ручная настройка сложнее; -
Обычай
bridge
Мост, который в настоящее время является основным методом решения подобных задач;
2.2 Пользовательский мост
Основные преимущества пользовательского моста по сравнению с мостом по умолчанию:
- Определяемые пользователем мосты могут обеспечить лучшую производительность в контейнерных приложениях.эффект изоляциии лучшеинтероперабельность:
Это предложение может показаться противоречивым, но
更好的隔离效果
для внешней сети и更好的互通性
означает то же самоеbridge
между разными контейнерами. В качестве примера возьмем два предыдущих контейнера, container1 и container2, соответственно развертывающие веб-службу и службу mysql.Контейнеру 1 нужно только предоставить веб-службу внешней сети.80
Контейнер 2, который отвечает за серверную часть, должен быть связан только с контейнером 1 и не должен подвергаться воздействию внешнего мира, что эффективно защищает безопасность внутреннего контейнера и улучшает эффект внешней изоляции контейнера. и определяемый пользователемbridge
Все порты между контейнером 1 и контейнером 2 автоматически открываются, что обеспечивает безбарьерную связь между контейнерами без случайного доступа внешнего мира. - Пользовательские мосты обеспечивают автоматическое разрешение DNS между контейнерами: Это также находится в центре внимания данной статьи.В отличие от моста по умолчанию, который может соединяться только через IP, определяемый пользователем мост автоматически обеспечивает разрешение DNS между контейнерами, а контейнеры могут взаимодействовать через имена или псевдонимы контейнеров.
2.2.1 Как использовать пользовательский мост
-
Создайте пользовательский мост:
docker network create my-net # 创建了一个名为"my-net"的网络
-
Добавьте контейнер веб-службы и контейнер службы mysql в «my-net» и наблюдайте за изменениями:
docker network connect my-net test_demo # 将Web服务加入my-net网络中 docker network connect my-net mysqld5.7 # 将mysql服务加入my-net网络中
# 查看my-net的网络配置 docker network inspect my-net # 输出结果(省略部分内容): [ { "Name": "my-net", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Config": [ { "Subnet": "172.18.0.0/16", # my-net的子网 "Gateway": "172.18.0.1" # my-net的网关 } ] }, "Containers": { "d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679": { "Name": "mysqld5.7", "EndpointID": "7d0e8d70bb523cceb4d2d8d4e3f8231fc68332c70f7f9b4e5d4abccce2b31a65", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", # mysql服务容器的IP,与之前不同 "IPv6Address": "" }, "dd292d535d16bbfe5382e29486756f4dddfea8e9b10af769db61618d739c5c4e": { "Name": "test_demo", "EndpointID": "f7802f1af81e258f77e227609dfdcdf66c49f19776381eb8b0dca6d9e794ccad", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", # Web服务容器的IP,与之前不同 "IPv6Address": "" } }, } ]
Как показано выше, определяемая пользователем сеть
my-net
Подсеть "172.18.0.0/16", поэтому два док-контейнера находятся вmy-net
IP-адреса в сети: «172.18.0.3/16», «172.18.0.2/16», которые отличаются от предыдущих «172.17.0.2/16» и «172.17.0.3/16». -
Соединение по имени или псевдониму контейнера: Перейдите к контейнеру1 веб-сервера и подключитесь к контейнеру2:
ping mysqld5.7 -c 3 # 输出结果: PING mysqld5.7 (172.18.0.3) 56(84) bytes of data. 64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.066 ms 64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.145 ms 64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.143 ms --- mysqld5.7 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2048ms rtt min/avg/max/mdev = 0.066/0.118/0.145/0.036 ms
Как показано выше, мы уже можем подключиться к серверу mysql через имя контейнера «mysqld5.7».
-
Отключиться от сети: Поскольку наш контейнер все еще подключен к мосту по умолчанию
docker0
, а сейчас он нам не нужен, поэтому мы должны связать контейнер сdocker0
отключен, выполните следующие действия:# 断开容器与docker0的连接 docker network disconnect bridge test_demo docker network disconnect bridge mysqld5.7
3. overlay
Ключевые слова: межхостовое взаимодействие, кластеризация.
【продолжение следует. . 】
-
Run multiple services in a container. docs.docker.com/config/cont… ↩︎