La VPN è attiva, il browser raggiunge i siti interni e il container continua a non risolvere gli stessi nomi. Un’installazione di pacchetto muore con un errore di risoluzione dei nomi come EAI_AGAIN, oppure un’applicazione non trova un host di database che la macchina host risolve senza alcun reclamo. Il container non usa il resolver installato dalla VPN. Docker ha copiato la configurazione del resolver dell’host quando il container è stato creato, e nulla l’ha ricopiata dopo.

Due viste del resolver sulla stessa macchina

Su Linux, Docker dà a ogni container una copia de la configurazione del resolver dell’host al momento della creazione, filtra gli indirizzi di loopback ed esegue un server DNS incorporato su 127.0.0.11 che inoltra le query verso l’esterno. Un client VPN che riscrive /etc/resolv.conf dopo l’avvio del container non cambia nulla al suo interno. Riavviare il container aiuta solo se il resolver dell’host è per caso corretto in quel momento.

Docker Desktop su macOS o Windows aggiunge uno strato, perché il demone vive in una macchina virtuale. Il resolver VPN dell’host potrebbe non essere mai visibile a quella VM, quindi un riavvio non cambia assolutamente nulla. Confronta le due viste prima di scegliere una correzione: docker exec mycontainer cat /etc/resolv.conf accanto all’elenco dei resolver dell’host.

Un container che elenca un resolver pubblico mentre l’host ne elenca uno interno risolverà i nomi pubblici e fallirà su quelli interni. Quella separazione è la firma di questo problema.

Opzione A: passare il resolver del tunnel per container

Docker accetta impostazioni DNS per container, che è la modifica più piccola che funziona. Prima leggi gli indirizzi del resolver della VPN: scutil --dns su macOS, resolvectl status o l’output di stato del client stesso su Linux. Poi avvia il container con quegli indirizzi, per esempio docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. In Compose la stessa impostazione è un elenco sotto il servizio, dove vive nel controllo di versione invece che nella cronologia della shell di qualcuno.

Un array dns in /etc/docker/daemon.json vale per ogni nuovo container, il che suona più ordinato e non lo è. Vale anche quando il tunnel è inattivo, e allora un resolver raggiungibile solo tramite la VPN rompe i normali download delle immagini. Le impostazioni per container sono più facili da giustificare e più facili da annullare.

Opzione B: lasciare che il container condivida la rete dell’host

La rete dell’host aggira del tutto la copia, perché il container usa il resolver dell’host e il tunnel dell’host. Rimuove anche l’isolamento di rete che probabilmente volevi, e non si comporta allo stesso modo in Docker Desktop. Su Linux è la scelta pragmatica per uno strumento occasionale che deve risolvere nomi interni.

Per le build nessuna delle due opzioni si applica, dato che i passaggi di build non ereditano i flag di esecuzione. Compila con la rete dell’host dove la piattaforma lo consente, oppure tieni l’installazione delle dipendenze in una fase che non ha bisogno del tunnel.

Ciò che nessuna delle due opzioni corregge

Un indirizzo DNS è inutile se il container non ha una rotta verso di esso. Il resolver della VPN di solito si trova nello spazio di indirizzamento del tunnel, quindi il container ha bisogno di un percorso verso quel prefisso. Il bridge predefinito di Docker instrada normalmente verso l’esterno attraverso l’host, e questo basta quando l’host ha la rotta del tunnel e l’inoltro è abilitato. Reti bridge personalizzate con i propri pool di indirizzi possono entrare in collisione con la sottorete della VPN, e allora le query finiscono da tutt’altra parte.

Controlla la sottorete della rete Docker rispetto alla sottorete della VPN prima di eseguire il debug del resolver stesso. La sovrapposizione produce un guasto che sembra esattamente un server DNS guasto.

Verifica all’interno del container

Prova con getent hosts db.internal dentro il container invece che con un browser o un runtime linguistico, perché quelli applicano la propria politica DNS e la propria cache. Se getent risolve il nome e l’applicazione continua a fallire, il resolver ora è corretto e il problema rimanente è a livello di applicazione. Se non lo risolve, il passaggio DNS non è concluso.

Ricrea il container dopo aver cambiato le sue impostazioni DNS. Modificare /etc/resolv.conf dentro un container in esecuzione scompare con esso e nasconde il problema di configurazione esattamente per il tempo che serve a qualcuno per riavviarlo.

Articoli correlati