Глубокое погружение в сети Docker

DockerDockerBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном занятии (LabEx) мы рассмотрим продвинутые концепции сетевого взаимодействия в Docker, основываясь на базовых знаниях о сетях Docker. Мы углубимся в три основных режима сети: Bridge (Мост), Host (Хост) и None (Нет). Также мы узнаем, как создавать пользовательские сети, соединять контейнеры в разных сетях и понять, как каждый режим сети влияет на взаимодействие и изоляцию контейнеров. Этот практический опыт даст вам прочный фундамент в использовании сетевых возможностей Docker.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/NetworkOperationsGroup(["Network Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/NetworkOperationsGroup -.-> docker/network("Manage Networks") subgraph Lab Skills docker/run -.-> lab-389047{{"Глубокое погружение в сети Docker"}} docker/exec -.-> lab-389047{{"Глубокое погружение в сети Docker"}} docker/inspect -.-> lab-389047{{"Глубокое погружение в сети Docker"}} docker/network -.-> lab-389047{{"Глубокое погружение в сети Docker"}} end

Пользовательские мостовые сети (Custom Bridge Networks)

Хотя Docker предоставляет сеть по умолчанию типа мост (bridge), создание пользовательских мостовых сетей обеспечивает лучшую изоляцию и контроль над взаимодействием между контейнерами.

  1. Сначала посмотрим на текущий список сетей Docker:
docker network ls

Вы должны увидеть что-то вроде этого:

NETWORK ID     NAME      DRIVER    SCOPE
296d1b460b17   bridge    bridge    local
91199fc6ad2e   host      host      local
1078d2c781b6   none      null      local
  1. Теперь создадим пользовательскую мостовую сеть:
docker network create my-custom-bridge
  1. Снова выведем список всех сетей Docker, чтобы убедиться, что сеть создана:
docker network ls

Теперь в выводе вы должны увидеть my-custom-bridge:

NETWORK ID     NAME               DRIVER    SCOPE
296d1b460b17   bridge             bridge    local
91199fc6ad2e   host               host      local
7215f99d0080   my-custom-bridge   bridge    local
1078d2c781b6   none               null      local
  1. Запустим два контейнера в пользовательской мостовой сети и установим утилиту ping:
docker run --network=my-custom-bridge --name container1 -d nginx
docker run --network=my-custom-bridge --name container2 -d nginx

Теперь установим утилиту ping в обоих контейнерах. Это необходимо, так как в стандартном образе Nginx нет утилиты ping:

docker exec container1 apt-get update && docker exec container1 apt-get install -y iputils-ping
docker exec container2 apt-get update && docker exec container2 apt-get install -y iputils-ping
  1. Протестируем взаимодействие между контейнерами:
docker exec container1 ping -c 4 container2

Вы должны увидеть успешные ответы на запросы ping, что показывает, что контейнеры в одной и той же пользовательской мостовой сети могут взаимодействовать, используя имена контейнеров. Это работает, потому что встроенный DNS Docker преобразует имена контейнеров в их IP-адреса в рамках одной сети.

Если вы не видите успешных ответов на запросы ping, убедитесь, что оба контейнера работают (docker ps) и что вы правильно установили утилиту ping.

Соединение контейнеров между сетями

Docker позволяет подключать контейнеры к нескольким сетям, что обеспечивает взаимодействие между контейнерами, находящимися в разных сетях. Это особенно полезно, когда вы хотите изолировать определенные контейнеры, но при этом разрешить между ними определенное взаимодействие.

  1. Сначала создадим вторую пользовательскую мостовую сеть:
docker network create my-second-bridge
  1. Проверим создание сети:
docker network ls

Теперь вы должны увидеть обе пользовательские сети:

NETWORK ID     NAME               DRIVER    SCOPE
296d1b460b17   bridge             bridge    local
91199fc6ad2e   host               host      local
7215f99d0080   my-custom-bridge   bridge    local
8a15f99d0081   my-second-bridge   bridge    local
1078d2c781b6   none               null      local
  1. Подключим container2 к новой сети:
docker network connect my-second-bridge container2

Эта команда добавляет container2 в сеть my-second-bridge, сохраняя при этом его подключение к сети my-custom-bridge.

  1. Создадим новый контейнер в второй сети:
docker run --network=my-second-bridge --name container3 -d nginx
docker exec container3 apt-get update && docker exec container3 apt-get install -y iputils-ping
  1. Протестируем взаимодействие между всеми контейнерами:
docker exec container1 ping -c 2 container2
docker exec container1 ping -c 2 container3
docker exec container2 ping -c 2 container3

Обратите внимание на результаты:

  • container1 может взаимодействовать с container2 (они находятся в одной сети)
  • container1 не может взаимодействовать с container3 (они находятся в разных сетях)
  • container2 может взаимодействовать как с container1, так и с container3 (он подключен к обеим сетям)

Если container1 смог отправить запросы ping в container3, значит, есть проблемы с изоляцией сетей.

Режим сети хоста (Host Network Mode)

Режим сети хоста отменяет сетевую изоляцию между контейнером и хост-машиной Docker, позволяя контейнеру напрямую использовать сеть хоста. Это может быть полезно для максимизации производительности, но имеет последствия для безопасности, так как снижает уровень изоляции.

  1. Создайте контейнер, используя режим сети хоста:
docker run --network host --name host-container -d nginx
  1. Проверьте текущий список сетей:
docker network ls

Вы не увидите новой сети для этого контейнера, так как он напрямую использует сеть хоста.

  1. Убедитесь, что контейнер использует сеть хоста:
docker inspect --format '{{.HostConfig.NetworkMode}}' host-container

В выводе должно быть host.

  1. Попробуйте получить доступ к стандартной странице Nginx с хост-машины:
curl localhost:80

Вы должны увидеть приветственную страницу Nginx. Это работает, потому что контейнер использует сеть хоста, и Nginx прослушивает порт 80 сетевого интерфейса хоста.

Примечание: Если на хост-машине уже запущена служба на порту 80, этот шаг может завершиться неудачно. В таком случае вам нужно сначала остановить существующую службу.

Режим сети "Нет" (None Network Mode)

Режим сети "нет" (none) создает контейнеры без сетевого интерфейса, полностью изолируя их от сети. Это полезно для обеспечения максимального уровня сетевой изоляции с точки зрения безопасности, но это также означает, что контейнер не может взаимодействовать по сети вообще.

  1. Создайте контейнер без сети:
docker run --network none --name isolated-container -d alpine sleep infinity
  1. Проверьте текущий список сетей:
docker network ls

Вы не увидите новой сети для этого контейнера, так как он не подключен ни к какой сети.

  1. Убедитесь, что у контейнера нет сетевого интерфейса:
docker exec isolated-container ip addr

Вы должны увидеть только локальный петлевой интерфейс (lo). Не будет никаких интерфейсов eth0 или других сетевых интерфейсов.

  1. Попробуйте отправить запросы ping на Google из изолированного контейнера:
docker exec isolated-container ping -c 2 google.com

Это должно завершиться ошибкой "Сеть недоступна", так как у контейнера нет доступа к сети.

Сетевые псевдонимы и обнаружение служб (Network Aliases and Service Discovery)

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

  1. Создайте новую мостовую сеть для этого упражнения:
docker network create service-network
  1. Проверьте создание сети:
docker network ls

Вы должны увидеть service-network в списке.

  1. Создайте два контейнера с одинаковым сетевым псевдонимом:
docker run -d --network service-network --network-alias myservice --name service1 nginx
docker run -d --network service-network --network-alias myservice --name service2 nginx
  1. Создайте клиентский контейнер и используйте nslookup для разрешения имени службы:
docker run --rm --network service-network appropriate/curl nslookup myservice

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

  1. Протестируйте доступ к службе несколько раз:
for i in {1..4}; do docker run --rm --network service-network appropriate/curl ping -c 1 myservice; done

Вы должны увидеть ответы от обоих контейнеров, что демонстрирует простой балансировщик нагрузки. DNS-сервер Docker будет чередовать два IP-адреса при разрешении имени myservice.

PING myservice (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.106 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.106/0.106/0.106 ms
PING myservice (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.119 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.119/0.119/0.119 ms
PING myservice (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.097 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.097/0.097 ms
PING myservice (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.140 ms

--- myservice ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.140/0.140/0.140 ms

Резюме

В этом продвинутом практическом занятии по сетевым возможностям Docker мы рассмотрели несколько ключевых концепций:

  1. Пользовательские мостовые сети для улучшения изоляции и взаимодействия контейнеров
  2. Соединение контейнеров между несколькими сетями
  3. Режим сети хоста (Host network mode) для прямого доступа к сетевому стеку хоста
  4. Режим сети "Нет" (None network mode) для полной сетевой изоляции
  5. Сетевые псевдонимы и обнаружение служб (Network aliases and service discovery) для создания масштабируемых приложений

Эти продвинутые сетевые функции Docker предоставляют мощные инструменты для проектирования сложных много-контейнерных приложений с точным контролем взаимодействия и изоляции между контейнерами. Понимание этих концепций является важным условием для проектирования эффективных, безопасных и масштабируемых контейнеризованных приложений.

Не забывайте, что хотя Docker предоставляет широкие возможности для настройки сети, при проектировании архитектуры сетей контейнеров важно учитывать аспекты безопасности. Всегда следуйте принципу наименьших привилегий, открывая только необходимые порты и службы.

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