Магия сетей в Docker Compose: От изоляции до сложных конфигураций

Магия сетей в Docker Compose: От изоляции до сложных конфигураций

Docker Compose превращает управление многоконтейнерными приложениями из головной боли в элегантный танец. Но без грамотной настройки сети этот танец напоминает попытку синхронного плавания в бассейне, где каждый плывёт в своём направлении. Понимание сетевых возможностей Compose — это ключ к созданию отказоустойчивых, безопасных и эффективных микросервисных архитектур, где контейнеры общаются чётко и предсказуемо.

Сети по умолчанию: Магия, которая происходит сама собой

Когда вы запускаете docker-compose up, Compose автоматически создаёт для вашего проекта выделенную сеть типа bridge. Это ваша приватная песочница. Все сервисы, описанные в файле docker-compose.yml, подключаются к этой сети и могут находить друг друга по имени сервиса. Это базовый, но мощный механизм service discovery.

Имя сети по умолчанию формируется на основе имени проекта (указанного в .env файле или через флаг -p) и суффикса _default. Например, myapp_default.

Явное определение сетей: Полный контроль

Для сложных сценариев вы можете и должны определять сети явно. Это открывает мир возможностей.

Создание пользовательских bridge-сетей

В корне файла docker-compose.yml вы можете секцию networks:

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: \"172.28.0.0/16\"
  frontend:
    driver: bridge

А затем в каждом сервисе указать, к каким сетям он подключен:

services:
  database:
    image: postgres
    networks:
      - backend

  api:
    build: ./api
    networks:
      - backend
      - frontend

  web:
    build: ./web
    networks:
      - frontend

Теперь API-сервис выступает в роли моста между внутренней сетью backend (где живёт база данных) и внешней frontend (откуда идут запросы от веб-приложения). База данных изолирована от прямого доступа извне.

Критически важные параметры сети

  • aliases: Псевдонимы для сервиса в сети. Дополнительные DNS-имена.
  • ipv4_address / ipv6_address: Фиксация статического IP-адреса для контейнера в сети с ручной настройкой IPAM.
  • driver_opts: Опции драйвера сети. Например, для настройки MTU.
  • external: true: Подключение к сети, созданной вне Docker Compose (например, через docker network create).

Используйте external сети для подключения контейнеров из разных проектов Compose. Это основа для взаимодействия независимо развёрнутых микросервисов.

Публикация портов: Мост между мирами

Ключ ports в конфигурации сервиса создаёт проброс портов с хоста в контейнер. Синтаксис \"HOST:CONTAINER\".

services:
  nginx:
    image: nginx
    ports:
      - \"80:80\"          # Порт 80 хоста -> порт 80 контейнера
      - \"127.0.0.1:443:443\" # Только локальный доступ на хосте

Для временной публикации портов только для других сервисов в той же сети используйте expose. Эти порты не публикуются на хост-машину.

Практический пример: Трёхзвенная архитектура

Рассмотрим типичный стек: Nginx + Python-приложение + PostgreSQL.

version: '3.8'

networks:
  public:
  private:

services:
  nginx:
    image: nginx:alpine
    ports:
      - \"80:80\"
    networks:
      - public
    depends_on:
      - app

  app:
    build: ./app
    networks:
      public:
      private:
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      - db

  db:
    image: postgres:15
    networks:
      - private
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

Nginx общается с приложением через сеть public. Приложение общается с базой данных через изолированную сеть private. База данных не имеет выхода в публичную сеть.

Диагностика и утилиты

  1. docker network ls — список всех сетей.
  2. docker network inspect [NETWORK_NAME] — детальная информация о сети, включая подключённые контейнеры и IP-адреса.
  3. docker-compose exec [SERVICE] ping [ANOTHER_SERVICE] — проверка связности между сервисами.

FAQ: Часто задаваемые вопросы

Как контейнеры находят друг друга по имени?

Docker Compose встраивает в создаваемые сети встроенный DNS-сервер. Когда контейнер пытается разрешить имя сервиса (например, db), DNS возвращает внутренний IP-адрес этого контейнера в данной сети.

Можно ли подключить существующий контейнер к сети Compose?

Да, если сеть определена как external. Используйте команду docker network connect [NETWORK_NAME] [CONTAINER_NAME].

В чём разница между ports и expose?

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

Как настроить статический IP для контейнера?

Необходимо явно определить сеть с настройками IPAM (IP Address Management) и затем указать ipv4_address в конфигурации сервиса внутри этой сети.

Что такое сеть host и когда её использовать?

При использовании сети host контейнер делит сетевое пространство с хост-машиной (не имеет собственной сетевой изоляции). Это может дать выигрыш в производительности, но является менее безопасным. Используйте осторожно, в основном для высокопроизводительных сетевых приложений (например, балансировщиков нагрузки).