Основы Docker: Сети (Networking)
Docker реализует сетевое взаимодействие между контейнерами, а также между контейнерами и хост-машиной, используя драйверы сетей. По умолчанию Docker создает несколько сетей, и вы также можете создавать свои собственные пользовательские сети.
Типы сетей Docker
Docker предоставляет несколько встроенных сетевых драйверов:
bridge(default): Это сетевой драйвер по умолчанию. Когда Docker устанавливается, он создает сетевой мост с именемdocker0. По умолчанию все контейнеры подключаются к этой сети. Контейнеры в одной bridge-сети могут взаимодействовать друг с другом по IP-адресам. Для доступа к портам контейнера извне (с хост-машины или из внешней сети) необходимо выполнить публикацию портов.host: При использовании сетиhostконтейнер напрямую использует сетевой интерфейс хост-машины. Контейнер не получает собственный изолированный сетевой стек. Это означает, что порты, которые прослушивает приложение внутри контейнера, напрямую доступны на хост-машине. Следует быть осторожным при использовании этого драйвера, так как это нарушает изоляцию сети между контейнерами и хостом, а также может привести к конфликтам портов, если несколько контейнеров попытаются использовать один и тот же порт.none: Контейнеры, подключенные к сетиnone, полностью изолированы от внешней сети и других контейнеров. У них есть только интерфейс loopback (lo).macvlan: Позволяет назначать MAC-адреса контейнерам, что делает их видимыми в физической сети как отдельные устройства.overlay: Используется для создания распределенных сетей, которые могут охватывать несколько Docker-хостов. Этот драйвер используется в Docker Swarm для обеспечения сетевого взаимодействия между сервисами, работающими на разных узлах Swarm-кластера.ipvlan: Похож наmacvlan, но работает на уровне IP и MAC-адресов Ethernet link.Пользовательские сети (User-defined networks): Вы можете создавать собственные сети типа
bridge,overlayиmacvlan. Пользовательские сетиbridgeобеспечивают лучшую изоляцию и взаимодействие между контейнерами по имени (DNS-разрешение имен контейнеров внутри сети).
Управление сетями Docker
Вы можете управлять сетями Docker с помощью команды docker network.
Просмотр доступных сетей
docker network lsЭта команда выведет список всех доступных сетей, их ID, имен, драйверов и областей действия.
Создание пользовательской сети
Вы можете создать собственную сеть с определенным драйвером (по умолчанию bridge):
docker network create my-custom-network
docker network create -d bridge another-bridge-network
docker network create -d overlay my-overlay-network # Требуется Docker SwarmПодключение контейнера к сети
При создании контейнера вы можете указать, к какой сети его подключить с помощью флага --network:
docker run --name my-container --network my-custom-network my-imageВы также можете подключить уже запущенный контейнер к сети (или отключить его от сети):
docker network connect my-custom-network my-container
docker network disconnect my-custom-network my-containerПросмотр информации о сети
Чтобы получить подробную информацию о конкретной сети, используйте команду docker network inspect:
docker network inspect my-custom-networkЭта команда выведет JSON-объект с информацией о сети, включая ее конфигурацию, подключенные контейнеры и IP-адреса.
Удаление сети
Вы можете удалить пользовательскую сеть, если она не используется ни одним контейнером:
docker network rm my-custom-networkВзаимодействие между контейнерами
Контейнеры, находящиеся в одной сети (кроме none и host), могут взаимодействовать друг с другом.
В сети bridge по умолчанию (docker0)
Контейнеры могут взаимодействовать по IP-адресам, которые Docker назначает им в этой сети. Однако IP-адреса контейнеров могут меняться при перезапуске, поэтому этот способ не является надежным для постоянного взаимодействия.
В пользовательских сетях bridge
В пользовательских сетях bridge, Docker предоставляет автоматическое DNS-разрешение имен контейнеров. Это означает, что контейнеры могут взаимодействовать друг с другом, используя имена своих контейнеров в качестве хост-имен.
Например, если у вас есть два контейнера с именами web и db в одной пользовательской сети my-network, контейнер web может обращаться к сервису, работающему на контейнере db, используя хост-имя db (и соответствующий порт).
Публикация портов (-p или ports в Docker Compose)
Чтобы сделать сервис, работающий внутри контейнера, доступным с хост-машины или из внешней сети, необходимо опубликовать порты контейнера на порты хост-машины. Это делается с помощью флага -p при запуске контейнера (docker run -p host_port:container_port) или с помощью секции ports в файле docker-compose.yml.
docker run -p 8080:80 nginx # Порт 80 контейнера будет доступен на порту 8080 хостаВ docker-compose.yml:
version: "3.9"
services:
web:
image: nginx:latest
ports:
- "80:80" # Порт 80 контейнера будет доступен на порту 80 хостаПримеры сетевого взаимодействия
Веб-приложение и база данных в одной пользовательской сети
Предположим, у вас есть веб-приложение (работающее в контейнере web) и база данных MySQL (работающая в контейнере db), и вы создали пользовательскую сеть my-app-network.
- Создайте сеть:
docker network create my-app-network - Запустите контейнер базы данных, подключив его к сети:bash
docker run --name db --network my-app-network -e MYSQL_ROOT_PASSWORD=secret -d mysql:latest - Запустите контейнер веб-приложения, подключив его к той же сети:bash
docker run --name web --network my-app-network -p 80:80 -d my-web-app-image
Теперь контейнер web может обращаться к базе данных MySQL, используя хост-имя db и порт MySQL (обычно 3306), без необходимости знать IP-адрес контейнера db. Веб-приложение также доступно на порту 80 хост-машины.
Взаимодействие через опубликованные порты
Если контейнеры находятся в разных сетях или вы хотите получить доступ к сервису контейнера с хост-машины, вы можете использовать опубликованные порты. В этом случае вы будете использовать IP-адрес хост-машины (или localhost, если обращаетесь с той же машины) и опубликованный порт.
Например, если вы запустили контейнер MySQL с публикацией порта -p 3306:3306, вы можете подключиться к нему с хост-машины, используя localhost:3306.
Docker Compose и сети
Docker Compose упрощает управление сетями для многоконтейнерных приложений. По умолчанию Compose создает одну сеть для вашего приложения. Все службы, определенные в одном файле docker-compose.yml, автоматически подключаются к этой сети и могут взаимодействовать друг с другом по именам служб (которые используются как хост-имена).
Вы также можете определять собственные сети в секции networks файла docker-compose.yml и подключать к ним определенные службы.
version: "3.9"
services:
web:
image: nginx:latest
ports:
- "80:80"
networks:
- frontend
- backend
depends_on:
- app
app:
build: ./app
networks:
- backend
environment:
DB_HOST: db
db:
image: mysql:8.0
networks:
- backend
environment:
MYSQL_ROOT_PASSWORD: secret
networks:
frontend:
backend:В этом примере созданы две сети: frontend и backend. Служба web подключена к обеим сетям, служба app и db — только к backend. Это позволяет изолировать сетевой трафик между различными частями приложения. Веб-сервер может взаимодействовать с приложением, а приложение — с базой данных, но прямой доступ к базе данных извне (через сеть frontend) отсутствует.
Понимание сетевого взаимодействия в Docker является важным для построения сложных многоконтейнерных приложений. Использование пользовательских сетей и DNS-разрешения имен контейнеров значительно упрощает взаимодействие между сервисами. Публикация портов позволяет делать сервисы доступными извне.