VPN działa, przeglądarka dociera do witryn wewnętrznych, a kontener nadal nie potrafi rozwiązać tych samych nazw. Instalacja pakietu kończy się błędem rozwiązywania nazw, takim jak EAI_AGAIN, albo aplikacja nie znajduje hosta bazy danych, który maszyna hosta rozwiązuje bez żadnych skarg. Kontener nie korzysta z resolvera zainstalowanego przez VPN. Docker skopiował konfigurację resolvera hosta przy tworzeniu kontenera i nic nie skopiowało jej ponownie później.

Dwa widoki resolvera na jednej maszynie

W systemie Linux Docker daje każdemu kontenerowi kopię konfiguracji resolvera hosta w chwili tworzenia, odfiltrowuje adresy loopback i uruchamia wbudowany serwer DNS pod 127.0.0.11, który przekazuje zapytania na zewnątrz. Klient VPN, który przepisze /etc/resolv.conf po uruchomieniu kontenera, niczego w nim nie zmienia. Ponowne uruchomienie kontenera pomaga tylko wtedy, gdy resolver hosta akurat jest wtedy poprawny.

Docker Desktop na macOS lub Windows dodaje warstwę, bo demon żyje w maszynie wirtualnej. Resolver VPN hosta może nigdy nie być widoczny dla tej VM, więc ponowne uruchomienie nie zmienia zupełnie niczego. Porównaj oba widoki, zanim wybierzesz poprawkę: docker exec mycontainer cat /etc/resolv.conf obok listy resolverów hosta.

Kontener, który wymienia publiczny resolver, podczas gdy host wymienia wewnętrzny, rozwiąże nazwy publiczne i zawiedzie na wewnętrznych. Ten podział jest sygnaturą tego problemu.

Opcja A: przekazać resolver tunelu dla każdego kontenera

Docker przyjmuje ustawienia DNS dla każdego kontenera i to jest najmniejsza działająca zmiana. Najpierw odczytaj adresy resolvera VPN: scutil --dns na macOS, resolvectl status albo własne wyjście statusu klienta na Linuksie. Następnie uruchom kontener z tymi adresami, na przykład docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. W Compose to samo ustawienie jest listą pod usługą, gdzie żyje w kontroli wersji, a nie w czyjejś historii powłoki.

Tablica dns w /etc/docker/daemon.json dotyczy każdego nowego kontenera, co brzmi schludniej, niż jest. Działa też, gdy tunel jest wyłączony, a resolver osiągalny tylko przez VPN psuje wtedy zwykłe pobieranie obrazów. Ustawienia dla pojedynczego kontenera łatwiej uzasadnić i łatwiej wycofać.

Opcja B: pozwolić kontenerowi współdzielić sieć hosta

Sieć hosta całkowicie omija kopię, bo kontener korzysta z resolvera hosta i tunelu hosta. Usuwa też izolację sieciową, której prawdopodobnie chciałeś, i nie zachowuje się tak samo pod Docker Desktop. W systemie Linux to pragmatyczny wybór dla jednorazowego narzędzia, które musi rozwiązywać nazwy wewnętrzne.

Dla buildów nie obowiązuje żadna z tych opcji, bo kroki builda nie dziedziczą flag czasu wykonania. Buduj z siecią hosta tam, gdzie platforma na to pozwala, albo trzymaj instalację zależności w etapie, który nie potrzebuje tunelu.

Czego nie naprawia żadna z opcji

Adres DNS jest bezużyteczny, jeśli kontener nie ma do niego trasy. Resolver VPN zwykle siedzi w przestrzeni adresowej tunelu, więc kontener potrzebuje ścieżki do tego prefiksu. Domyślny most Dockera zwykle kieruje ruch na zewnątrz przez hosta, i to wystarcza, gdy host ma trasę tunelu, a przekazywanie jest włączone. Własne sieci mostkowe z własnymi pulami adresów mogą kolidować z podsiecią VPN, a wtedy zapytania idą zupełnie gdzie indziej.

Zanim zaczniesz debugować sam resolver, porównaj podsieć sieci Dockera z podsiecią VPN. Nakładanie się daje awarię, która wygląda dokładnie jak zepsuty serwer DNS.

Sprawdź wewnątrz kontenera

Testuj za pomocą getent hosts db.internal wewnątrz kontenera, a nie przeglądarką czy środowiskiem uruchomieniowym języka, bo one stosują własną politykę DNS i własny cache. Jeśli getent rozwiąże nazwę, a aplikacja nadal zawodzi, resolver jest już poprawny, a pozostały problem jest na poziomie aplikacji. Jeśli nie rozwiąże, krok DNS nie jest zakończony.

Po zmianie ustawień DNS utwórz kontener ponownie. Edycja /etc/resolv.conf w działającym kontenerze znika razem z nim i ukrywa problem konfiguracji dokładnie na tyle, ile ktoś potrzebuje na jego ponowne uruchomienie.

Powiązane artykuły