VPN běží, prohlížeč se dostane na interní stránky, a kontejner přesto nedokáže přeložit stejná jména. Instalace balíčku umírá na chybu překladu jmen, jako je EAI_AGAIN, nebo aplikace nenajde hostitele databáze, kterého hostitelský stroj přeloží bez jediné stížnosti. Kontejner nepoužívá resolver, který VPN nainstalovala. Docker zkopíroval konfiguraci resolveru hostitele při vytvoření kontejneru a poté ji už nic znovu nezkopírovalo.

Dva pohledy na resolver na jednom stroji

V Linuxu dá Docker každému kontejneru kopii konfigurace resolveru hostitele v okamžiku vytvoření, odfiltruje adresy loopback a spouští vestavěný server DNS na 127.0.0.11, který přeposílá dotazy ven. Klient VPN, který přepíše /etc/resolv.conf poté, co se kontejner spustil, uvnitř nic nezmění. Restart kontejneru pomůže jen tehdy, když je resolver hostitele v tu chvíli náhodou správný.

Docker Desktop na macOS nebo Windows přidává vrstvu, protože démon žije ve virtuálním stroji. Resolver VPN hostitele nemusí být pro tento VM nikdy viditelný, takže restart nezmění vůbec nic. Porovnejte oba pohledy, než zvolíte opravu: docker exec mycontainer cat /etc/resolv.conf vedle seznamu resolverů hostitele.

Kontejner, který uvádí veřejný resolver, zatímco hostitel uvádí interní, bude přeložit veřejná jména a selže na interních. Toto rozdělení je podpisem tohoto problému.

Možnost A: předat resolver tunelu pro každý kontejner

Docker přijímá nastavení DNS pro každý kontejner, což je nejmenší změna, která funguje. Nejprve si přečtěte adresy resolveru VPN: scutil --dns na macOS, resolvectl status nebo vlastní stavový výstup klienta na Linuxu. Potom kontejner s nimi spusťte, například docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. V Compose je stejné nastavení seznam pod službou, kde žije ve veršovacím systému místo v něčí historii shellu.

Pole dns v /etc/docker/daemon.json platí pro každý nový kontejner, což zní úhledněji, ale není. Platí i tehdy, když je tunel mimo provoz, a resolver dostupný jen přes VPN pak rozbije běžné stahování imagí. Nastavení pro jednotlivý kontejner se snáze zdůvodňuje a snáze vrací.

Možnost B: nechte kontejner sdílet síť hostitele

Síť hostitele kopii úplně obchází, protože kontejner používá resolver hostitele a tunel hostitele. Také odstraňuje síťovou izolaci, kterou jste pravděpodobně chtěli, a pod Docker Desktop se nechová stejně. V Linuxu je to pragmatická volba pro jednorázový nástroj, který musí překládat interní jména.

Pro buildy neplatí ani jedna možnost, protože kroky buildu nedědí přepínače doby běhu. Buildte se sítí hostitele tam, kde to platforma dovolí, nebo držte instalaci závislostí ve fázi, která tunel nepotřebuje.

Co ani jedna možnost neopraví

Adresa DNS je k ničemu, pokud k ní kontejner nemá trasu. Resolver VPN obvykle sídlí uvnitř adresního prostoru tunelu, takže kontejner potřebuje cestu k tomuto prefixu. Výchozí most Dockeru obvykle směruje ven přes hostitele, což stačí, když hostitel má trasu tunelu a přeposílání je zapnuté. Vlastní mostové sítě s vlastními fondy adres se mohou srazit s podsítí VPN, a pak dotazy jdou úplně jinam.

Než začnete ladit samotný resolver, porovnejte podsíť sítě Dockeru s podsítí VPN. Překrytí vytváří selhání, které vypadá přesně jako rozbitý server DNS.

Ověřte uvnitř kontejneru

Testujte pomocí getent hosts db.internal uvnitř kontejneru, ne prohlížečem nebo jazykovým runtime, protože ty uplatňují vlastní politiku DNS a vlastní kešování. Pokud getent jméno přeloží a aplikace stále selhává, resolver je nyní správný a zbývající problém je na úrovni aplikace. Pokud ho nepřeloží, krok DNS není dokončen.

Po změně nastavení DNS kontejner znovu vytvořte. Úprava /etc/resolv.conf uvnitř běžícího kontejneru zmizí spolu s ním a skryje problém konfigurace přesně na tak dlouho, jak dlouho někomu trvá ho restartovat.

Související články