Как получить доступ из одного докер-контейнера в другой докер-контейнер
- четверг, 6 мая 2021 г. в 00:38:05
Цель этой статьи — показать как мы можем сконфигурировать два и более контейнера, чтобы они могли взаимодействовать друг с другом. В этой статье мы сделаем следующее:
Создадим образ Docker используя простой веб-сервис с использованием Python и Flask.
Запустим два отдельных контейнера
Создадим сеть в Docker
Объединим контейнеры используя созданную сеть
Чтобы пойти дальше вы должны обладать средними знаниями в программировании и API. Также понадобится докер инсталлированный локально на вашей машине.
Руководство об основах работы с контейнерами можно найти здесь:
Для этой статьи мы будем использовать два простых веб-сервиса, каждый со своим эндпойнтом. Давайте назовём первый сервис "ping", второй — "pong", а нашим замыслом будет отправка запроса сервисом "ping" к сервису "pong" так, чтобы они могли играть в пинг-понг.
Я использовал Flask и Docker чтобы создать простое приложение и вы можете прочитать больше о тех базовых командах Docker что я использовал, в этом руководстве.
Мы запустим каждый сервис в собственном контейнере и объединим эти контейнеры, используя сеть в Docker.
Наши сервисы - очень простые flask-приложения. В app.py будут наши эндпойнты.
В нашем случае сервис "ping" будет иметь эндпойнт "/ping", который будет отправлять запросы к сервису "pong" в эндпойнт "/pong". Если сервис "pong" недоступен, то он просто вернёт "Ping …”. В противном случае сервис вернёт “Ping … Pong”.
В requirements.txt перечислены все модули, которые мы будем использовать, а в Dockerfile перечислены все шаги, которые помогут нам собрать образ.
Так же, как и сервис "ping", наш сервис "pong" представляет собой flask-приложение и имеет эндпойнт "/pong", как показано ниже.
Сервис "ping" сервис мы запустим на порту 5000, а сервис "pong" на порту 5001.
Сейчас у нас есть два python-сервиса с их Dockerfile. Давайте соберём образы Docker для них.
cd ping-service
docker build -t ping-service .
и
cd pong-service
docker build -t pong-service .
После того как выполним команду docker images
мы должны увидеть два образа:
REPOSITORY TAG IMAGE ID CREATED SIZE
pong-service latest 968a682344de 7 seconds ago 124MB
ping-service latest 6e079525fd69 About a minute ago 128MB
python 3.8-slim-buster b281745b6df9 8 days ago 114MB
Теперь у нас есть образы, давайте создадим из них контейнеры и запустим их.
cd ping-service
docker 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-service
docker run --name pong-service-container -p 5001:5001 pong-service
А сейчас давайте выполним docker container ls
, чтобы посмотреть на созданный контейнеры:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7eb5ee014fb pong-service "python app.py" 13 seconds ago Up 11 seconds 0.0.0.0:5001->5001/tcp pong-service-container
d2331893e5b9 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
.
Без сети наши контейнеры не смогут взаимодействовать друг с другом. Или другими словами, "ping-service-container" не сможет отправить запрос в эндпойнт "/pong" контейнера "pong-service-container".
Мы можем сделать доступным взаимодействие через сеть в Docker посредством следующих шагов:
Создаём сеть
Добавляем контейнеры в сеть
И таким образом всем контейнеры в одной докер-сети могут взаимодействовать между собой через имя контейнера или IP-адрес.
Давайте выполним эти вышеуказанные шаги.
Давайте создадим сеть с именем 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-container
docker 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 во время разработки или в производственном окружении, когда вы бы хотели использовать отдельные контейнеры для разных сервисов — например, базы данных, фронтенда, бэкенда, поиска и т.д.