Сети Docker: базовая настройка связи между контейнерами
Практическая работа с сетями Docker: создание пользовательской сети, подключение контейнеров, DNS по имени сервиса и использование в Docker Compose.
Контейнеры Docker могут обмениваться данными через виртуальные сети. Для приложений из нескольких контейнеров удобнее создавать отдельные пользовательские сети, чем использовать стандартную сеть bridge.
В этой инструкции рассматриваются только базовые операции с сетями Docker: создание, подключение контейнеров, проверка связи и использование в Docker Compose.
Проверено на: Ubuntu Server 24.04 LTS и Docker Engine
Уровень сложности: начальный
Время выполнения: около 15 минут
Требуемый доступ: пользователь с доступом к Docker
Что будет рассмотрено
После выполнения инструкции можно будет:
- просматривать существующие сети;
- создавать пользовательские bridge-сети;
- подключать к ним контейнеры;
- обращаться к контейнерам по имени;
- публиковать порты на хосте;
- описывать сети в Docker Compose;
- разделять сервисы по нескольким сетям;
- удалять неиспользуемые сети.
Просмотр существующих сетей
docker network ls
Обычно Docker создаёт стандартные сети:
bridge
host
none
Подробная информация о сети:
docker network inspect bridge
Создание пользовательской сети
Создайте сеть:
docker network create app-network
Проверьте:
docker network ls
Посмотрите параметры:
docker network inspect app-network
По умолчанию будет создана сеть с драйвером bridge.
Запуск контейнера в сети
Запустите Nginx:
docker run -d \
--name web \
--network app-network \
nginx:alpine
Проверьте контейнер:
docker ps
Посмотрите его сетевые параметры:
docker inspect \
--format '{{json .NetworkSettings.Networks}}' \
web
Проверка связи по имени контейнера
Запустите временный контейнер в той же сети:
docker run --rm \
--network app-network \
busybox \
ping -c 3 web
Контейнер web доступен по собственному имени благодаря встроенному DNS Docker.
Проверьте DNS-разрешение:
docker run --rm \
--network app-network \
busybox \
nslookup web
Проверка HTTP:
docker run --rm \
--network app-network \
alpine \
sh -c 'apk add --no-cache curl >/dev/null && curl -I http://web'
Ожидаемый ответ:
HTTP/1.1 200 OK
Почему не нужен фиксированный IP
IP-адрес контейнера может измениться после пересоздания.
Проверить текущий IP:
docker inspect \
--format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
web
Для связи между контейнерами используйте DNS-имя:
http://web
а не фиксированный IP-адрес.
Просмотр участников сети
docker network inspect app-network
В разделе Containers отображаются подключённые контейнеры.
Краткий вывод:
docker network inspect app-network \
--format '{{json .Containers}}'
Публикация порта на хосте
Связь внутри сети не требует публикации порта. Чтобы открыть Nginx на хосте, контейнер нужно пересоздать с параметром -p.
Удалите тестовый контейнер:
docker rm -f web
Запустите снова:
docker run -d \
--name web \
--network app-network \
-p 8080:80 \
nginx:alpine
Проверьте с хоста:
curl -I http://127.0.0.1:8080
Параметр:
8080:80
означает:
порт 8080 хоста → порт 80 контейнера
Внутренняя и внешняя доступность
Без секции публикации портов:
- сервис доступен другим контейнерам в той же сети;
- сервис не публикуется на интерфейсы хоста.
С опубликованным портом:
- сервис доступен через порт хоста;
- внешний доступ дополнительно зависит от firewall и сетевых правил.
Базы данных и внутренние API не следует публиковать наружу без необходимости.
Подключение работающего контейнера
Создайте контейнер без нужной сети:
docker run -d \
--name client \
alpine \
sh -c 'while true; do sleep 3600; done'
Подключите его:
docker network connect app-network client
Проверьте:
docker inspect \
--format '{{json .NetworkSettings.Networks}}' \
client
Отключение контейнера от сети
docker network disconnect app-network client
Проверьте список участников:
docker network inspect app-network
Добавление сетевого alias
Подключите контейнер с дополнительным DNS-именем:
docker network connect \
--alias frontend \
app-network \
client
Проверьте alias:
docker run --rm \
--network app-network \
busybox \
nslookup frontend
Использование сети в Docker Compose
Создайте каталог проекта:
mkdir -p ~/docker-network-example
cd ~/docker-network-example
Создайте файл compose.yaml:
cat >compose.yaml <<'EOF'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
networks:
- frontend
client:
image: alpine
command:
- sh
- -c
- while true; do sleep 3600; done
networks:
- frontend
networks:
frontend:
driver: bridge
EOF
Проверьте конфигурацию:
docker compose config
Запустите:
docker compose up -d
Проверьте:
docker compose ps
Проверка связи в Compose
Сервис доступен по имени, указанному в services.
Проверьте:
docker compose exec client \
ping -c 3 web
Проверка HTTP:
docker compose exec client \
wget -S -O /dev/null http://web
Адрес сервиса внутри сети:
http://web
Публиковать порт web для доступа из client не требуется.
Автоматическая сеть Compose
Если явно не указывать networks, Docker Compose создаст для проекта общую сеть по умолчанию.
Пример:
services:
web:
image: nginx:alpine
client:
image: alpine
command:
- sh
- -c
- while true; do sleep 3600; done
Оба сервиса будут подключены к одной сети проекта и смогут обращаться друг к другу по именам web и client.
Разделение сервисов по сетям
Пример с отдельными frontend- и backend-сетями:
services:
proxy:
image: nginx:alpine
networks:
- frontend
- backend
app:
image: alpine
command:
- sh
- -c
- while true; do sleep 3600; done
networks:
- backend
db:
image: postgres:alpine
environment:
POSTGRES_PASSWORD: CHANGE_ME
networks:
- backend
networks:
frontend:
backend:
В такой схеме:
proxyподключён к двум сетям;appиdbдоступны только в backend-сети;- база данных не подключена к frontend-сети.
Это ограничивает ненужную сетевую доступность.
Внешняя сеть Compose
Создайте сеть вручную:
docker network create shared-network
Добавьте в compose.yaml:
services:
app:
image: alpine
command:
- sh
- -c
- while true; do sleep 3600; done
networks:
- shared
networks:
shared:
external: true
name: shared-network
Compose будет использовать существующую сеть и не удалит её при выполнении:
docker compose down
Фиксированное имя сети
По умолчанию Compose добавляет к имени сети префикс проекта.
Чтобы задать точное имя:
networks:
frontend:
name: app-frontend
После запуска сеть будет называться:
app-frontend
Проверка опубликованных портов
Для конкретного контейнера:
docker port web
Для всех контейнеров:
docker ps \
--format 'table {{.Names}}\t{{.Ports}}'
Проверка прослушиваемого порта на хосте:
sudo ss -lntup | grep ':8080'
Удаление сети
Сначала удалите подключённые контейнеры:
docker rm -f web client
Удалите сеть:
docker network rm app-network
Если сеть используется, Docker не позволит её удалить.
Удаление сети Compose
cd ~/docker-network-example
docker compose down
Compose удалит созданные контейнеры и сеть проекта.
Внешние сети останутся.
Поиск неиспользуемых сетей
docker network ls \
--filter dangling=true
Очистка неиспользуемых сетей
docker network prune
Без подтверждения:
docker network prune -f
Команда удаляет сети, не используемые контейнерами.
Типичные проблемы
Контейнер не разрешается по имени
Проверьте, что оба контейнера подключены к одной пользовательской сети:
docker network inspect NETWORK_NAME
Проверьте сети контейнера:
docker inspect \
--format '{{json .NetworkSettings.Networks}}' \
CONTAINER_NAME
Связь по IP работает, а по имени — нет
Убедитесь, что используется пользовательская сеть, а не только стандартная bridge.
Создайте отдельную сеть и подключите к ней оба контейнера.
Порт не открывается на хосте
Проверьте публикацию:
docker port CONTAINER_NAME
Проверьте локальный ответ:
curl -I http://127.0.0.1:8080
Проверьте прослушиваемые порты:
sudo ss -lntup | grep ':8080'
Сервис доступен из контейнера, но не извне
Проверьте:
- секцию
ports; - локальный firewall;
- правила Docker;
- адрес привязки;
- сетевые ограничения провайдера.
Compose создал сеть с неожиданным именем
Посмотрите список:
docker network ls
При необходимости задайте параметр:
name: app-network
Быстрый набор команд
Создать сеть:
docker network create NETWORK_NAME
Посмотреть сети:
docker network ls
Проверить сеть:
docker network inspect NETWORK_NAME
Подключить контейнер:
docker network connect NETWORK_NAME CONTAINER_NAME
Отключить контейнер:
docker network disconnect NETWORK_NAME CONTAINER_NAME
Удалить сеть:
docker network rm NETWORK_NAME
Итог
После выполнения инструкции:
- создана пользовательская Docker-сеть;
- контейнеры подключены к общей сети;
- проверена связь по DNS-именам;
- опубликован порт на хосте;
- сеть описана в Docker Compose;
- рассмотрено разделение сервисов по нескольким сетям;
- показано безопасное удаление сетей.
Для production-среды каждый сервис следует подключать только к тем сетям, которые действительно необходимы для его работы.