Введение
В ходе этой практической работы мы изучим продвинутые концепции сетевого взаимодействия в Docker, опираясь на базовые знания о сетях. Мы подробно разберем три основных сетевых режима: Bridge (мост), Host (хост) и None (отсутствие сети). Вы также научитесь создавать пользовательские сети, подключать контейнеры к нескольким сетям одновременно и поймете, как каждый режим влияет на коммуникацию и изоляцию контейнеров. Этот практический опыт заложит прочный фундамент для работы с сетевой инфраструктурой Docker.
Пользовательские мостовые сети
Хотя Docker предоставляет стандартную сеть типа bridge по умолчанию, создание собственных пользовательских мостовых сетей обеспечивает лучшую изоляцию и более гибкий контроль над взаимодействием между контейнерами.
- Для начала просмотрим текущий список сетей Docker:
docker network ls
Вы должны увидеть примерно следующее:
NETWORK ID NAME DRIVER SCOPE
296d1b460b17 bridge bridge local
91199fc6ad2e host host local
1078d2c781b6 none null local
- Теперь создадим пользовательскую мостовую сеть:
docker network create my-custom-bridge
- Снова выведите список всех сетей 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
- Запустите два контейнера в этой пользовательской сети и установите утилиту 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
- Проверьте связь между контейнерами:
docker exec container1 ping -c 4 container2
Вы должны увидеть успешные ответы на запросы ping. Это доказывает, что контейнеры в одной пользовательской мостовой сети могут взаимодействовать друг с другом, используя имена контейнеров. Это возможно благодаря встроенному DNS-серверу Docker, который сопоставляет имена контейнеров с их IP-адресами внутри одной сети.
Если ping не проходит, убедитесь, что оба контейнера запущены (docker ps) и утилита ping была установлена без ошибок.
Соединение контейнеров между разными сетями
Docker позволяет подключать контейнеры к нескольким сетям одновременно, что делает возможным взаимодействие между контейнерами, находящимися в разных сегментах. Это особенно полезно, когда нужно изолировать определенные контейнеры, сохранив при этом возможность точечного обмена данными.
- Сначала создадим вторую пользовательскую мостовую сеть:
docker network create my-second-bridge
- Проверьте создание сети:
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
- Подключите
container2к новой сети:
docker network connect my-second-bridge container2
Эта команда добавляет container2 в сеть my-second-bridge, при этом он остается подключенным и к my-custom-bridge.
- Создайте новый контейнер во второй сети:
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
- Проверьте связь между всеми контейнерами:
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 смог пропинговать container3, это означало бы нарушение логики изоляции сети.
Сетевой режим Host
Режим Host убирает сетевую изоляцию между контейнером и хост-системой Docker, позволяя контейнеру использовать сетевой стек хоста напрямую. Это полезно для достижения максимальной производительности, но несет риски для безопасности, так как снижается уровень изоляции.
- Создайте контейнер, используя сетевой режим host:
docker run --network host --name host-container -d nginx
- Проверьте текущий список сетей:
docker network ls
Вы не увидите новой сети для этого контейнера, так как он использует сеть хоста напрямую.
- Убедитесь, что контейнер действительно использует сеть хоста:
docker inspect --format '{{.HostConfig.NetworkMode}}' host-container
Команда должна вывести host.
- Попробуйте получить доступ к странице Nginx по умолчанию с вашей хост-машины:
curl localhost:80
Вы должны увидеть приветственную страницу Nginx. Это работает, потому что контейнер использует сеть хоста, и Nginx слушает порт 80 непосредственно на сетевом интерфейсе хоста.
Примечание: Если на вашей хост-машине уже запущен какой-либо сервис на порту 80, этот шаг может завершиться ошибкой. В таком случае сначала необходимо остановить существующий сервис.
Сетевой режим None
Режим 'none' создает контейнеры без сетевого интерфейса, полностью изолируя их от любой сети. Это применяется для обеспечения максимальной безопасности и изоляции, однако такой контейнер не сможет передавать или принимать данные по сети.
- Создайте контейнер без сети:
docker run --network none --name isolated-container -d alpine sleep infinity
- Проверьте список сетей:
docker network ls
Для этого контейнера не будет создано новой сети, так как он ни к чему не подключен.
- Убедитесь, что у контейнера нет сетевых интерфейсов:
docker exec isolated-container ip addr
Вы должны увидеть только локальный интерфейс (lo). Интерфейсы eth0 или другие сетевые адаптеры будут отсутствовать.
- Попробуйте выполнить ping Google из изолированного контейнера:
docker exec isolated-container ping -c 2 google.com
Команда должна завершиться ошибкой "Network is unreachable" (Сеть недоступна), так как у контейнера нет доступа к сети.
Сетевые псевдонимы и обнаружение сервисов
Сети Docker поддерживают обнаружение сервисов (service discovery) с помощью сетевых псевдонимов (aliases), что крайне полезно для создания отказоустойчивых и масштабируемых приложений. Эта функция позволяет нескольким контейнерам отвечать на одно и то же DNS-имя, реализуя базовую балансировку нагрузки.
- Создайте новую мостовую сеть для этого упражнения:
docker network create service-network
- Проверьте создание сети:
docker network ls
Вы должны увидеть service-network в списке.
- Создайте два контейнера с одинаковым сетевым псевдонимом:
docker run -d --network service-network --network-alias myservice --name service1 nginx
docker run -d --network service-network --network-alias myservice --name service2 nginx
- Создайте клиентский контейнер и используйте
nslookupдля разрешения имени сервиса:
docker run --rm --network service-network appropriate/curl nslookup myservice
Вы должны увидеть IP-адреса обоих контейнеров. Это демонстрирует, что встроенный DNS-сервер Docker распределяет запросы между двумя контейнерами.
- Проверьте доступ к сервису несколько раз:
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 мы изучили несколько ключевых концепций:
- Пользовательские мостовые сети для улучшения изоляции и взаимодействия контейнеров.
- Подключение контейнеров к нескольким сетям одновременно.
- Сетевой режим Host для прямого доступа к сетевому стеку хоста.
- Сетевой режим None для полной сетевой изоляции.
- Сетевые псевдонимы и обнаружение сервисов для построения масштабируемых приложений.
Эти продвинутые сетевые возможности Docker предоставляют мощные инструменты для проектирования сложных многоконтейнерных приложений с точным контролем над коммуникациями и безопасностью. Понимание этих принципов критически важно для создания эффективных и защищенных контейнеризированных систем.
Помните, что хотя сетевое взаимодействие в Docker предлагает большую гибкость, при проектировании архитектуры важно учитывать вопросы безопасности. Всегда следуйте принципу наименьших привилегий, открывая только необходимые порты и сервисы.
По мере дальнейшей работы с Docker эти концепции станут неоценимыми при оркестрации сложных приложений и микросервисных архитектур. Регулярно практикуйтесь, чтобы довести навыки управления сетями Docker до совершенства.



