Введение
Контейнеры Docker стали фундаментальной частью современного разработки и развертывания приложений. При работе с несколькими контейнерами обеспечение правильной связи между ними имеет решающее значение для корректной работы ваших приложений.
В этом практическом занятии вы узнаете, как проверить и устранить проблемы с подключением между контейнерами Docker. Мы начнем с основных концепций контейнеров Docker, настроим контейнеры для тестирования, а затем изучим различные методы проверки и диагностики сетевых подключений между контейнерами.
По завершении этого руководства вы сможете уверенно тестировать, проверять и решать проблемы с подключением в ваших контейнеризованных приложениях.
Для этого практического занятия требуется подключение к Интернету для обучения, поэтому только пользователи Pro могут запустить виртуальную машину. Перейдите к тарифу Pro.
Настройка контейнеров Docker для тестирования
Прежде чем мы сможем протестировать связь между контейнерами, нам нужно создать несколько контейнеров для работы. В этом шаге мы настроим два простых контейнера Docker и узнаем о основных командах Docker.
Общие сведения о контейнерах Docker
Контейнеры Docker - это легковесные автономные пакеты, которые включают все, что нужно для запуска приложения: код, среду выполнения, системные инструменты, библиотеки и настройки. Контейнеры используют ядро операционной системы хост-машины, но работают в изолированных средах.
Создание тестовых контейнеров
Давайте начнем с создания двух простых контейнеров на основе образа Ubuntu. Мы будем использовать эти контейнеры на протяжении всего практического занятия для проверки связи между ними.
Сначала создадим наш первый контейнер:
docker run -d --name container1 ubuntu:22.04 sleep infinity
Теперь создадим второй контейнер:
docker run -d --name container2 ubuntu:22.04 sleep infinity

Пояснение параметров команды:
-d: Запускает контейнер в отсоединенном режиме (в фоновом режиме)--name: Назначает имя контейнеруubuntu:22.04: Docker-образ для использования (версия Ubuntu 22.04)sleep infinity: Команда, которая запускает контейнер на бесконечное время
Проверка запуска контейнеров
Для проверки правильности запуска контейнеров используйте следующую команду:
docker ps
Вы должны увидеть вывод, похожий на этот:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f8d97c645cce ubuntu:22.04 "sleep infinity" 5 seconds ago Up 4 seconds container2
a2c516a57cb8 ubuntu:22.04 "sleep infinity" 18 seconds ago Up 17 seconds container1
Если вы не видите оба контейнера в списке, они, возможно, не запустились правильно. Попробуйте создать их снова.
Установка сетевых инструментов
По умолчанию образ контейнера Ubuntu очень минималистичный и не включает сетевые инструменты, которые нам понадобятся. Установим эти инструменты в обоих контейнерах:
Для контейнера1:
docker exec container1 apt-get update
docker exec container1 apt-get install -y iputils-ping net-tools iproute2 curl
Для контейнера2:
docker exec container2 apt-get update
docker exec container2 apt-get install -y iputils-ping net-tools iproute2 curl
Эти команды:
- Используют
docker execдля выполнения команд внутри запущенного контейнера - Обновляют список пакетов с помощью
apt-get update - Устанавливают сетевые инструменты (
iputils-pingдля проверки соединения,net-toolsдля netstat,iproute2для ip-команд иcurl)
Теперь наши контейнеры готовы к проверке связи в следующих шагах.
Общие сведения о сетях Docker
Контейнеры Docker общаются друг с другом через сети. Для тестирования и устранения проблем с подключением между контейнерами необходимо понимать, как работает сетевое взаимодействие Docker.
Основы сетей Docker
При установке Docker автоматически создаются несколько стандартных сетей. Чаще всего используются следующие:
bridge: Стандартная сеть, к которой подключаются контейнеры, если не указана другая сетьhost: Контейнеры напрямую используют сеть хоста (без изоляции)none: Контейнеры не имеют доступа к сети
Проверим сети на вашей системе:
docker network ls
Вы должны увидеть вывод, похожий на этот:
NETWORK ID NAME DRIVER SCOPE
1b95853bf83b bridge bridge local
91199fc6ad2e host host local
1078d2c781b6 none null local
Общие сведения о стандартной сети bridge
По умолчанию оба наших контейнера подключены к стандартной сети bridge. Проверим эту сеть:
docker network inspect bridge
Эта команда выводит подробную информацию о сети bridge, включая контейнеры, подключенные к ней, и их IP-адреса. В выводе найдите раздел "Containers", чтобы увидеть, что в нем перечислены оба контейнера1 и контейнер2 с их IP-адресами.
Поиск IP-адресов контейнеров
Для работы с подключением контейнеров нам нужно знать IP-адреса, назначенные нашим контейнерам. Есть несколько способов получить эту информацию:
Используя docker inspect:
docker inspect --format='{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1
Или изнутри контейнера:
docker exec container1 hostname -i
Запишите IP-адреса обоих контейнеров:
docker exec container1 hostname -i
docker exec container2 hostname -i
Вывод покажет IP-адрес каждого контейнера, который обычно начинается с 172.17.0.x на стандартной сети bridge.
Создание пользовательской сети Docker
Хотя стандартная сеть bridge позволяет контейнерам общаться, создание пользовательской сети обеспечивает лучшую изоляцию и встроенное разрешение DNS (контейнеры могут обращаться друг к другу по имени, а не по IP).
Создадим пользовательскую сеть bridge:
docker network create --driver bridge my-network
Теперь подключим наши существующие контейнеры к этой новой сети:
docker network connect my-network container1
docker network connect my-network container2
Мы можем проверить, что контейнеры подключены к новой сети:
docker network inspect my-network
Теперь наши контейнеры подключены как к стандартной сети bridge, так и к нашей пользовательской сети my-network. В следующем шаге мы протестируем связь между ними.
Тестирование базовой связи между контейнерами
Теперь, когда наши контейнеры настроены и подключены к сетям, мы можем протестировать связь между ними. Мы используем несколько методов, чтобы проверить, могут ли контейнеры общаться друг с другом.
Использование ping для проверки связи
Самый простой способ проверить базовое сетевое взаимодействие - это использовать команду ping, которая отправляет запросы эхо ICMP на целевой хост.
Попробуем отправить ping из контейнера1 в контейнер2 по IP-адресу:
## Сначала получим IP-адрес контейнера2
CONTAINER2_IP=$(docker exec container2 hostname -i)
echo "IP-адрес контейнера2: $CONTAINER2_IP"
## Получим первый IP-адрес из CONTAINER2_IP
CONTAINER2_IP=$(echo $CONTAINER2_IP | cut -d' ' -f1)
echo "IP-адрес контейнера2: $CONTAINER2_IP"
## Теперь отправим ping из контейнера1 в контейнер2
docker exec container1 ping -c 4 $CONTAINER2_IP
Вы должны увидеть вывод, похожий на этот:
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.095 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.087 ms
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.067/0.085/0.095/0.000 ms
Тестирование разрешения DNS
Одним из преимуществ пользовательских сетей Docker является то, что они обеспечивают автоматическое разрешение DNS, позволяя контейнерам обращаться друг к другу по имени.
Протестируем разрешение DNS, отправив ping по имени контейнера:
docker exec container1 ping -c 4 container2
Это должно работать, потому что оба контейнера находятся на нашей пользовательской сети my-network, которая обеспечивает разрешение DNS. Вы должны увидеть ответы ping, похожие на предыдущий тест, но используя имя контейнера вместо IP-адреса.
Использование curl для проверки HTTP-связи
Для приложений, которые запускают веб-сервисы, часто нужно проверить HTTP-связь. Создадим простой HTTP-сервер в контейнере2 и протестируем связь с ним из контейнера1.
Сначала запустим базовый HTTP-сервер в контейнере2:
docker exec container2 apt-get install -y python3
docker exec -d container2 bash -c "echo 'Hello from container2' > /index.html && cd / && python3 -m http.server 8080"
Подождите несколько секунд, пока сервер запустится, затем протестируйте соединение из контейнера1:
docker exec container1 curl -s http://container2:8080
Вы должны увидеть вывод:
Hello from container2
Это подтверждает, что контейнер1 может подключиться к HTTP-сервису контейнера2, используя имя контейнера для разрешения DNS.
Тестирование соединения с использованием различных методов
Также полезно знать, как проверить связь с использованием других инструментов. Попробуем использовать nc (netcat), чтобы проверить, открыт ли определенный порт:
## Убедитесь, что netcat установлен в контейнере1
docker exec container1 apt-get install -y netcat
## Протестируем связь с HTTP-сервером на контейнере2
docker exec container1 nc -zv container2 8080
Вы должны увидеть вывод, указывающий на успешное соединение:
Connection to container2 (172.18.0.3) 8080 port [tcp/*] succeeded!
Эти тесты подтверждают, что наши контейнеры могут общаться друг с другом как на уровне сети (ping), так и на уровне приложения (HTTP).
Решение проблем с подключением контейнеров
Если у вас нет проблем с подключением, вы можете пропустить этот шаг.
Теперь, когда мы знаем, как тестировать связь между контейнерами, давайте изучим, как устранять общие проблемы с подключением.
Общие проблемы с подключением
При работе с сетями контейнеров Docker вы можете столкнуться с несколькими общими проблемами:
- Контейнеры на разных сетях без правильной маршрутизации
- Настройки брандмауэра или безопасности блокируют трафик
- Приложение не слушает ожидаемый IP/порт
- Ошибки в настройке сети
- Проблемы с разрешением DNS
Рассмотрим шаги по устранению каждой из этих потенциальных проблем.
Проверка конфигурации сети
Сначала рассмотрим конфигурацию сети наших контейнеров:
## Просмотр сетевых интерфейсов контейнера1
docker exec container1 ip addr show
## Просмотр сетевых интерфейсов контейнера2
docker exec container2 ip addr show
Вывод показывает все сетевые интерфейсы в каждом контейнере. Каждая подключенная сеть Docker отображается в виде интерфейса eth с назначенным IP-адресом.
Проверка маршрутов сети
Проверим конфигурацию маршрутизации в наших контейнерах:
docker exec container1 route -n
Это показывает таблицу маршрутизации для контейнера1, указывая, куда направляется сетевой трафик.
Проверка слушаемых портов
Для определения, правильно ли приложение слушает соединения, используйте:
docker exec container2 netstat -tuln
Это показывает все TCP и UDP порты, которые слушаются. Наш HTTP-сервер должен слушать порт 8080.
Диагностика с использованием tcpdump
Для более детального анализа сетевого трафика мы можем использовать tcpdump для захвата и анализа пакетов:
## Установить tcpdump в контейнер1
docker exec container1 apt-get install -y tcpdump dnsutils
## Захватить пакеты в течение 10 секунд
docker exec container1 timeout 10 tcpdump -i eth0 -n
Во время выполнения этого откройте другой терминал и сгенерируйте некоторый трафик:
docker exec container1 ping -c 3 container2
В выводе tcpdump вы должны увидеть захваченные пакеты ICMP.
Проверка разрешения DNS в Docker
Если у вас возникают проблемы с разрешением DNS между контейнерами:
## Проверить конфигурацию DNS
docker exec container1 cat /etc/resolv.conf
## Протестировать разрешение DNS
docker exec container1 nslookup container2
Симуляция проблемы сети
Протестируем проблему с подключением, временно отключив контейнер1 от нашей пользовательской сети:
## Отключить контейнер1 от my-network
docker network disconnect my-network container1
## Попробовать отправить ping по имени (это должно завершиться неудачей)
docker exec container1 ping -c 2 container2
Вы должны увидеть, что ping завершается неудачей, потому что контейнер1 не может больше разрешать имя контейнера2 после отключения от общей сети.
Подключим его снова:
## Переподключить контейнер1 к my-network
docker network connect my-network container1
## Проверить, восстановлено ли подключение
docker exec container1 ping -c 2 container2
Теперь ping должен работать снова, демонстрируя, что контейнеры должны находиться на одной сети для правильного разрешения имен.
Чек-лист по устранению неполадок
При возникновении проблем с подключением контейнеров следуйте этому чек-листу:
- Проверить, запущены ли контейнеры:
docker ps - Проверить, находятся ли они на одной сети:
docker network inspect <сеть> - Проверить, назначены ли IP-адреса:
docker inspect <контейнер> - Протестировать базовое подключение (ping):
docker exec <контейнер> ping <целевой> - Проверить, слушает ли приложение:
docker exec <контейнер> netstat -tuln - Проверить, работает ли разрешение DNS:
docker exec <контейнер> nslookup <целевой> - Проверить наличие проблем с брандмауэром:
docker exec <контейнер> iptables -L - Проверить логи контейнера:
docker logs <контейнер>
Систематический подход поможет вам выявить и решить большинство проблем с подключением контейнеров.
Резюме
В этом практическом занятии вы узнали, как тестировать и устранять проблемы с подключением между контейнерами Docker. Вы:
- Создали контейнеры Docker и настроили их для работы с сетью
- Изучили основы сетевого взаимодействия Docker, включая стандартные и пользовательские сети
- Использовали различные инструменты для тестирования базовой связи между контейнерами (ping, curl, netcat)
- Исследовали общие проблемы с подключением и узнали систематические подходы к их устранению
Эти навыки необходимы для разработки и поддержки приложений на основе Docker, особенно в микросервисных архитектурах, где несколько контейнеров должны взаимодействовать друг с другом.
Для дальнейшего обучения вы можете изучить Docker Compose для приложений с несколькими контейнерами, Docker Swarm или Kubernetes для оркестрации контейнеров, а также более продвинутые концепции сети, такие как наложенные сети для развертывания на нескольких узлах.



