Zašto Docker kontejneri ignorišu VPN-ov DNS rezolver
Kontejner kopira rezolver hosta pri pokretanju, pa VPN koji kasnije prepisuje DNS ostaje nevidljiv unutar njega. Prenesi rezolver eksplicitno.
VPN radi, pregledač dolazi do internih stranica, a kontejner i dalje ne može da razreši ista imena. Instalacija paketa pada sa greškom razrešavanja imena kao što je EAI_AGAIN, ili aplikacija ne može da pronađe host baze podataka koji host mašina razrešava bez ikakve žalbe. Kontejner ne koristi rezolver koji je VPN instalirao. Docker je kopirao konfiguraciju rezolvera hosta kada je kontejner stvoren, i ništa je posle toga nije ponovo kopiralo.
Dva pogleda na rezolver na istoj mašini
Na Linuxu Docker svakom kontejneru daje kopiju konfiguracije rezolvera hosta u trenutku stvaranja, filtrira loopback adrese i pokreće ugrađeni DNS server na 127.0.0.11 koji prosleđuje upite ka spolja. VPN klijent koji prepiše /etc/resolv.conf nakon što je kontejner pokrenut ne menja ništa unutar njega. Ponovno pokretanje kontejnera pomaže samo ako je rezolver hosta u tom trenutku slučajno ispravan.
Docker Desktop na macOS-u ili Windowsu dodaje sloj, jer daemon živi u virtuelnoj mašini. Rezolver VPN-a na hostu možda nikada neće biti vidljiv toj VM, pa ponovno pokretanje ne menja baš ništa. Uporedi dva pogleda pre nego što izabereš rešenje: docker exec mycontainer cat /etc/resolv.conf pored liste rezolvera hosta.
Kontejner koji navodi javni rezolver dok host navodi interni razrešavaće javna imena i padati na internim. Ta podela je potpis ovog problema.
Opcija A: preneti rezolver tunela po kontejneru
Docker prihvata DNS postavke po kontejneru, što je najmanja promena koja funkcioniše. Prvo pročitaj adrese VPN rezolvera: scutil --dns na macOS-u, resolvectl status ili sopstveni statusni izlaz klijenta na Linuxu. Zatim pokreni kontejner sa njima, na primer docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. U Compose-u je ista postavka lista ispod servisa, gde živi u kontroli verzija umesto u nečijoj istoriji komandi.
Niz dns u /etc/docker/daemon.json primenjuje se na svaki novi kontejner, što zvuči urednije nego što jeste. Primenjuje se i kada je tunel pao, a rezolver dostupan samo kroz VPN tada kvari obično povlačenje slika. Postavke po kontejneru lakše je obrazložiti i lakše poništiti.
Opcija B: neka kontejner deli mrežu hosta
Umrežavanje hosta u potpunosti zaobilazi kopiju, jer kontejner koristi rezolver hosta i tunel hosta. Ono uklanja i mrežnu izolaciju koju si verovatno želeo, i ne ponaša se isto pod Docker Desktopom. Na Linuxu je to pragmatičan izbor za jednokratni alat koji mora da razrešava interna imena.
Za buildove ne važi nijedna opcija, jer koraci builda ne nasleđuju zastavice vremena izvršavanja. Gradi sa umrežavanjem hosta gde platforma to dozvoljava, ili drži instalaciju zavisnosti u fazi kojoj tunel nije potreban.
Šta nijedna opcija ne popravlja
DNS adresa je beskorisna ako kontejner nema rutu do nje. Rezolver VPN-a obično sedi unutar adresnog prostora tunela, pa kontejneru treba put do tog prefiksa. Dockerov podrazumevani most obično usmerava napolje kroz host, što je dovoljno kada host ima rutu tunela i kada je prosleđivanje omogućeno. Prilagođene mostovne mreže sa sopstvenim bazenima adresa mogu se sudariti sa VPN podmrežom, a tada upiti odlaze sasvim negde drugde.
Proveri podmrežu Docker mreže prema VPN podmreži pre nego što otklanjaš greške u samom rezolveru. Preklapanje proizvodi kvar koji izgleda tačno kao pokvaren DNS server.
Proveri unutar kontejnera
Testiraj sa getent hosts db.internal unutar kontejnera, a ne pregledačem ili jezičkim runtimeom, jer oni primenjuju sopstvenu DNS politiku i sopstveno keširanje. Ako getent razreši ime a aplikacija i dalje pada, rezolver je sada ispravan i preostali problem je na nivou aplikacije. Ako ga ne razreši, DNS korak nije završen.
Ponovo kreiraj kontejner nakon promene njegovih DNS postavki. Uređivanje /etc/resolv.conf unutar pokrenutog kontejnera nestaje sa njim i skriva problem konfiguracije tačno onoliko koliko nekome treba da ga ponovo pokrene.