Dev Container nie dociera do hosta dostępnego tylko przez VPN: gdzie szukać
Przeglądarka i kontener mają różne konteksty resolvera, proxy i tras. Zanim zmienisz jakiekolwiek ustawienie VPN, ustal, którego używa zawodzący proces.
Prywatne API otwiera się w przeglądarce na pulpicie, a zawodzi w kontenerze deweloperskim. To nie sprzeczność i rzadko winna jest sama VPN. Żądanie przeglądarki i zawodzące żądanie wysłały różne procesy, z różnymi resolverami, proxy i trasami, a często z zupełnie różnych przestrzeni nazw sieci. „Na moim laptopie” może oznaczać hosta Windows, dystrybucję WSL, maszynę wirtualną Docker Desktop i kontener wewnątrz tej VM — cztery konteksty, z których każdy może odpowiedzieć inaczej na tę samą nazwę hosta. Ustal, którego używa zawodzący proces, zanim dotkniesz choćby jednego ustawienia.
Znajdź proces, zanim zmienisz ustawienie
Zacznij od silnika kontenerów, nie od klienta VPN. Zapytaj, z jakim kontekstem rozmawia wiersz poleceń i na jakim systemie operacyjnym działa ten silnik, bo kontener Linux zarządzany przez VM na pulpicie idzie inną drogą niż ten zarządzany przez lokalnego demona:
docker context ls
docker info --format '{{.OperatingSystem}} / {{.Name}}'
docker run --rm alpine ip route
W Windows wsl -l -v mówi, czy dystrybucja działa pod WSL 2, co stawia ją za własnym przełącznikiem wirtualnym. Ten szczegół decyduje, czy kontener współdzieli tablicę routingu hosta, czy siedzi za NAT, który potrzebuje przekierowanego portu lub nazwy hosta, aby dotrzeć do hosta.
Utrzymaj jedno żądanie stałe i porównuj
Wybierz jeden nieszkodliwy punkt końcowy na prywatnym hoście i używaj go w każdym porównaniu: z przeglądarki, z terminala hosta, z dystrybucji WSL i z wnętrza kontenera. Zapisz cztery rzeczy dla każdej próby: rozwiązany adres, czy użyto proxy, klasę błędu i upływ czasu. Wyszukiwanie nazwy, nawiązanie połączenia, walidacja TLS i status HTTP to cztery różne problemy, a ich zmieszanie w „nie działa” marnuje cały poranek.
Porównanie wykonaj wewnątrz zawodzącego kontenera, z limitem czasu, żeby cicha zapora nie trzymała terminala przez minuty. Nowy kontener odtwarza kontekst sieciowy silnika, ale nie przestrzeń nazw, zmienne proxy ani resolver kontenera aplikacji, więc docker exec do prawdziwego kontenera jest testem rozstrzygającym, a kontener obok to tylko sposób na wyizolowanie, czy różnica jest w silniku, czy w kontenerze:
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
Obraz bazowy alpine zawiera busybox, a nie zawiera curl, i właśnie taki szczegół powoduje, że skopiowany blok diagnostyczny zawodzi: wybierz obraz z klientem albo dodaj go w tym samym uruchomieniu. Porównanie z niepowiązanymi publicznymi stronami niczego nie izoluje. Jeśli https://example.com działa z kontenera, dowiedziałeś się, że kontener ma dostęp do internetu, i nic o tym, czy dociera do prywatnego adresu przez tunel. Podobnie otwarcie nowego terminala dowodzi tylko, że nowy terminal działa, a nie że dzieli środowisko uruchomieniowe z aplikacją, która zawiodła.
Docker Desktop może działać z VPN
Własna dokumentacja Docker dotycząca VPN i łączności z hostem opisuje to jako obsługiwaną konfigurację, a uczciwe podsumowanie jest takie, że to działa, a nie jest automatycznie zepsute. Nie zakładaj, że VM na pulpicie z założenia omija tunel hosta; w wielu konfiguracjach ruch poprawnie podąża za tunelem hosta, i dlatego mit „Docker ignoruje VPN” daje pewne siebie i błędne porady.
Nadal ważne jest używany backend, polityka split-tunnel klienta i konfiguracja resolvera, którą otrzymała VM. Klient VPN, który instaluje trasy, ale nie DNS, lub który wypycha serwer DNS nieosiągalny dla VM, powoduje błąd wyszukiwania nazwy wewnątrz kontenera, podczas gdy host działa, bo ma dodatkowy resolver lub odpowiedź z pamięci podręcznej. To problem resolvera w kostiumie kontenera. Przetrwa każde ponowne połączenie VPN, którego spróbujesz, bo tunel już niesie ruch, o który prosiłeś.
Nakładanie się adresów i MTU to różne awarie
Dwie awarie zasługują na własną diagnozę, bo często się je myli z polityką dostępu. Pierwsza to nakładanie się adresów: jeśli VPN wypycha zakres, który koliduje z podsiecią domyślnego mostu sieci kontenerów, trasa kontenera dla tego zakresu wskazuje lokalny most i nigdy nie dociera do tunelu. Sprawdź rzeczywiste podsieci zamiast zgadywać:
docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
ip route get 10.20.30.40
Druga to problem z MTU. Jeśli połączenie się nawiązuje i TLS się kończy, ale większe odpowiedzi się zatrzymują, masz problem z rozmiarem pakietu, nie z autoryzacją, i zamiana rekordów DNS nigdy tego nie naprawi. Przetestuj małym i dużym żądaniem, zanim cokolwiek zmienisz, i zapisz oba wyniki.
Rozwiązaniem nakładania jest inna podsieć kontenerów albo ograniczona trasa, wybrana przez właściciela planu adresów. Rozwiązaniem zablokowania MTU jest ściśnięcie lub obniżenie MTU tunelu albo interfejsu do wartości, która przetrwa ścieżkę, zastosowane w warstwie, którą kontrolujesz.
Konfiguracja proxy jest na proces, nie na maszynę
Wewnątrz kontenera localhost nazywa własny kontekst sieciowy tego kontenera, więc proxy działające na hoście nie jest tam osiągalne pod tą nazwą. Docker Desktop udostępnia host.docker.internal do dostępu do hosta, a w Linuksie dodajesz je jawnie przez --add-host=host.docker.internal:host-gateway. Tak czy inaczej, ta nazwa daje ci trasę do hosta; nie tworzy usługi proxy ani nie upoważnia cię do korzystania z niej.
Użyj adresu i portu proxy podanych dla rzeczywistego środowiska i sprawdź, kto je czyta. Zmienne wyeksportowane w interaktywnej powłoce nie konfigurują automatycznie każdego rozszerzenia edytora, serwera językowego, narzędzia build i demona w tle. Liczy się proces, który wysłał zawodzące żądanie, więc sprawdź jego środowisko, a nie środowisko swojego terminala.
Wreszcie, niech poprawka sama się wyjaśni. Przydatne rozwiązanie nazywa granicę, która była błędna, ustawienie, które ją zmieniło, i zbiór procesów, na które teraz wpływa. Restart VPN, edytora i silnika po kolei może zmienić objaw, ale nie zostawia niczego, z czego następna osoba mogłaby skorzystać.