Montowanie wolumenu Dockera zawodzi po połączeniu VPN: sprawdź demon
Twój bind mount jest w porządku. VPN zmienia, który demon odpowiada klientowi, więc wypisz endpoint, udowodnij ścieżkę tam i przestań edytować wolumen.
Niemal każdy tekst o tym problemie obwinia wolumen i właśnie dlatego naprawa zajmuje tyle czasu. Miałeś działający bind mount, firmowy VPN się połączył, a docker compose up teraz zawodzi z powodu brakującej ścieżki źródłowej, pustego katalogu albo montowania, którego silnik odmawia utworzyć. W środowiskach, które porządkowałem, plik Compose nie był zmieniony, a ścieżka była poprawna. Zmieniło się to, który demon otrzymał żądanie, a błąd montowania był tylko pierwszym miejscem, w którym ta różnica stała się widoczna.
Wolumen nigdy się nie przesunął; przesunęło się żądanie
Flaga -v /srv/app:/app nie jest kopią katalogu wykonywaną przez twoją powłokę. Klient zamienia ją na żądanie API, a odpowiadający demon rozwiązuje /srv/app względem własnego systemu plików. Gdy obie strony działają na tym samym jądrze, ta ścieżka jest tą, którą widzisz w menedżerze plików. Gdy endpoint się zmienia, ten sam ciąg jest wyszukiwany na maszynie, która nigdy nie słyszała o katalogu twojego projektu, a demon albo zgłasza źródło jako brakujące, albo po cichu tworzy w jego miejscu pusty katalog.
To także dlatego nazwany wolumen nadal działa, a bind mount nie. -v appdata:/app nazywa magazyn, który należy do demona, więc żadna ścieżka hosta nie musi istnieć w konkretnym miejscu. Jeśli zmiana jednej usługi z bind mountu na nazwany wolumen sprawia, że błąd znika, nie naprawiłeś problemu. Potwierdziłeś, że klient i demon nie zgadzają się co do tego, do którego systemu plików należy ścieżka, a ta niezgodność wraca w chwili, gdy znów potrzebujesz prawdziwego katalogu hosta.
Wypisz endpoint, zanim dotkniesz montowania
Kilka ustawień może wskazać klientowi endpoint, i nie zawsze się zgadzają: flaga --context , DOCKER_CONTEXT, DOCKER_HOST w bieżącej powłoce oraz kontekst zapisany w konfiguracji klienta. Zamiast rozważać pierwszeństwo, wypisz je wszystkie i porównaj odpowiedzi.
docker context show
docker context ls
docker version
docker info --format "{{.Name}} {{.OperatingSystem}} {{.ServerVersion}}"
Konfiguracja klienta znajduje się w ~/.docker/config.json w systemach Linux i macOS oraz w %USERPROFILE%\.docker\config.json w systemie Windows, a wartość wyeksportowana w bieżącym terminalu zastępuje zapisaną tylko na czas tej sesji. Jeśli endpoint jest nazwą hosta, a nie lokalnym gniazdem, o tym, gdzie wyląduje, decydują rozwiązywanie nazw i trasy, i to właśnie przepisuje klient VPN. Tunel, który dodaje trasę lub podmienia resolver, może wysłać nazwę, która kiedyś oznaczała ten laptop, na adres wewnątrz sieci firmowej.
Porównuj stan, a nie konfigurację. Uruchom docker ps -a i docker images z wyłączonym tunelem, a potem ponownie z włączonym. Inna lista kontenerów jest mocniejszym dowodem niż jakikolwiek plik konfiguracyjny, bo pokazuje, że na twoje żądanie odpowiedział inny demon.
Zapytaj demona, czy ścieżka tam istnieje
Gdy już wiesz, do którego demona dotarłeś, każ mu spojrzeć na katalog. --mount forma zawodzi z jaśniejszym komunikatem niż krótka flaga, bo sprawdza źródło, zanim uruchomi kontener:
docker run --rm --mount type=bind,source=/srv/app,target=/app alpine ls -la /app
Jeśli zgłasza źródło jako brakujące, utwórz je na maszynie, która odpowiedziała, albo wskaż usługę na nazwany wolumen i skopiuj tam dane. Czego nie powinieneś robić, to odtwarzanie wolumenów i reinstalacja silnika przed tym sprawdzeniem. Te działania zmieniają środowisko na tyle, że ukrywają niezgodność, pozostawiając ją na miejscu.
Jeszcze jedna ścieżka przebiega zupełnie gdzie indziej: pobieranie obrazu to praca demona, nie klienta. Udane pobranie dowodzi tylko, że demon dociera do registry, a działający bind mount tylko, że ścieżka została rozwiązana. Testuj każdą ścieżkę tam, gdzie naprawdę się wykonuje, inaczej spędzisz popołudnie na niewłaściwej.
Nazwy intranetowe zawodzą z innego powodu
Druga połowa tego samego zgłoszenia to zwykle to, że kontener nie może dotrzeć do intranet.corp.example. To osobny mechanizm, nie drugi problem z wolumenem. Kontener otrzymuje swój /etc/resolv.conf przy starcie, wygenerowany z ustawień resolvera demona, więc serwer DNS dodany przez VPN po utworzeniu kontenera nie pojawi się tam, dopóki kontener nie zostanie odtworzony.
Wbudowany resolver Dockera w sieci zdefiniowanej przez użytkownika przekazuje zapytania zewnętrzne do skonfigurowanych serwerów hosta, co pomaga, gdy VPN przepisuje resolver hosta, i szkodzi, gdy dzielony DNS wysyła strefę wewnętrzną do serwera, którego demon już nie widzi. Wąskie, jawne mapowanie omija spór o nazwy, które nigdy się nie zmieniają:
services:
web:
extra_hosts:
- "intranet.corp.example:10.20.30.40"
To zapisuje wpis w pliku hosts kontenera, więc kontener nigdy nie dowiaduje się niczego o tunelu, a także zamraża adres. Gdy wewnętrzny host się przenosi, wpis pozostaje błędny, dopóki ktoś nie zmodyfikuje pliku Compose. Używaj go dla stałego urządzenia lub przypiętej bazy danych, a nazwy, które się przemieszczają, zostaw DNS-owi.
Co naprawdę zmienia reinstalacja
Reinstalacja Docker Desktop odtwarza maszynę wirtualną, gniazdo i listę kontekstów, a montowanie znów zaczyna działać. Ten wynik jest prawdziwy i niczego nie uczy, dlatego ta sama usterka wraca po kolejnej aktualizacji VPN. Reinstalacja zastąpiła endpoint, którego używał klient; nie pogodziła ścieżki nazywanej przez twój projekt z systemem plików, który demon naprawdę czyta.
Mój porządek pracy jest krótki. Potwierdź, którego endpointu użyje klient. Potwierdź, który demon odpowiedział, porównując listy kontenerów. Poproś ten demon o wypisanie ścieżki źródłowej. Dopiero potem edytuj montowanie, dodaj wpis hosts albo zmień typ wolumenu. Jeśli utrzymujesz plik Compose dla zespołu pracującego przez VPN, preferuj nazwane wolumeny dla danych, które powinien posiadać demon, aby ścieżka hosta nigdy nie stała się częścią umowy.