Docker-Volume-Mount schlägt nach VPN-Verbindung fehl: Prüfe den Daemon
Dein Bind-Mount ist in Ordnung. Ein VPN ändert, welcher Daemon dem Client antwortet, also gib den Endpoint aus, beweise den Pfad dort und höre auf, das Volume zu bearbeiten.
Fast jede Beschreibung dieses Problems gibt dem Volume die Schuld, und genau deshalb dauert die Reparatur so lange. Du hattest einen Bind-Mount, der funktionierte, das Firmen-VPN verband sich, und docker compose up schlägt jetzt fehl, mit einem fehlenden Quellpfad, einem leeren Verzeichnis oder einem Mount, den die Engine nicht anlegen will. In den Umgebungen, die ich aufgeräumt habe, war die Compose-Datei unverändert und der Pfad korrekt. Geändert hatte sich, welcher Daemon die Anfrage erhielt, und der Mount-Fehler war nur die erste Stelle, an der dieser Unterschied sichtbar wurde.
Das Volume hat sich nie bewegt; die Anfrage schon
Ein -v /srv/app:/app Flag ist keine Verzeichniskopie, die deine Shell ausführt. Der Client macht daraus eine API-Anfrage, und der Daemon, der antwortet, löst /srv/app gegen sein eigenes Dateisystem auf. Wenn beide Seiten auf demselben Kernel laufen, ist das der Pfad, den du im Dateimanager siehst. Ändert sich der Endpoint, wird dieselbe Zeichenkette auf einer Maschine nachgeschlagen, die noch nie von deinem Projektverzeichnis gehört hat, und der Daemon meldet die Quelle als fehlend oder legt still ein leeres Verzeichnis an ihrer Stelle an.
Das ist auch der Grund, warum ein benanntes Volume weiter funktioniert, ein Bind-Mount aber nicht. -v appdata:/app benennt Speicher, den der Daemon besitzt, also muss kein Host-Pfad an einer bestimmten Stelle existieren. Wenn der Wechsel eines Dienstes von einem Bind-Mount zu einem benannten Volume den Fehler verschwinden lässt, hast du das Problem nicht behoben. Du hast bestätigt, dass Client und Daemon sich uneinig darüber sind, welchem Dateisystem der Pfad gehört, und diese Uneinigkeit kehrt zurück, sobald du wieder ein echtes Host-Verzeichnis brauchst.
Gib den Endpoint aus, bevor du den Mount anfasst
Mehrere Einstellungen können den Client auf einen Endpoint zeigen, und sie stimmen nicht immer überein: ein --context Flag, DOCKER_CONTEXT, DOCKER_HOST in der aktuellen Shell und der in der Client-Konfiguration gespeicherte Kontext. Statt über die Rangfolge nachzudenken, gib alle aus und vergleiche die Antworten.
docker context show
docker context ls
docker version
docker info --format "{{.Name}} {{.OperatingSystem}} {{.ServerVersion}}"
Die Client-Konfiguration liegt unter ~/.docker/config.json unter Linux und macOS und unter %USERPROFILE%\.docker\config.json unter Windows, und ein im aktuellen Terminal exportierter Wert überschreibt den gespeicherten nur für diese Sitzung. Ist der Endpoint ein Hostname statt eines lokalen Sockets, entscheiden Namensauflösung und Routen, wo er landet, und genau die schreibt ein VPN-Client um. Ein Tunnel, der eine Route hinzufügt oder den Resolver austauscht, kann einen Namen, der früher diesen Laptop meinte, an eine Adresse im Firmennetz schicken.
Vergleiche den Zustand statt die Konfiguration. Führe docker ps -a und docker images bei getrenntem Tunnel aus, dann noch einmal mit aktivem. Eine andere Containerliste ist ein stärkerer Beweis als jede Konfigurationsdatei, denn sie zeigt, dass ein anderer Daemon deine Anfrage beantwortet hat.
Frage den Daemon, ob der Pfad dort existiert
Wenn du weißt, welchen Daemon du erreicht hast, lass ihn in das Verzeichnis schauen. Die Form --mount schlägt mit einer klareren Meldung fehl als das kurze Flag, weil sie die Quelle prüft, bevor sie den Container startet:
docker run --rm --mount type=bind,source=/srv/app,target=/app alpine ls -la /app
Meldet sie die Quelle als fehlend, lege sie auf der Maschine an, die geantwortet hat, oder zeige den Dienst auf ein benanntes Volume und kopiere die Daten hinein. Was du nicht tun solltest: Volumes neu erstellen und die Engine neu installieren, bevor diese Prüfung erfolgt ist. Diese Aktionen verändern die Umgebung so weit, dass sie die Diskrepanz verbergen, während sie bestehen bleibt.
Ein weiterer Pfad läuft ganz woanders: Ein Image zu ziehen ist Daemon-Arbeit, keine Client-Arbeit. Ein erfolgreicher Pull beweist nur, dass der Daemon eine Registry erreicht, und ein funktionierender Bind-Mount nur, dass ein Pfad aufgelöst wurde. Teste jeden Pfad dort, wo er tatsächlich ausgeführt wird, sonst verbringst du einen Nachmittag mit dem falschen.
Intranet-Namen scheitern aus einem anderen Grund
Die zweite Hälfte desselben Berichts ist meist, dass der Container intranet.corp.examplenicht erreicht. Das ist ein separater Mechanismus, kein zweites Volume-Problem. Ein Container bekommt seine /etc/resolv.conf beim Start, erzeugt aus den Resolver-Einstellungen des Daemons, also erscheint ein DNS-Server, den das VPN nach dem Erstellen des Containers hinzugefügt hat, dort erst, wenn der Container neu erstellt wird.
Der eingebettete Resolver von Docker in einem benutzerdefinierten Netzwerk leitet externe Abfragen an die konfigurierten Server des Hosts weiter, was hilft, wenn das VPN den Host-Resolver umschreibt, und schadet, wenn Split-DNS eine interne Zone an einen Server schickt, den der Daemon nicht mehr sieht. Ein enges, explizites Mapping umgeht die Diskussion für Namen, die sich nie ändern:
services:
web:
extra_hosts:
- "intranet.corp.example:10.20.30.40"
Das schreibt einen Eintrag in die hosts-Datei des Containers, sodass der Container nie etwas über den Tunnel erfährt, und es friert außerdem die Adresse ein. Wenn der interne Host umzieht, bleibt der Eintrag falsch, bis jemand die Compose-Datei bearbeitet. Verwende es für ein festes Gerät oder eine festgepinnte Datenbank und lass DNS die Namen verwalten, die sich bewegen.
Was eine Neuinstallation tatsächlich ändert
Eine Neuinstallation von Docker Desktop erstellt die VM, den Socket und die Kontextliste neu, und der Mount funktioniert wieder. Dieses Ergebnis ist real und lehrt nichts, weshalb derselbe Fehler nach dem nächsten VPN-Update zurückkehrt. Die Neuinstallation ersetzte den Endpoint, den der Client benutzte; sie brachte den Pfad, den dein Projekt nennt, nicht mit dem Dateisystem in Einklang, das der Daemon tatsächlich liest.
Meine Reihenfolge ist kurz. Bestätige, welchen Endpoint der Client verwenden wird. Bestätige, welcher Daemon geantwortet hat, indem du Containerlisten vergleichst. Bitte diesen Daemon, den Quellpfad aufzulisten. Erst dann bearbeite den Mount, füge einen hosts-Eintrag hinzu oder ändere einen Volume-Typ. Wenn du die Compose-Datei für ein Team pflegst, das über ein VPN arbeitet, bevorzuge benannte Volumes für Daten, die der Daemon besitzen sollte, damit ein Host-Pfad nie Teil des Vertrags wird.