Введение
В рамках этой лабораторной работы мы изучим фундаментальные аспекты сетевого взаимодействия в Docker. Сети Docker позволяют контейнерам обмениваться данными друг с другом и с внешним миром. Мы рассмотрим различные типы сетей, научимся создавать собственные сети, подключать к ним контейнеры и управлять сетевыми конфигурациями. Этот практический опыт заложит прочный фундамент для понимания концепций и методов работы с сетями в экосистеме Docker.
Понимание типов сетей Docker
Docker предоставляет несколько встроенных сетевых драйверов. Начнем с изучения стандартных сетей, которые уже присутствуют в вашей системе.
В терминале выполните следующую команду, чтобы вывести список всех доступных сетей Docker:
docker network ls
Эта команда отображает все сети, созданные Docker в вашей системе. Вы должны увидеть вывод, похожий на этот:
NETWORK ID NAME DRIVER SCOPE
79dce413aafd bridge bridge local
91199fc6ad2e host host local
1078d2c781b6 none null local
Разберем основные типы сетей:
bridge: Это сетевой драйвер по умолчанию. Если вы запускаете контейнер, не указывая сеть, он автоматически подключается к сети типа bridge. Контейнеры в одной сети bridge могут взаимодействовать друг с другом, используя свои IP-адреса.host: Этот драйвер убирает сетевую изоляцию между контейнером и хостом Docker. Контейнер использует сетевое пространство имен хоста напрямую, что означает использование IP-адреса и портов хоста. Это бывает полезно для оптимизации производительности в определенных сценариях.none: Этот драйвер полностью отключает сетевое взаимодействие для контейнера. Контейнеры с таким типом сети не имеют доступа к внешним сетям или другим контейнерам. Это полезно, когда требуется максимальная изоляция.
Столбец SCOPE указывает, ограничена ли сеть одним хостом (local) или может охватывать несколько хостов в кластере Docker Swarm (swarm).
Инспекция стандартной сети Bridge
Теперь, когда мы увидели список сетей, давайте подробнее изучим стандартную сеть bridge. Она создается Docker автоматически и используется всеми контейнерами, если не указано иное.
Выполните следующую команду для детального осмотра сети bridge:
docker network inspect bridge
Эта команда предоставляет подробную информацию о сети, включая ее подсеть, шлюз и подключенные контейнеры. Вы увидите вывод в формате JSON, похожий на этот (сокращено для краткости):
[
{
"Name": "bridge",
"Id": "79dce413aafdd7934fa3c1d0cc97decb823891ce406442b7d51be6126ef06a5e",
"Created": "2024-08-22T09:58:39.747333789+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
Разберем ключевые параметры из этого вывода:
Subnet: Подсеть, используемая контейнерами в этой сети —172.17.0.0/16. Это означает, что контейнерам будут назначаться IP-адреса из этого диапазона.Gateway: Шлюз для этой сети —172.17.0.1. Это IP-адрес, который контейнеры используют для связи с внешними сетями.Containers: Это поле сейчас пустое, так как мы еще не запустили ни одного контейнера.Options: Различные параметры конфигурации. Например,enable_iccсо значением "true" означает, что межоболочечное взаимодействие (inter-container communication) разрешено.
Понимание этой информации критически важно при поиске сетевых неисправностей или при необходимости настроить взаимодействие контейнеров с конкретными диапазонами IP-адресов.
Создание пользовательской сети Bridge
Хотя стандартная сеть bridge подходит для многих задач, создание собственных сетей обеспечивает лучшую изоляцию и контроль. Пользовательские сети особенно полезны, когда нужно сгруппировать связанные контейнеры или ограничить круг контейнеров, которые могут общаться друг с другом.
Давайте создадим собственную сеть типа bridge под названием my-network:
docker network create --driver bridge my-network
Эта команда создает новую сеть. Флаг --driver bridge здесь не является обязательным, так как bridge используется по умолчанию, но мы указали его для наглядности.
Теперь проверим, что наша новая сеть появилась в системе:
docker network ls
Вы должны увидеть my-network в списке:
NETWORK ID NAME DRIVER SCOPE
1191cb61c989 bridge bridge local
91199fc6ad2e host host local
47ac4e684a72 my-network bridge local
1078d2c781b6 none null local
Появление my-network в списке подтверждает успешное создание. Теперь эта сеть готова для подключения контейнеров.
Подключение контейнеров к сетям
Теперь, когда у нас есть пользовательская сеть, давайте создадим два контейнера и подключим их к ней. В качестве примера мы будем использовать образ nginx — легкий веб-сервер.
Выполните следующие команды для создания двух контейнеров:
docker run -d --name container1 --network my-network nginx
docker run -d --name container2 --network my-network nginx
Разберем используемые флаги:
-d: Запускает контейнер в фоновом режиме (detached mode).--name: Присваивает контейнеру имя для удобства обращения к нему.--network: Указывает, к какой сети должен подключиться контейнер.nginx: Имя образа, на основе которого создаются контейнеры.
Эти команды создают два фоновых контейнера с именами container1 и container2, оба подключены к нашей сети my-network.
Убедимся, что контейнеры запущены и подключены:
docker ps
Эта команда выводит список всех запущенных контейнеров:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1234567890ab nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp container2
abcdef123456 nginx "/docker-entrypoint.…" 20 seconds ago Up 19 seconds 80/tcp container1
Как видно из вывода, оба контейнера работают на базе образа Nginx и прослушивают порт 80 внутри себя.
Тестирование связи между контейнерами
Одним из главных преимуществ сетей Docker является то, что контейнеры в одной сети могут общаться друг с другом, используя свои имена в качестве имен хостов (hostnames). Это упрощает настройку взаимодействия между сервисами, так как вам не нужно знать их динамические IP-адреса.
Проверим это, отправив запрос из container1 к container2:
docker exec container1 curl -s container2
Разбор команды:
docker exec: Позволяет выполнить команду внутри запущенного контейнера.container1: Имя контейнера, внутри которого мы запускаем команду.curl -s container2: Сама команда. Она отправляет GET-запрос кcontainer2, а флаг-s(silent) скрывает лишнюю служебную информацию.
В результате вы должны увидеть HTML-код стандартной приветственной страницы Nginx:
<!doctype html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark;
}
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
</p>
<p>
For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br />
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.
</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Успешный ответ подтверждает, что container1 может связаться с container2 по его имени. Встроенный DNS-сервер Docker автоматически разрешает имя контейнера в его IP-адрес внутри сети.
Проброс портов контейнера
По умолчанию контейнеры в пользовательской сети могут общаться между собой, но они недоступны извне хоста Docker. Чтобы сделать контейнер доступным для хоста или внешних сетей, нам нужно «пробросить» (экспонировать) его порты.
Создадим новый контейнер с открытым портом:
docker run -d --name exposed-container -p 8080:80 --network my-network nginx
Разбор команды:
-d: Запуск в фоновом режиме.--name exposed-container: Имя контейнера.-p 8080:80: Сопоставление порта 80 внутри контейнера с портом 8080 на хост-машине.--network my-network: Подключение к нашей сети.nginx: Используемый образ.
Теперь вы можете получить доступ к серверу Nginx этого контейнера прямо с вашей хост-машины, открыв браузер по адресу http://localhost:8080 или воспользовавшись curl:
curl localhost:8080
Вы увидите тот же HTML-код приветствия Nginx. Однако на этот раз мы обращаемся к контейнеру напрямую с хоста, а не из другого контейнера.
Использование хост-сети (Host Networking)
В сценариях, где требуется, чтобы контейнер разделял сетевой стек хоста, можно использовать драйвер host. Это убирает сетевую изоляцию, что полезно для некоторых высокопроизводительных приложений, но требует осторожности из-за возможных конфликтов портов.
Создадим контейнер с использованием хост-сети:
docker run -d --name host-networked --network host nginx
Обратите внимание, что при использовании --network host флаг -p не применяется, так как контейнер уже использует сетевые интерфейсы хоста напрямую.
Чтобы убедиться, что контейнер использует хост-сеть, проверим его настройки:
docker inspect --format '{{.HostConfig.NetworkMode}}' host-networked
Команда должна вывести host.
В этом режиме контейнер имеет тот же IP-адрес, что и хост. Это максимизирует производительность, но любые порты, которые открывает приложение в контейнере, открываются непосредственно на хосте.
Резюме
В ходе этой лабораторной работы мы изучили основы сетевого взаимодействия в Docker. Мы рассмотрели различные типы сетей, научились создавать пользовательские сети, подключать к ним контейнеры, проверять связь между ними, пробрасывать порты и использовать хост-режим. Эти концепции являются фундаментом для проектирования и управления контейнеризированными приложениями.
Мы научились:
- Выводить список и инспектировать сети Docker.
- Создавать пользовательские мостовые (bridge) сети.
- Подключать контейнеры к сетям.
- Тестировать связь между контейнерами по их именам.
- Открывать доступ к портам контейнера для хост-системы.
- Использовать режим host для сетевого взаимодействия.
Понимание этих принципов поможет вам создавать более надежные и безопасные приложения. По мере углубления в Docker вы столкнетесь с более сложными сетевыми сценариями, но знания, полученные здесь, станут надежной базой для изучения оркестрации контейнеров и микросервисной архитектуры.
Помните, что сети Docker — это мощный инструмент, позволяющий изолировать среды приложений, сохраняя при этом контролируемую связь между компонентами и внешним миром. Практикуйтесь и изучайте продвинутые темы, чтобы стать экспертом в управлении сетями Docker.



