Miksi Docker-säiliöt jättävät VPN:n DNS-resolverin huomiotta
Säiliö kopioi isäntäkoneen resolverin käynnistyessään, joten DNS:n myöhemmin uudelleenkirjoittava VPN jää sen sisällä näkymättömäksi. Välitä resolveri eksplisiittisesti.
VPN on päällä, selain tavoittaa sisäiset sivustot, eikä säiliö silti pysty ratkaisemaan samoja nimiä. Paketin asennus kuolee nimienratkaisuvirheeseen kuten EAI_AGAIN, tai sovellus ei löydä tietokannan isäntää, jonka isäntäkone ratkaisee ilman mitään valitusta. Säiliö ei käytä resolveria, jonka VPN asensi. Docker kopioi isäntäkoneen resolverin kokoonpanon, kun säiliö luotiin, eikä mikään kopioinut sitä uudelleen sen jälkeen.
Kaksi resolverin näkymää yhdellä koneella
Linuxissa Docker antaa jokaiselle säiliölle kopion isäntäkoneen resolverin kokoonpanosta luontihetkellä, suodattaa loopback-osoitteet pois ja ajaa sisäänrakennettua DNS-palvelinta osoitteessa 127.0.0.11, joka välittää kyselyt ulospäin. VPN-asiakasohjelma, joka kirjoittaa /etc/resolv.conf uudelleen säiliön käynnistymisen jälkeen, ei muuta sen sisällä mitään. Säiliön uudelleenkäynnistys auttaa vain, jos isäntäkoneen resolveri sattuu olemaan oikein juuri sillä hetkellä.
Docker Desktop macOS:ssä tai Windowsissa lisää kerroksen, koska daemon elää virtuaalikoneessa. Isäntäkoneen VPN-resolveri ei välttämättä ole koskaan näkyvissä sille VM:lle, joten uudelleenkäynnistys ei muuta yhtään mitään. Vertaa kahta näkymää ennen korjauksen valintaa: docker exec mycontainer cat /etc/resolv.conf isäntäkoneen resolveriluettelon vieressä.
Säiliö, joka luettelee julkisen resolverin, kun isäntäkone luettelee sisäisen, ratkaisee julkiset nimet ja epäonnistuu sisäisissä. Tämä jakautuma on tämän ongelman allekirjoitus.
Vaihtoehto A: välitä tunnelin resolveri säiliökohtaisesti
Docker hyväksyy DNS-asetukset säiliökohtaisesti, ja se on pienin toimiva muutos. Lue ensin VPN:n resolveriosoitteet: scutil --dns macOS:ssä, resolvectl status tai asiakasohjelman oma tilatuloste Linuxissa. Käynnistä säiliö sitten niiden kanssa, esimerkiksi docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. Composessa sama asetus on palvelun alla oleva luettelo, jossa se elää versionhallinnassa eikä jonkun shell-historiassa.
Taulukko dns tiedostossa /etc/docker/daemon.json koskee jokaista uutta säiliötä, mikä kuulostaa siistimmältä kuin on. Se koskee myös silloin, kun tunneli on alhaalla, ja silloin vain VPN:n kautta tavoitettava resolveri rikkoo tavalliset imagen lataukset. Säiliökohtaisia asetuksia on helpompi perustella ja helpompi perua.
Vaihtoehto B: anna säiliön jakaa isäntäkoneen verkko
Isäntäkoneen verkko ohittaa kopion kokonaan, koska säiliö käyttää isäntäkoneen resolveria ja isäntäkoneen tunnelia. Se poistaa myös verkon eristyksen, jota todennäköisesti halusit, eikä se käyttäydy samoin Docker Desktopissa. Linuxissa se on pragmaattinen valinta kertakäyttöiselle työkalulle, jonka täytyy ratkaista sisäisiä nimiä.
Buildien kohdalla kumpikaan vaihtoehto ei päde, koska build-vaiheet eivät peri ajonaikaisia lippuja. Rakenna isäntäkoneen verkolla siellä, missä alusta sen sallii, tai pidä riippuvuuksien asennus vaiheessa, joka ei tarvitse tunnelia.
Mitä kumpikaan vaihtoehto ei korjaa
DNS-osoite on hyödytön, jos säiliöllä ei ole reittiä sinne. VPN:n resolveri sijaitsee yleensä tunnelin osoiteavaruudessa, joten säiliö tarvitsee polun siihen etuliitteeseen. Dockerin oletussilta reitittää yleensä ulos isäntäkoneen kautta, ja se riittää, kun isäntäkoneella on tunnelin reitti ja edelleenvälitys on käytössä. Mukautetut siltäverkot omilla osoitealtaillaan voivat törmätä VPN:n aliverkkoon, ja silloin kyselyt menevät aivan muualle.
Tarkista Docker-verkon aliverkko VPN:n aliverkkoa vasten ennen kuin alat selvittää itse resolveria. Päällekkäisyys tuottaa vian, joka näyttää täsmälleen rikkinäiseltä DNS-palvelimelta.
Varmista säiliön sisältä
Testaa säiliön sisällä komennolla getent hosts db.internal sen sijaan, että käyttäisit selainta tai kieliajoympäristöä, koska ne soveltavat omaa DNS-käytäntöään ja omaa välimuistiaan. Jos getent ratkaisee nimen ja sovellus epäonnistuu silti, resolveri on nyt oikein ja jäljellä oleva ongelma on sovellustasolla. Jos se ei ratkaise, DNS-vaihe ei ole valmis.
Luo säiliö uudelleen, kun olet muuttanut sen DNS-asetuksia. /etc/resolv.conf-tiedoston muokkaaminen käynnissä olevan säiliön sisällä katoaa sen mukana ja piilottaa kokoonpano-ongelman täsmälleen niin pitkäksi aikaa kuin joltakulta kuluu sen uudelleenkäynnistämiseen.