Das VPN läuft, der Browser erreicht interne Seiten, und der Container kann dieselben Namen weiterhin nicht auflösen. Eine Paketinstallation stirbt mit einem Namensauflösungsfehler wie EAI_AGAIN, oder eine Anwendung findet keinen Datenbank-Host, den der Host-Rechner ohne jede Beschwerde auflöst. Der Container nutzt nicht den Resolver, den das VPN installiert hat. Docker hat die Resolver-Konfiguration des Hosts beim Anlegen des Containers kopiert, und danach hat sie nichts erneut kopiert.

Zwei Resolver-Sichten auf einer Maschine

Unter Linux gibt Docker jedem Container beim Anlegen eine Kopie von der Resolver-Konfiguration des Hosts, filtert Loopback-Adressen heraus und betreibt einen eingebetteten DNS-Server unter 127.0.0.11, der Abfragen nach außen weiterleitet. Ein VPN-Client, der /etc/resolv.conf umschreibt, nachdem der Container gestartet wurde, ändert darin nichts. Ein Neustart des Containers hilft nur, wenn der Resolver des Hosts in diesem Moment zufällig korrekt ist.

Docker Desktop unter macOS oder Windows fügt eine Schicht hinzu, weil der Daemon in einer virtuellen Maschine lebt. Der VPN-Resolver des Hosts ist für diese VM möglicherweise nie sichtbar, sodass ein Neustart überhaupt nichts ändert. Vergleichen Sie beide Sichten, bevor Sie eine Lösung wählen: docker exec mycontainer cat /etc/resolv.conf neben der Resolver-Liste des Hosts.

Ein Container, der einen öffentlichen Resolver auflistet, während der Host einen internen auflistet, löst öffentliche Namen auf und scheitert an internen. Diese Trennung ist die Signatur dieses Problems.

Option A: den Tunnel-Resolver pro Container übergeben

Docker akzeptiert DNS-Einstellungen pro Container, und das ist die kleinste Änderung, die funktioniert. Lesen Sie zuerst die Resolver-Adressen des VPN: scutil --dns unter macOS, resolvectl status oder die eigene Statusausgabe des Clients unter Linux. Starten Sie den Container dann damit, zum Beispiel docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. In Compose ist dieselbe Einstellung eine Liste unter dem Dienst, wo sie in der Versionsverwaltung liegt statt in jemandes Shell-Historie.

Ein dns-Array in /etc/docker/daemon.json gilt für jeden neuen Container, was ordentlicher klingt, als es ist. Es gilt auch, wenn der Tunnel ausgefallen ist, und ein nur über das VPN erreichbarer Resolver zerbricht dann gewöhnliche Image-Pulls. Einstellungen pro Container sind leichter zu begründen und leichter rückgängig zu machen.

Option B: den Container das Host-Netzwerk teilen lassen

Host-Netzwerk umgeht die Kopie vollständig, weil der Container den Resolver des Hosts und den Tunnel des Hosts nutzt. Es beseitigt außerdem die Netzwerkisolierung, die Sie wahrscheinlich wollten, und verhält sich unter Docker Desktop nicht gleich. Unter Linux ist es die pragmatische Wahl für ein Einmalwerkzeug, das interne Namen auflösen muss.

Für Builds gilt keine der beiden Optionen, da Build-Schritte keine Laufzeit-Flags erben. Bauen Sie mit Host-Netzwerk, wo die Plattform es erlaubt, oder halten Sie die Abhängigkeitsinstallation in einer Stufe, die den Tunnel nicht braucht.

Was keine der beiden Optionen behebt

Eine DNS-Adresse ist nutzlos, wenn der Container keine Route dorthin hat. Der VPN-Resolver sitzt normalerweise im Adressraum des Tunnels, also braucht der Container einen Weg zu diesem Präfix. Dockers Standard-Bridge leitet normalerweise über den Host nach außen, und das genügt, wenn der Host die Tunnel-Route hat und Weiterleitung aktiviert ist. Eigene Bridge-Netze mit eigenen Adresspools können mit dem VPN-Subnetz kollidieren, und dann gehen Abfragen ganz woanders hin.

Prüfen Sie das Subnetz des Docker-Netzes gegen das Subnetz des VPN, bevor Sie den Resolver selbst debuggen. Eine Überlappung erzeugt einen Fehler, der genau wie ein defekter DNS-Server aussieht.

Im Container verifizieren

Testen Sie mit getent hosts db.internal im Container statt mit einem Browser oder einer Sprachlaufzeit, weil diese ihre eigene DNS-Politik und ihr eigenes Caching anwenden. Wenn getent den Namen auflöst und die Anwendung weiterhin scheitert, ist der Resolver jetzt korrekt und das verbleibende Problem liegt auf Anwendungsebene. Wenn er ihn nicht auflöst, ist der DNS-Schritt nicht abgeschlossen.

Erzeugen Sie den Container neu, nachdem Sie seine DNS-Einstellungen geändert haben. Das Bearbeiten von /etc/resolv.conf in einem laufenden Container verschwindet mit ihm und verdeckt das Konfigurationsproblem genau so lange, wie jemand zum Neustart braucht.

Ähnliche Artikel