Контейнер розробки не може досягти хоста, доступного лише через VPN: де шукати
Браузер і контейнер мають різні контексти резолвера, проксі та маршрутів. З'ясуйте, який із них використовує процес, що зазнає невдачі, перш ніж змінювати будь-яке налаштування VPN.
Приватний API відкривається у вашому браузері на комп'ютері та зазнає невдачі в контейнері розробки. Це не суперечність, і рідко винна сама VPN. Запит із браузера та запит, що зазнає невдачі, виконали різні процеси, з різними резолверами, проксі та маршрутами, і часто з цілком різних мережевих просторів імен. «На моєму ноутбуці» може означати хост Windows, дистрибутив WSL, віртуальну машину Docker Desktop і контейнер усередині цієї ВМ — чотири контексти, кожен із яких може по-різному відповісти на те саме ім'я хоста. З'ясуйте, який із них використовує процес, що зазнає невдачі, перш ніж торкнутися бодай одного налаштування.
Знайдіть процес, перш ніж змінювати налаштування
Почніть із рушія контейнерів, а не з клієнта VPN. Запитайте, з яким контекстом спілкується командний рядок і на якій операційній системі працює цей рушій, бо контейнер Linux під керуванням віртуальної машини на комп'ютері — це інший шлях, ніж той, яким керує локальний демон:
docker context ls
docker info --format '{{.OperatingSystem}} / {{.Name}}'
docker run --rm alpine ip route
У Windows wsl -l -v повідомляє, чи працює дистрибутив під WSL 2, що ставить його за власний віртуальний комутатор. Ця деталь визначає, чи контейнер спільно використовує таблицю маршрутизації хоста, чи стоїть за NAT, якому потрібен переспрямований порт або ім'я хоста, щоб досягти хоста.
Тримайте один запит сталим і порівнюйте
Виберіть одну нешкідливу кінцеву точку на приватному хості й використовуйте її для кожного порівняння: з браузера, з термінала хоста, з дистрибутива WSL і зсередини контейнера. Записуйте чотири речі для кожної спроби: розв'язану адресу, чи використовувався проксі, клас збою та витрачений час. Пошук імені, встановлення з'єднання, перевірка TLS і статус HTTP — це чотири різні проблеми, і змішування їх у «це не працює» витрачає ранок.
Виконуйте порівняння всередині контейнера, що зазнає невдачі, з тайм-аутом, щоб тихий брандмауер не тримав термінал хвилинами. Новий контейнер відтворює мережевий контекст рушія, але не простір імен, змінні проксі чи резолвер контейнера застосунку, тому docker exec у справжній контейнер — це авторитетний тест, а допоміжний контейнер лише спосіб ізолювати, чи різниця в рушії, чи в контейнері:
docker exec -it app /bin/sh -c "getent hosts api.internal; curl -v --max-time 8 https://api.internal/ 2>&1 | tail -20"
docker run --rm --network container:app curlimages/curl:latest -sv --max-time 8 https://api.internal/ 2>&1 | tail -20
Базовий образ alpine містить busybox і не має curl, і саме така деталь змушує скопійований діагностичний блок зазнавати невдачі: виберіть образ із клієнтом або додайте його в тому самому запуску. Порівняння з не пов'язаними публічними сайтами нічого не ізолює. Якщо https://example.com працює з контейнера, ви дізналися, що контейнер має доступ до інтернету, і нічого про те, чи може він досягти приватної адреси через тунель. Так само відкриття нового термінала доводить лише, що новий термінал працює, а не те, що він поділяє середовище виконання із застосунком, який зазнав невдачі.
Docker Desktop може працювати з VPN
Власна документація Docker про VPN і підключення до хоста описує це як підтримуване налаштування, і чесний підсумок такий, що воно працює, а не автоматично зламане. Не припускайте, що віртуальна машина на комп'ютері обходить тунель хоста за задумом; у багатьох конфігураціях трафік правильно йде тунелем хоста, саме тому фольклор «Docker ігнорує VPN» дає впевнені й хибні поради.
Важливим залишається backend, який використовується, політика розділеного тунелю клієнта та конфігурація резолвера, яку отримала ВМ. Клієнт VPN, який встановлює маршрути, але не DNS, або який надсилає DNS-сервер, недоступний для ВМ, спричиняє збій пошуку імені всередині контейнера, тоді як хост працює, бо має додатковий резолвер або кешовану відповідь. Це проблема резолвера в контейнерному костюмі. Вона переживає кожне повторне підключення VPN, яке ви спробуєте, бо тунель уже несе той трафік, який ви просили його нести.
Перекриття адрес і MTU — це різні збої
Два збої заслуговують на власну діагностику, бо їх часто плутають із політикою доступу. Перший — перекриття адрес: якщо VPN передає діапазон, що збігається з підмережею типового мосту мережі контейнера, маршрут контейнера для цього діапазону вказує на локальний міст і ніколи не досягає тунелю. Огляньте фактичні підмережі замість здогадок:
docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
ip route get 10.20.30.40
Другий — проблема MTU. Якщо з'єднання встановлюється і TLS завершується, але більші відповіді застрягають, у вас проблема розміру пакета, а не авторизації, і заміна записів DNS ніколи це не виправить. Перевірте малим запитом і великим, перш ніж щось змінювати, і запишіть обидва результати.
Виправлення для перекриття — інша підмережа контейнера або обмежений маршрут, обраний тим, хто володіє планом адрес. Виправлення для застою MTU — обмеження або зменшення MTU тунелю чи інтерфейсу до значення, що витримує шлях, застосоване на шарі, який ви контролюєте.
Конфігурація проксі — для процесу, а не для машини
Усередині контейнера localhost називає власний мережевий контекст цього контейнера, тому проксі, що працює на хості, там недоступний під цим ім'ям. Docker Desktop надає host.docker.internal для доступу до хоста, а в Linux ви додаєте його явно за допомогою --add-host=host.docker.internal:host-gateway. У будь-якому разі це ім'я дає вам маршрут до хоста; воно не створює службу проксі й не дає вам права нею користуватися.
Використовуйте адресу й порт проксі, надані для фактичного середовища, і перевірте, хто їх читає. Змінні, експортовані в інтерактивній оболонці, не налаштовують автоматично кожне розширення редактора, мовний сервер, інструмент збірки й фоновий демон. Важливий той процес, який зробив запит, що зазнає невдачі, тому огляньте його середовище, а не середовище вашого термінала.
Насамкінець, зробіть так, щоб виправлення пояснювало себе. Корисне рішення називає межу, яка була хибною, налаштування, що її змінило, і набір процесів, на які воно тепер впливає. Перезапуск VPN, редактора й рушія по черзі може змінити симптом, але не залишає нічого, чим наступна людина могла б скористатися.