Метод связи контейнера Docker

Docker

Несколько дней назад, чтобы решить противоречие между ежедневной работой и разработкой и тестированием в локальной среде, в системе 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 по умолчанию

bridge原理示意图

Как показано выше, в 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 предоставляет следующее:

  1. Добавлять при запуске контейнера докеров--linkПараметр, но в настоящее время от него отказались. Основная причина отказа в том, что его нужно создать на обоих подключенных контейнерах.--linkвариант, когда количество соединяемых между собой контейнеров велико, сложность операции значительно возрастет;

  2. После запуска контейнера докеров войдите в контейнер и измените/etc/hostКонфигурационный файл, недостаток в том, что ручная настройка сложнее;

  3. ОбычайbridgeМост, который в настоящее время является основным методом решения подобных задач;

2.2 Пользовательский мост

Основные преимущества пользовательского моста по сравнению с мостом по умолчанию:

  • Определяемые пользователем мосты могут обеспечить лучшую производительность в контейнерных приложениях.эффект изоляциии лучшеинтероперабельность: Это предложение может показаться противоречивым, но更好的隔离效果для внешней сети и更好的互通性означает то же самоеbridgeмежду разными контейнерами. В качестве примера возьмем два предыдущих контейнера, container1 и container2, соответственно развертывающие веб-службу и службу mysql.Контейнеру 1 нужно только предоставить веб-службу внешней сети.80Контейнер 2, который отвечает за серверную часть, должен быть связан только с контейнером 1 и не должен подвергаться воздействию внешнего мира, что эффективно защищает безопасность внутреннего контейнера и улучшает эффект внешней изоляции контейнера. и определяемый пользователемbridgeВсе порты между контейнером 1 и контейнером 2 автоматически открываются, что обеспечивает безбарьерную связь между контейнерами без случайного доступа внешнего мира.
  • Пользовательские мосты обеспечивают автоматическое разрешение DNS между контейнерами: Это также находится в центре внимания данной статьи.В отличие от моста по умолчанию, который может соединяться только через IP, определяемый пользователем мост автоматически обеспечивает разрешение DNS между контейнерами, а контейнеры могут взаимодействовать через имена или псевдонимы контейнеров.
2.2.1 Как использовать пользовательский мост
  1. Создайте пользовательский мост:

    docker network create my-net        # 创建了一个名为"my-net"的网络
    
  2. Добавьте контейнер веб-службы и контейнер службы 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-netIP-адреса в сети: «172.18.0.3/16», «172.18.0.2/16», которые отличаются от предыдущих «172.17.0.2/16» и «172.17.0.3/16».

  3. Соединение по имени или псевдониму контейнера: Перейдите к контейнеру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».

  4. Отключиться от сети: Поскольку наш контейнер все еще подключен к мосту по умолчаниюdocker0, а сейчас он нам не нужен, поэтому мы должны связать контейнер сdocker0отключен, выполните следующие действия:

    # 断开容器与docker0的连接
    docker network disconnect bridge test_demo
    docker network disconnect bridge mysqld5.7
    

3. overlay

Ключевые слова: межхостовое взаимодействие, кластеризация.

【продолжение следует. . 】


  1. Run multiple services in a container. docs.docker.com/config/cont… ↩︎