Сети Docker Compose: создание и управление сетями для контейнеров | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Сети Docker Compose: создание и управление сетями для контейнеров

02 апреля 2026 9 мин. чтения
Содержание статьи

Зачем нужны сети в Docker Compose: от изоляции до безопасности микросервисов

При запуске сервисов через Docker Compose без явной конфигурации сетей все контейнеры автоматически попадают в одну общую мостовую сеть с именем проекта. Это удобно для быстрого старта, но создает серьезные риски для production-среды: уязвимость одного сервиса может привести к компрометации всего приложения, сложность диагностики проблем и отсутствие четкой архитектурной сегментации. Согласно статистике, в первом полугодии 2025 года было зарегистрировано более 25 000 попыток атак на облачные и гибридные инфраструктуры, что делает вопрос изоляции критически важным.

Создание пользовательских сетей в Docker Compose превращает хаотичную группу контейнеров в структурированную, безопасную систему. Вы получаете контроль над тем, какие сервисы могут взаимодействовать друг с другом, организуете трафик по четким правилам и снижаете «атакуемую поверхность» вашего приложения. Это не просто настройка — это фундамент для построения отказоустойчивых и безопасных микросервисных архитектур.

Сеть по умолчанию vs. Пользовательские сети: в чем разница на практике

Основные различия между автоматически созданной сетью и пользовательскими сетями, которые вы определяете в docker-compose.yml, сводятся к контролю и прозрачности:

  • Идентификация: Сеть по умолчанию получает автоматическое имя (например, myproject_default), которое сложно отследить. Пользовательские сети имеют осмысленные, заданные вами названия (frontend, backend, database), что сразу отражает их роль в архитектуре.
  • IP-адресация: В сети по умолчанию Docker динамически назначает IP-адреса из пула, что затрудняет планирование и настройку брандмауэров. В пользовательских сетях вы можете задать фиксированную подсеть, диапазон адресов и даже статические IP для критичных сервисов.
  • Изоляция: В сети по умолчанию все сервисы проекта видят друг друга, что противоречит принципам минимального необходимого доступа. Пользовательские сети позволяют создать строгие сегменты: например, база данных будет доступна только для backend-сервиса, а не для frontend.
  • Диагностика: Проблемы связности в общей сети сложнее локализовать. В сегментированной архитектуре вы сразу понимаете, в каком сегменте произошел сбой.

Архитектурные паттерны: как правильно сегментировать типовое приложение

Для типичного стека приложения (например, Nginx, веб-приложение, PostgreSQL, Redis) лучшей практикой является создание трех отдельных сетей:

  1. Frontend сеть (например, front-tier): В этой сети находится только reverse proxy (Nginx/Traefik). Она может быть подключена к внешнему миру или к другой внешней сети. Сервисы backend и database к этой сети не подключены.
  2. Backend сеть (например, app-tier): Сеть для взаимодействия frontend и backend сервисов. Здесь находятся Nginx и веб-приложение. База данных и кэш остаются изолированными.
  3. Database сеть (например, data-tier): Полностью внутренняя, изолированная сеть. В нее подключены веб-приложение и база данных (и, возможно, кэш). Это гарантирует, что к данным могут обращаться только сервисы, которым это действительно необходимо.

Такая сегментация аналогична организации офиса: бухгалтерия (database сеть), отдел разработки (backend сеть) и приемная (frontend сеть) имеют разный уровень доступа к информации и ресурсам.

Базовый синтаксис: создание и подключение сетей в docker-compose.yml

Конфигурация сетей в Docker Compose состоит из двух ключевых шагов: объявление сети на корневом уровне файла и подключение конкретных сервисов к этой сети. Рассмотрим минимальный рабочий пример для версии 3.8, который является современным стандартом.

Объявление сети на корневом уровне

Сети объявляются в отдельной секции networks в начале файла docker-compose.yml. Это определение создает сеть, но пока не связывает ее с сервисами.

version: '3.8'

services:
  # Сервисы будут описаны ниже

networks:
  backend:
    # Базовая сеть без дополнительных параметров
  database:
    # Вторая сеть для изоляции

В этом примере мы объявили две сети: backend и database. Docker Compose создаст их при запуске проекта.

Подключение сервиса к сети

Чтобы сервис мог использовать объявленную сеть, необходимо указать ее в секции networks внутри описания сервиса.

version: '3.8'

services:
  webapp:
    image: myapp:latest
    networks:
      - backend  # Подключаем сервис к сети backend

  db:
    image: postgres:15
    networks:
      - database  # Подключаем сервис к сети database
      - backend   # Сервис db также подключен к backend для связи с webapp

networks:
  backend:
  database:

В этом конфигурации сервис webapp находится только в сети backend. Сервис db подключен к обеим сетям, что позволяет ему общаться с webapp через сеть backend, но также быть частью изолированной сети database. Внутри одной сети контейнеры могут находить друг друга по имени сервиса (в данном случае webapp и db) через встроенный DNS-сервер Docker.

Версии 2 и 3: ключевые отличия в сетевой конфигурации

Формат файла Docker Compose существенно изменился между версиями 2 и 3. Это часто приводит к ошибкам, когда код из старой документации или примеров не работает в современных проектах. Знание различий поможет избежать этих проблем.

Синтаксис версии 2: устаревший, но встречающийся

В версии 2 формата сети часто объявлялись неявно, непосредственно при подключении сервиса. Отдельная корневая секция networks могла отсутствовать.

version: '2'

services:
  webapp:
    image: myapp:latest
    networks:
      - backend

  db:
    image: postgres:15
    networks:
      - backend

networks:
  backend:
    driver: bridge

Обратите внимание, что даже при наличии секции networks, возможности управления (такие как ipam для задания подсети) были ограничены. Использование версии 2 для новых проектов не рекомендуется.

Синтаксис версии 3: современный стандарт

Версия 3 (и более поздние, например, 3.8) требует явного объявления всех сетей в корневой секции networks. Это делает конфигурацию более чистой и предоставляет доступ к расширенным параметрам.

version: '3.8'

services:
  webapp:
    image: myapp:latest
    networks:
      - backend

  db:
    image: postgres:15
    networks:
      - backend

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
          gateway: 172.20.0.1

Ключевое отличие: в версии 3 вы можете детально настроить драйвер сети (driver) и управление IP-адресами (ipam), что невозможно или сильно ограничено в версии 2. Для всех новых проектов следует указывать version: '3.8' или выше.

Продвинутые сценарии: внешние сети, статические IP и алиасы

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

Подключение к внешней, предсозданной сети

Когда ваш Compose-проект должен взаимодействовать с контейнерами, созданными вне этого проекта (например, с reverse proxy Traefik, запущенным отдельно), необходимо подключить сервисы к уже существующей внешней сети.

version: '3.8'

services:
  webapp:
    image: myapp:latest
    networks:
      - traefik-public
      - app-internal

networks:
  traefik-public:
    external: true
    name: traefik-public  # Имя сети, созданной ранее через `docker network create`
  app-internal:
    driver: bridge

Ключевые параметры: external: true указывает, что сеть не будет создаваться Compose, а name задает точное имя существующей сети. Внимание: эта сеть должна быть создана (например, командой docker network create traefik-public) до запуска docker-compose up.

Ручное управление IP-адресацией (IPAM)

Для назначения статических IP-адресов контейнерам используется секция ipam (IP Address Management). Это важно, когда IP-адрес сервиса должен быть фиксированным для конфигурации брандмауэров, других систем или для гарантии постоянного внутреннего endpoint.

networks:
  backend:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: "172.22.0.0/24"
          gateway: "172.22.0.1"
          ip_range: "172.22.0.0/28"

services:
  database:
    image: postgres:15
    networks:
      backend:
        ipv4_address: 172.22.0.10  # Статический IP для этого контейнера в сети backend

В этом примере для сети backend задана подсеть 172.22.0.0/24, шлюз и даже диапазон адресов (ip_range). Сервису database явно назначен статический адрес 172.22.0.10. Предостережение: необходимо тщательно планировать адресацию, чтобы избежать конфликтов между контейнерами.

Алиасы (aliases) для резервирования имён

Алиасы предоставляют контейнеру дополнительные DNS-имена внутри сети. Это полезно для организации сервисов (например, указание роли) или создания резервных точек доступа.

services:
  db-primary:
    image: postgres:15
    networks:
      backend:
        aliases:
          - "postgres"
          - "primary-db"

  app:
    image: myapp:latest
    networks:
      - backend

Контейнер db-primary будет доступен в сети backend не только по имени сервиса db-primary, но также по адресам postgres и primary-db. Сервис app может подключиться к базе данных, используя любое из этих имен.

Готовые примеры конфигураций для микросервисного стека

Ниже представлены две полные, готовые к использованию конфигурации, которые демонстрируют применение всех рассмотренных принципов.

Пример 1: Стандартная трехзвенная архитектура (Web + App + DB)

Это универсальный шаблон для классического веб-приложения с четкой сегментацией трафика.

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - front-tier
      - app-tier

  app:
    image: my-webapp:latest
    networks:
      - app-tier
      - data-tier

  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    networks:
      - data-tier

networks:
  front-tier:
    driver: bridge
  app-tier:
    driver: bridge
  data-tier:
    driver: bridge

Архитектура и поток трафика:

  • Сеть front-tier: Изолированная сеть для входящего трафика. В идеале, только nginx должен быть здесь, но в данном примере он также подключен к app-tier для передачи запросов.
  • Сеть app-tier: Связывает nginx и app. База данных postgres в эту сеть не подключена.
  • Сеть data-tier: Полностью внутренняя сеть для связи app и postgres. Это гарантирует, что база данных недоступна напрямую из внешнего мира или даже из frontend-сервиса.

Пример 2: Архитектура с внешним прокси и кэшем

Более сложный сценарий, приближенный к production, с использованием внешней сети для reverse proxy и внутренней сети с ручной IP-адресацией.

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    ports:
      - "80:80"
      - "443:443"
    networks:
      - traefik-public
      - app-network

  backend:
    image: my-backend:latest
    networks:
      - app-network
        aliases:
          - "api"

  redis:
    image: redis:7
    networks:
      - app-network
        ipv4_address: 172.30.0.5

networks:
  traefik-public:
    external: true
    name: traefik-public
  app-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/24
          gateway: 172.30.0.1

Ключевые особенности:

  • traefik подключен к внешней сети traefik-public, которая уже существует в Docker, и к внутренней сети проекта app-network.
  • backend сервис находится только в внутренней сети app-network и имеет алиас api, по которому Traefik может его найти.
  • redis полностью изолирован в сети app-network и имеет статический IP-адрес 172.30.0.5, который может быть использован в конфигурации приложения для гарантированного подключения.
  • Сервис redis не подключен к внешней сети traefik-public и, следовательно, недоступен извне, что повышает безопасность.

Для управления более сложными контейнерными инфраструктурами, особенно в кластерных средах, полезно понимать принципы оркестрации. В нашей базе знаний есть практическое руководство по Docker для системных администраторов и DevOps, которое охватывает архитектуру и развертывание многоконтейнерных приложений.

Диагностика и управление: команды для проверки и отладки

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

Ключевые команды Docker CLI для работы с сетями

  • docker network ls — список всех сетей в Docker, включая созданные Compose. Показывает имя, драйвер и область (scope).
  • docker network inspect <network_name> — детальная информация о конкретной сети: подсеть, шлюз, список подключенных контейнеров с их IP-адресами и MAC-адресами. Это основной инструмент для проверки конфигурации.
  • docker-compose ps — показывает статус всех сервисов текущего проекта, что помогает быстро понять, какие контейнеры запущены и готовы к взаимодействию.
  • docker logs <service_name> — просмотр логов конкретного сервиса. Если контейнер не может подключиться к другому, ошибки часто видны здесь.

Как проверить связь между контейнеров

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

  1. Запустите проект: docker-compose up -d.
  2. Подключитесь к одному контейнеру: docker-compose exec <service_name> sh (или bash). Например, docker-compose exec backend sh.
  3. Внутри контейнера попробуйте разрешить DNS-имя другого сервиса: nslookup redis. Успешный ответ подтвердит, что DNS работает.
  4. Проверьте связность. Пинг (ping redis) может не работать, если контейнер не отвечает на ping. Вместо этого используйте инструменты сетевого уровня, доступные в контейнере: например, curl http://redis:6379 (если сервис ожидает соединения) или nc -zv redis 6379 для проверки открытого порта.

Если вы столкнулись с проблемами, которые не удается решить стандартными командами, возможно, требуется более глубокий анализ. Для комплексной диагностики сложных систем, таких как Kubernetes, рекомендуем ознакомиться с полным пошаговым гайдом по диагностике Custom Resources в Kubernetes.

Поделиться:
Сохранить гайд? В закладки браузера