Перейти к содержанию
Innovialabs

Сети в Docker: bridge, host и пользовательские сети

Основы3 мин

Коротко

Контейнеры в одной пользовательской сети находят друг друга по имени сервиса, а наружу приложение доступно только через опубликованный порт (-p). Сеть host убирает изоляцию и нужна редко.

Как устроены сети в Docker

Каждый контейнер получает собственный сетевой стек: свой IP-адрес, свои порты, свой localhost. Docker связывает контейнеры между собой и с хостом через сетевые драйверы. В повседневной работе важны три варианта:

  • bridge (по умолчанию) — виртуальная сеть внутри хоста. Контейнеры получают внутренние адреса, наружу выходят через NAT.
  • пользовательская bridge-сеть — то же самое, но с встроенным DNS по имени контейнера и лучшей изоляцией. Это стандартный выбор.
  • host — контейнер использует сетевой стек хоста напрямую, без изоляции и без публикации портов.

Есть и другие драйверы (none, overlay, macvlan), но они нужны для специальных задач: полной изоляции, кластеров или подключения контейнера напрямую в физическую сеть.

Публикация портов: как попасть в контейнер снаружи

Порт внутри контейнера по умолчанию недоступен с хоста и из интернета. Чтобы открыть его, порт нужно опубликовать:

docker run -d -p 8080:80 nginx

Запись читается как ХОСТ:КОНТЕЙНЕР: запросы на порт 8080 хоста попадают на порт 80 контейнера.

Важные детали:

  • -p 8080:80 слушает на всех интерфейсах хоста, то есть порт может быть виден из интернета. Если сервис нужен только локально, используйте -p 127.0.0.1:8080:80.
  • Docker сам добавляет правила в firewall хоста, и они могут обходить настройки вроде ufw. Не публикуйте порты баз данных без необходимости.
  • EXPOSE в Dockerfile — это только документация, он не открывает порт.

DNS по имени сервиса

В пользовательской сети контейнеры обращаются друг к другу по имени, а не по IP. IP-адреса меняются при каждом пересоздании контейнера, имена — нет.

docker network create app-net
docker run -d --name db --network app-net postgres
docker run -d --name api --network app-net my-api

Теперь api подключается к базе по адресу db:5432. В стандартной сети bridge такой DNS не работает — это частая причина ошибки «не удаётся найти хост».

В Docker Compose пользовательская сеть создаётся автоматически, и имя сервиса из docker-compose.yml становится его DNS-именем:

services:
  api:
    build: .
    ports:
      - "8080:3000"
    environment:
      DATABASE_URL: postgres://user:pass@db:5432/app
  db:
    image: postgres:16

Обратите внимание: у db нет секции ports. Базе не нужно быть доступной снаружи — api достаёт до неё по внутренней сети.

Сравнение режимов

РежимИзоляцияDNS по имениНужен -pКогда использовать
bridge по умолчаниюестьнетдабыстрые эксперименты
пользовательский bridgeестьдада, для доступа снаружипочти всегда
hostнет—нетособые случаи с производительностью сети, только Linux
noneполная——задачи без сети

Частые ошибки

  • localhost внутри контейнера. Для контейнера localhost — это он сам, а не хост и не соседний контейнер. Обращайтесь к соседям по имени сервиса.
  • Приложение слушает 127.0.0.1. Если сервер внутри контейнера привязан к 127.0.0.1, опубликованный порт не сработает. Слушайте 0.0.0.0.
  • Перепутаны порты в -p. Слева порт хоста, справа — контейнера.
  • Порт уже занят на хосте. Docker не запустит контейнер, если порт хоста используется другим процессом.
  • Контейнеры в разных сетях. Сервисы из разных Compose-проектов по умолчанию не видят друг друга. Подключите их к общей внешней сети.
  • Открытая наружу база данных. Публикация 5432 или 3306 на всех интерфейсах — прямой риск безопасности.

Как проверить связь

  • docker network ls — список сетей.
  • docker network inspect app-net — какие контейнеры подключены и их адреса.
  • docker exec -it api sh, затем ping db или nc -zv db 5432 (если утилиты есть в образе) — проверка доступности изнутри.
  • docker port api — какие порты опубликованы.

Подробности по драйверам есть в официальной документации Docker.

Частые вопросы

В Docker Desktop работает имя host.docker.internal. В Linux его можно добавить через --add-host=host.docker.internal:host-gateway или в extra_hosts в Compose.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.