Цель этой статьи показать как мы можем сконфигурировать два и более контейнеров, чтобы они могли взаимодействовать друг с другом. В этой статье мы сделаем следующее:
-
Создадим образ Docker используя простой веб-сервис с использованием Python и Flask.
-
Запустим два отдельных контейнера
-
Создадим сеть в Docker
-
Объединим контейнеры используя созданную сеть
Подготовка
Чтобы пойти дальше вы должны обладать средними знаниями в программировании и API. Также понадобится докер инсталлированный локально на вашей машине.
Руководство об основах работы с контейнерами можно найти здесь:
Идея
Для этой статьи мы будем использовать два простых веб-сервиса, каждый со своим эндпойнтом. Давайте назовём первый сервис "ping", второй "pong", а нашим замыслом будет отправка запроса сервисом "ping" к сервису "pong" так, чтобы они могли играть в пинг-понг.
Я использовал Flask и Docker чтобы создать простое приложение и вы можете прочитать больше о тех базовых командах Docker что я использовал, в этом руководстве.
Мы запустим каждый сервис в собственном контейнере и объединим эти контейнеры, используя сеть в Docker.
Фото от https://unsplash.com/@ellenqinСервис "ping"
Наши сервисы - очень простые flask-приложения. В app.py будут наши эндпойнты.
В нашем случае сервис "ping" будет иметь эндпойнт "/ping", который будет отправлять запросы к сервису "pong" в эндпойнт "/pong". Если сервис "pong" недоступен, то он просто вернёт "Ping . В противном случае сервис вернёт Ping Pong.
В requirements.txt перечислены все модули, которые мы будем использовать, а в Dockerfile перечислены все шаги, которые помогут нам собрать образ.
Сервис "pong"
Так же, как и сервис "ping", наш сервис "pong" представляет собой flask-приложение и имеет эндпойнт "/pong", как показано ниже.
Сервис "ping" сервис мы запустим на порту 5000, а сервис "pong" на порту 5001.
Собираем образы Docker
Source: https://www.metricfire.com/blog/how-to-build-optimal-docker-images/Сейчас у нас есть два python-сервиса с их Dockerfile. Давайте соберём образы Docker для них.
cd ping-servicedocker build -t ping-service .
и
cd pong-servicedocker build -t pong-service .
После того как выполним команду docker images
мы
должны увидеть два образа:
REPOSITORY TAG IMAGE ID CREATED SIZEpong-service latest 968a682344de 7 seconds ago 124MBping-service latest 6e079525fd69 About a minute ago 128MBpython 3.8-slim-buster b281745b6df9 8 days ago 114MB
Запуск контейнеров
Теперь у нас есть образы, давайте создадим из них контейнеры и запустим их.
cd ping-servicedocker run --name ping-service-container -p 5000:5000 ping-service
И ожидаемый вывод в консоль будет подобен следующему:
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 761-609-740
Если мы выполним команду curl http://0.0.0.0:5000
мы должны получить вывод сообщения Hello, I am ping
service!
Теперь давайте запустим контейнер для сервиса "pong":
cd pong-servicedocker run --name pong-service-container -p 5001:5001 pong-service
А сейчас давайте выполним docker container ls
,
чтобы посмотреть на созданный контейнеры:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESd7eb5ee014fb pong-service "python app.py" 13 seconds ago Up 11 seconds 0.0.0.0:5001->5001/tcp pong-service-containerd2331893e5b9 ping-service "python app.py" 3 minutes ago Up 3 minutes 0.0.0.0:5000->5000/tcp ping-service-container
Мы видим, что у нас теперь есть два контейнера с именами
pong-service-container
иping-service-container
.
Настраиваем сеть в Docker
Без сети наши контейнеры не смогут взаимодействовать друг с другом. Или другими словами, "ping-service-container" не сможет отправить запрос в эндпойнт "/pong" контейнера "pong-service-container".
Мы можем сделать доступным взаимодействие через сеть в Docker посредством следующих шагов:
-
Создаём сеть
-
Добавляем контейнеры в сеть
И таким образом всем контейнеры в одной докер-сети могут взаимодействовать между собой через имя контейнера или IP-адрес.
Давайте выполним эти вышеуказанные шаги.
Создаём сеть в Docker
Давайте создадим сеть с именем
ping-pong-network
docker network create ping-pong-network
и когда мы выполним команду docker network inspect
ping-pong-network
, мы получим:
TheDarkSide:pong-service raf$ docker network inspect ping-pong-network[ { "Name": "ping-pong-network", "Id": "b496b144d72d9d02795eb0472351b093d6b4f1d0015a37e1525d4d163e7ec532", "Created": "2021-04-18T22:16:25.2399196Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.25.0.0/16", "Gateway": "172.25.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} }]
И как говорилось выше, это сеть без контейнеров и мы можем пойти дальше и добавить запущенные контейнеры в эту сеть, используя следующие команды:
docker network connect ping-pong-network ping-service-containerdocker network connect ping-pong-network pong-service-container
И если теперь запустим инспектирование сети(docker network
inspect ping-pong-network)
, то в секции
Containers
мы увидим наши контейнеры:
"Containers": { "d2331893e5b9dad95a2691b81c256a9f07d4bf62c10601115483d45f8d7b8e2a": { "Name": "ping-service-container", "EndpointID": "3a9e8eea9802602652719461681d3ad4bc7c603697bc1c1b027e35876fdddad7", "MacAddress": "02:42:ac:19:00:02", "IPv4Address": "172.25.0.2/16", "IPv6Address": "" }, "d7eb5ee014fbdb850a19ebb216a56f8b7ebd10db62af197d2d17f5be30ee0210": { "Name": "pong-service-container", "EndpointID": "901ba7f76df59498bd662742536ee31a56a26cc4eedd35d4bd681c9788be5291", "MacAddress": "02:42:ac:19:00:03", "IPv4Address": "172.25.0.3/16", "IPv6Address": "" } }
И как было сказано выше, контейнеры могут взаимодействовать друг с другом используя имя контейнера или IPv4 адрес.
Проверяем взаимодействие контейнеров
Когда оба сервиса "ping" и "pong" будут объединены общей сетью, то запрос к эндпойнту "/ping" сервиса "ping":
TheDarkSide:pong-service raf$ curl http://0.0.0.0:5000/ping
нам вернёт:
Ping ... Pong
Для тестирования остановим один из контейнеров и затем проведём инспекцию сети. Мы должны будем увидеть только один контейнер.
Видео руководство
Кому лень читать, кто больше любит видео и сюда пролистал "по диагонали", может посмотреть это руководство в формате видео.
Заключение
Контейнеры в одной докер-сети могут взаимодействовать используя свой IP адрес или имя контейнера.
Это удобно при использовании Docker во время разработки или в производственном окружении, когда вы бы хотели использовать отдельные контейнеры для разных сервисов например, базы данных, фронтенда, бэкенда, поиска и т.д.