Пошук уроків, статей та іншого контенту
Налаштуєте взаємодію сервісів через Docker-мережу та підключення за іменами контейнерів.
Контейнери Docker ізольовані, але можуть взаємодіяти через мережу. Для цього їх підключають до спільної Docker-мережі.
У мережі користувача Docker автоматично надає DNS-розв’язання імен контейнерів. Тому один контейнер може звертатися до іншого за його іменем:
http://web:80У цьому прикладі web — ім’я контейнера, а не localhost і не IP-адреса.
localhostlocalhost усередині контейнера вказує на сам цей контейнер.
Якщо контейнер client звертається до:
http://localhost:80він шукає вебсервер усередині client, а не в контейнері web.
Для звернення до іншого контейнера потрібно використовувати його DNS-ім’я в спільній мережі.
Створимо мережу app-net:
docker network create app-netПеревірити список мереж можна командою:
docker network lsКористувацька bridge-мережа ізолює підключені до неї контейнери від контейнерів, які підключені до інших мереж. Водночас усі контейнери в одній мережі можуть взаємодіяти між собою.
Запустимо вебсервер Nginx у мережі app-net:
docker run -d \
--name web \
--network app-net \
nginx:alpineПараметри команди:
-d запускає контейнер у фоновому режимі;
--name web задає ім’я контейнера;
--network app-net підключає контейнер до мережі;
nginx:alpine — образ, з якого створюється контейнер.
Тепер запустимо тимчасовий контейнер-клієнт у тій самій мережі:
docker run --rm \
--network app-net \
alpine:3.20 \
wget -qO- http://webКоманда виведе HTML-сторінку, яку повернув Nginx.
Тут контейнер alpine звертається до web за іменем. Docker знаходить IP-адресу контейнера web через внутрішній DNS-сервер.
Порт 80 не потрібно публікувати на хост, оскільки запит відбувається всередині Docker-мережі.
Наведений сценарій можна виконати послідовно:
docker network create app-net
docker run -d \
--name web \
--network app-net \
nginx:alpine
docker run --rm \
--network app-net \
alpine:3.20 \
wget -qO- http://web
docker rm -f web
docker network rm app-netОстанні дві команди видаляють контейнер і мережу після завершення перевірки.
Публікація порту потрібна, коли доступ до контейнера має відбуватися з хост-системи або ззовні:
docker run -d \
--name web \
--network app-net \
-p 8080:80 \
nginx:alpineПісля цього:
хост звертається до Nginx через http://localhost:8080;
інший контейнер у мережі app-net звертається через http://web:80.
Параметр -p 8080:80 не змінює адресу для інших контейнерів. Вони використовують внутрішній порт сервісу та ім’я контейнера.
Якщо сервіс потрібен лише іншим контейнерам, публікувати його порт не обов’язково:
docker run -d \
--name web \
--network app-net \
nginx:alpineКонтейнер можна підключити до мережі після його запуску:
docker run -d \
--name web \
nginx:alpine
docker network connect app-net webПісля docker network connect контейнер web стає доступним іншим контейнерам у мережі app-net за своїм іменем.
Від’єднати контейнер від мережі можна так:
docker network disconnect app-net webІнформацію про мережу можна отримати командою:
docker network inspect app-netУ результаті можна побачити:
підключені контейнери;
їхні IP-адреси в цій мережі;
параметри мережі;
мережеві діапазони.
Список мереж контейнера показує команда:
docker inspect webЩоб отримати лише назви підключених мереж:
docker inspect \
--format '{{json .NetworkSettings.Networks}}' \
webДля контейнера можна задати додаткове ім’я в конкретній мережі:
docker run -d \
--name web \
--network app-net \
--network-alias api \
nginx:alpineТепер інші контейнери в app-net можуть звертатися до цього самого контейнера за іменами:
web
apiНаприклад:
docker run --rm \
--network app-net \
alpine:3.20 \
wget -qO- http://apiПсевдонім особливо корисний, коли ім’я контейнера є технічним, а сервіс має зрозуміле логічне ім’я.
Контейнер може бути підключений до кількох мереж. Це дає змогу розділити групи сервісів.
Наприклад, створимо дві мережі:
docker network create frontend
docker network create backendЗапустимо вебконтейнер у frontend:
docker run -d \
--name web \
--network frontend \
nginx:alpineПідключимо той самий контейнер також до backend:
docker network connect backend webТепер web має мережевий інтерфейс у кожній із двох мереж.
Інший контейнер, підключений лише до backend, зможе взаємодіяти з web, але не матиме доступу до контейнерів, які існують тільки у frontend.
Після завершення прикладу мережі можна видалити:
docker rm -f web
docker network rm frontend backendbridgeDocker створює стандартну мережу з назвою bridge. Контейнер можна запустити в ній без параметра --network:
docker run -d \
--name web \
nginx:alpineПроте для взаємодії сервісів краще створювати окрему користувацьку мережу через docker network create.
Користувацькі bridge-мережі мають автоматичне DNS-розв’язання імен контейнерів. Це дозволяє використовувати стабільні імена замість IP-адрес, які можуть змінюватися після пересоздання контейнера.
Створити окрему мережу:
docker network create app-netЗапустити сервіси з параметром --network:
docker run -d --name web --network app-net nginx:alpineЗ іншого контейнера звертатися до сервісу за іменем:
http://web:80Публікувати порт через -p лише тоді, коли сервіс має бути доступним із хоста або зовнішньої мережі.
localhost для іншого контейнераНеправильно:
http://localhost:80Якщо запит виконується з контейнера-клієнта, localhost вказує на нього самого.
Правильно:
http://web:80Якщо один контейнер працює в frontend, а інший — у backend, вони не зможуть звертатися один до одного за іменами.
Перевірити мережі можна так:
docker inspect web
docker inspect clientIP-адреса контейнера може змінитися після його видалення та повторного запуску. Для взаємодії використовуйте ім’я контейнера або мережевий псевдонім.
Якщо запущено контейнер із параметром:
-p 8080:80то:
з хоста використовується порт 8080;
з іншого контейнера в тій самій мережі використовується порт 80.
Запит між контейнерами має вигляд:
http://web:80а не:
http://web:8080Ім’я контейнера буде доступним лише після того, як контейнер підключений до відповідної мережі. Якщо сервіс ще не запущений або був видалений, DNS-ім’я не приведе до працюючого застосунку.
Контейнери взаємодіють через спільну Docker-мережу.
Для сервісів варто створювати користувацьку мережу через docker network create.
У межах такої мережі контейнери доступні за іменами.
localhost усередині контейнера означає цей самий контейнер.
Для запитів між контейнерами не потрібна публікація портів через -p.
Порт публікують, коли до сервісу потрібно звертатися з хоста або ззовні.
IP-адреси контейнерів не варто використовувати як постійні адреси.
Стан мережі та підключених контейнерів можна перевірити через docker network inspect.