Перейти к основному содержимому

7.06. Сеть в контейнерах

Разработчику Архитектору Инженеру

Сеть в контейнерах

Другой важной темой для особенностей контейнеров является сеть.

Взаимодействие между контейнерами часто требует создания пользовательских сетей Docker, которые обеспечивают безопасное и надежное соединение между сервисами. По умолчанию Docker предоставляет несколько типов сетей, таких как bridge, host и none, однако для более сложных сценариев рекомендуется создавать собственные сети с использованием команды docker network create. Например, команда docker network create my_custom_network создает новую сеть с именем my_custom_network. После этого контейнеры могут быть подключены к этой сети с помощью флага --network при запуске, например: docker run -d --network=my_custom_network <image_name>.

Пользовательские сети позволяют контейнерам взаимодействовать друг с другом по имени, что значительно упрощает конфигурацию сервисов. Например, если два контейнера подключены к одной сети, они могут обращаться друг к другу по имени контейнера, которое автоматически регистрируется в DNS Docker. Это особенно важно для микросервисной архитектуры, где различные сервисы должны обмениваться данными без прямой зависимости от IP-адресов.

Docker предоставляет несколько типов виртуальных сетей, которые позволяют организовать взаимодействие между контейнерами и внешним миром. Bridge (мостовая сеть) - тип сети, создаваемый Docker по умолчанию. Эта сеть называется docker0 - контейнеры, подключённые к этой сети, получают IP-адреса из внутреннего пула (например, 172.17.0.x). Это подходит для изоляции контейнеров друг от друга. Для доступа к контейнерам извне используется проброс портов (-p).

Пример:

docker run -d --name my-app -p 8080:80 nginx

Здесь порт 80 контейнера проброшен на порт 8080 хоста.

Host (хостовая сеть) используется контейнером напрямую, без изоляции. Это увеличивает производительность, но снижает безопасность и не требует проброса портов:

docker run -d --network host my-app

Overlay (наложенная сеть) используется в распределённых системах (Docker Swarm, например) и позволяет контейнерам на разных хостах взаимодествовать через виртуальную сеть. Это подходит для микросервисной архитектуры, но требует настройки оркестратора. Пример:

docker network create -d overlay my-overlay-network

None (без сети) - контейнер полностью изолирован от сети, и нет доступа к внешнему миру. Пример:

docker run -d --network none my-app

Docker позволяет создавать собственные сети для лучшей организации контейнеров.

При создании сети используется команда network create:

docker network create my-bridge-network

Далее можно просто подключать контейнеры к сети:

docker run -d --name app1 --network my-bridge-network nginx
docker run -d --name app2 --network my-bridge-network mysql

В таком случае, контейнеры app1 и app2 будут находиться в одной сети и смогут взаимодействовать друг с другом по имени (DNS-разрешение). Если же контейнер уже запущен, можно его подключить к другой сети через network connect:

docker network connect my-bridge-network existing-container

Соответственно disconnect - отключение контейнера от сети.

Проброс портов позволяет сделать сервисы, работающие внутри контейнера, доступными извне. Синтаксис таков:

-p <хост_порт>:<контейнер_порт>

К примеру, если выполнить команду:

docker run -d -p 8080:80 nginx

…то сервис будет доступен по адресу http://localhost:8080.

Для взаимодействия между контейнерами в рамках одной сети используется DNS-разрешение имён - Docker автоматически настраивает DNS, чтобы контейнеры могли обращаться друг к другу по имени. Раньше использовалась опция --link (линковка контейнеров), но сейчас она считается устаревшей. Вместо неё рекомендуется использовать пользовательские сети.

Для просмотра сетей, нужно выполнить команду docker network ls.

По умолчанию, Docker использует NAT (Network Address Translation) для маршрутизации трафика между контейнерами и хостом. Это обеспечивает изоляцию контейнеров. Важно также отметить, что контейнер может быть подключен к нескольким сетям одновременно, и что Docker поддерживает IPv6 (но для этого нужно явно включить его в конфигурации Docker).

В Docker Desktop (Mac/Windows), используется host.docker.internal - специальное имя для доступа к хосту из контейнера. На Linux host.docker.internal недоступно по умолчанию, и используется IP хоста.