Из Docker не открывается адрес в VPN: как найти пересечение подсетей
После запуска приложения в Compose оно перестало получать отчёты с внутреннего API. С Docker-хоста тот же адрес открывается по VPN. В контейнере запрос ждёт до тайм-аута, хотя остальные подключения работают. Если сбой затрагивает одну подсеть, сначала узнайте, куда контейнер вообще пытается отправить пакет. Иногда он считает удалённый адрес своим соседом по виртуальной сети и ищет его рядом с собой.
Сравните маршрут до одного и того же IP
Допустим, нужный адрес — 172.21.8.40, а Docker-хост видит его через tun0. Подставьте адрес API и имя существующего контейнера. Для примера нужен Linux-хост с Docker Engine и правом открыть сетевое пространство имён процесса через sudo nsenter. На Docker Desktop эти проверки относятся к Linux-VM, где работает демон.
target=172.21.8.40
pid=$(docker inspect --format '{{.State.Pid}}' report-api)
if [ "$pid" -gt 0 ]; then
ip route get "$target"
sudo nsenter --target "$pid" --net ip route get "$target"
fi
Первая строка результата относится к Docker-хосту. Во второй то же вычисление маршрута выполняется в сетевом пространстве контейнера. Утилита ip при этом берётся из системы хоста, поэтому устанавливать её в образ не требуется. Если приложение обращается к API по DNS-имени, сверяйте маршрут к IP, который получил именно контейнер. Иначе можно сравнить два разных сервера.
Характерная пара результатов выглядит так.
172.21.8.40 dev tun0 src 10.8.0.14 172.21.8.40 dev eth0 src 172.21.0.3
У Docker-хоста адрес уходит в туннель. У контейнера маршрут через eth0 идёт без via. Ядро считает адрес непосредственно доступным в этой сети. В типичной IPv4 bridge-сети контейнер будет пытаться определить MAC этого соседа через ARP. До маршрута хоста через VPN дело не доходит. Для нормального выхода через bridge ожидается маршрут через шлюз, например via 172.30.240.1 dev eth0 после переноса сети.
Свяжите маршрут с сетью Compose
У контейнера может быть несколько сетей, поэтому узнайте их имена и проверьте подсеть конкретной сети.
docker inspect --format '{{range $name, $_ := .NetworkSettings.Networks}}{{println $name}}{{end}}' report-api
docker network inspect --format '{{json .IPAM.Config}}' reports_default
Если IPAM показывает 172.21.0.0/16, адрес 172.21.8.40 действительно входит в эту сеть. В контейнере напрямую подключённый маршрут для /16 более специфичен, чем маршрут по умолчанию. Когда в его таблице другой маршрут оказался точнее, результат ip route get будет иным. Поэтому начинать с одной только проверки CIDR недостаточно.
Выберите диапазон для Compose после сверки с маршрутами хоста, адресами офисных сетей и пулами VPN. Проверьте состояние и с подключённым VPN: часть маршрутов может появляться только после соединения. Пример ниже показывает настройку одной сети по умолчанию. 172.30.240.0/24 — пример, который нужно заменить на свободный диапазон в своей инфраструктуре.
networks:
default:
ipam:
config:
- subnet: 172.30.240.0/24
Проверьте два направления на стенде
Существующая bridge-сеть сохраняет выделенный диапазон. Сначала поднимите отдельный стенд с новой сетью и проверьте, что её IPAM действительно выдаёт выбранную подсеть. Используйте отдельное имя проекта и отдельные порты и данные стенда, если сервисы публикуют порты или работают с томами. Снова выполните ip route get для API из контейнера и убедитесь, что появился шлюз. Затем повторите прикладной запрос и убедитесь, что приложение продолжает видеть соседний сервис по имени из Compose. Это позволит поймать две разные ошибки: сбой выхода к API и случайную потерю связи внутри проекта.
Если пакет уже направляется через шлюз, а API по-прежнему молчит, проверяйте на хосте маршрут и правила пересылки для этого трафика. В некоторых окружениях VPN-политика разрешает только соединения, открытые самим хостом. Результат проверки маршрута поможет отделить этот случай от пересечения адресов.
Откройте программу курса Docker и Docker Compose. В сетевых лабораторных вы будете настраивать связь между контейнерами, проверять доступность сервиса и соберёте окружение приложения с PostgreSQL. Открытый урок о запуске контейнера подойдёт для первого знакомства с тем, как Docker размещает процессы приложения.
Продолжить на практике
- Docker и Docker Compose: контейнеризация приложений ↗
Практический курс Docker для разработчиков: упакуйте своё приложение, подключите PostgreSQL и запускайте окружение через Compose. Научитесь находить поломки, обновлять сервис и восстанавливать данные. 6 Dockerfile-задач с автопроверкой и 42 локальные лабораторные.
