После internal: true пропал внешний API: разделяем сети Compose

Базу и приложение поместили в сеть с internal: true, чтобы закрыть лишний сетевой доступ. PostgreSQL по-прежнему доступен приложению, но запрос к платёжному API перестал проходить. Это ожидаемый конфликт требований: один сервис должен общаться только внутри стека, другому нужен ещё и внешний маршрут.

В Compose сеть internal предназначена для внешне изолированной сети. Если подключить к ней единственный интерфейс приложения, нельзя одновременно рассчитывать на обычный выход к интернет-зависимостям. Удобнее описать топологию по реальным связям: база остаётся во внутреннем сегменте, приложение имеет доступ и к нему, и к сети с внешней связностью.

Показать связи в конфигурации

Ниже база находится только в backend, а приложение — в backend и outbound. Порт базы на хост не публикуется. Само приложение собирается из каталога проекта.

services:
  app:
    build: .
    networks: [backend, outbound]
  db:
    image: postgres:17-alpine
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets: [db_password]
    networks: [backend]

networks:
  backend:
    internal: true
  outbound: {}

secrets:
  db_password:
    file: ./secrets/db_password.txt

Для запуска нужен файл secrets/db_password.txt с подходящим тестовым паролем и согласованная конфигурация подключения app к db. Фрагмент показывает сетевое разделение, а не готовое приложение. Его полезно читать буквально: app видит db по общей backend-сети, db не подключена к outbound.

Internal не является списком разрешённых внешних адресов. Если app подключена к обычной сети, сам по себе Compose не ограничивает её исходящий трафик одним платёжным API. Для адресных политик понадобятся дополнительные сетевые механизмы. Также двусетевое приложение остаётся точкой, которая может обращаться к данным базы: топология не заменяет права пользователя PostgreSQL и проверку запросов.

Проверить нужный и ненужный путь

На учебном стенде отдельно проверьте соединение app → db и HTTPS-запрос app → внешний тестовый endpoint. Затем посмотрите docker network inspect для обеих сетей и убедитесь, что db не подключена к outbound. Сравнивайте именно запущенные контейнеры после пересоздания, а не только отредактированный YAML.

Если проблема сохраняется, разделите DNS и маршрут. Ошибка разрешения имени и timeout уже установленного адреса требуют разных проверок. При нескольких сетях порядок и выбор шлюза зависят от конфигурации Docker; не пытайтесь управлять им случайным порядком строк. Проверяйте фактические маршруты приложения и используйте поддерживаемые параметры своей версии Compose.

Удобный результат такой настройки — схема, по которой коллега сразу понимает назначение каждого подключения. Сеть базы отделена, а необходимость внешнего доступа приложения явно видна в review. Это лучше скрытого исключения, добавленного вручную в уже работающий контейнер и потерянного при следующем обновлении.

Продолжить практику

Эту настройку проще понимать в составе приложения, у которого есть сеть, данные и понятная процедура обновления. На курсе «Docker и Docker Compose: контейнеризация приложений» вы упакуете HTTP-сервис с PostgreSQL, разберёте конфигурацию, хранение данных и диагностику сбоев. В программе есть локальные лабораторные, работа с registry и версиями образов; итоговый проект включает передачу окружения другому разработчику и проверку восстановления базы.

Посмотреть программу курса

Источник: официальная документация.

Другие задачи по теме: Процессы, сеть, тома и сборка контейнера.

Продолжить на практике

  • Docker и Docker Compose: контейнеризация приложений ↗

    Упакуйте приложение в Docker и запустите его с PostgreSQL через Compose. Образы, сети, тома, диагностика поломок, обновление версий и восстановление данных — с практикой и итоговым проектом.