Вы добавляете network_mode: service:vpn в приложение, перезапускаете стек, и приложение умирает, потому что db больше не разрешается. В файле compose ничего не переименовано, поэтому очевидные подозреваемые — DNS и база данных. Настоящее изменение меньше и страннее: приложение перестало быть участником сети Compose, где существует это имя. Пока вы не решите, из какого пространства имён должна отвечать база данных, любое исправление имени хоста — догадка.

Почему имя хоста db перестало разрешаться

Служба, использующая network_mode, не имеет собственного адреса в сети Compose; она заимствует пространство имён указанной службы. Это пространство приносит свои интерфейсы, маршруты, пространство портов и резолвер, и оно заменяет подключение приложения к сети backend. Имя db никогда не было абстрактным: оно жило в этой сети и разрешалось через встроенный DNS. Уберите подключение, и имени негде разрешаться.

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

Три вопроса перед правкой файла

Ответьте на них по порядку, потому что каждый сужает топологию. На что должна отвечать база данных: на имя хоста, которое используют другие контейнеры, или только на приложение на loopback? Должно ли приложение публиковать порт на хост, и какая служба владела бы им? Должна ли база данных быть доступна с хоста или с другой машины, или только изнутри туннеля?

Если базе данных нужно собственное имя, а приложение ничего не публикует, держите их на отдельных подключениях. Если приложение должно публиковать порт и всё идёт через туннель, поместите базу данных в пространство имён VPN и используйте loopback. Смешение обоих даёт стек, который чисто запускается и падает при подключении.

Оставьте базу данных там, где она есть

Меньшее изменение подключает владельца пространства имён к сети, которая уже содержит базу данных. Приложение наследует это подключение, потому что делит стек vpn, и db разрешается точно как раньше.

services:
  vpn:
    networks:
      - backend
  app:
    network_mode: service:vpn
  db:
    networks:
      - backend
networks:
  backend:

Не добавляйте networks и в приложение. Compose отклоняет это свойство вместе с network_mode в той же службе, и ошибка указывает на файл, а не на пару. Если клиент VPN фильтрует назначение backend внутри своего пространства имён, настройте и его поддерживаемую политику локальной сети; общее подключение предлагает путь, но не отменяет этот фильтр.

Переместите базу данных в пространство имён

Большее изменение помещает базу данных в то же пространство имён и направляет приложение на 127.0.0.1 с настоящим портом. Два процесса не могут оба занять один и тот же адрес и порт только потому, что запустились в разных контейнерах, поэтому база данных, которая также слушает на wildcard-адресе, столкнётся со всем остальным, что это делает. Проверьте слушателя перед перемещением.

Опубликованные порты принадлежат службе, владеющей пространством имён. Добавление ports в приложение отклоняется вместе с network_mode, а изобретение отдельного адреса приложения описывает интерфейс, которого нет.

Готовность, блокировка и резолвер

depends_on упорядочивает запуск контейнеров; это не доказательство того, что туннель работает, и он не останавливает трафик, когда туннель падает. Рассматривайте достижимость, готовность туннеля и блокировку отказов как три отдельных требования. Стек, удовлетворяющий только первому, проходит ручной тест в хороший день и течёт в плохой. Запишите три ответа рядом с файлом compose, там, куда посмотрит следующий человек.

Совместное использование пространства имён также означает, что приложение наследует резолвер контейнера VPN, что помогает, когда туннель навязывает DNS-серверы, и путает, когда не делает этого. Проверьте, что пространство имён действительно содержит, вместо того чтобы предполагать, что резолвер хоста применим. Справочник служб Compose документирует network_mode, ports и поведение зависимостей в одном месте, включая то, почему у службы network_mode нет собственного адреса.

Похожие статьи