Téměř každý text o tomto problému obviňuje svazek, a právě proto oprava trvá tak dlouho. Měli jste bind mount, který fungoval, firemní VPN se připojila a docker compose up nyní selhává s chybějící cestou ke zdroji, prázdným adresářem nebo připojením, které engine odmítá vytvořit. V prostředích, která jsem uklízel, se soubor Compose nezměnil a cesta byla správná. Změnilo se to, který daemon požadavek dostal, a chyba připojení byla jen prvním místem, kde se tento rozdíl stal viditelným.

Svazek se nikdy nepohnul; požadavek ano

Přepínač -v /srv/app:/app není kopie adresáře prováděná vaším shellem. Klient z něj udělá požadavek API a daemon, který odpovídá, vyhodnocuje /srv/app vůči svému vlastnímu souborovému systému. Když obě strany běží na stejném jádru, je tato cesta ta, kterou vidíte ve správci souborů. Když se endpoint změní, stejný řetězec se hledá na stroji, který o adresáři vašeho projektu nikdy neslyšel, a daemon buď oznámí zdroj jako chybějící, nebo na jeho místě tiše vytvoří prázdný adresář.

To je také důvod, proč pojmenovaný svazek funguje dál, zatímco bind mount ne. -v appdata:/app pojmenovává úložiště, které daemon vlastní, takže žádná cesta hostitele nemusí existovat na konkrétním místě. Pokud výměna jedné služby z bind mountu za pojmenovaný svazek způsobí, že chyba zmizí, problém jste neopravili. Potvrdili jste, že klient a daemon se neshodují v tom, kterému souborovému systému cesta patří, a tento nesouhlas se vrátí ve chvíli, kdy znovu potřebujete skutečný adresář hostitele.

Vypište endpoint, než se dotknete připojení

Několik nastavení může nasměrovat klienta na endpoint a ne vždy se shodují: přepínač --context , DOCKER_CONTEXT, DOCKER_HOST v aktuálním shellu a kontext uložený v konfiguraci klienta. Místo uvažování o prioritě vypište všechny a porovnejte odpovědi.

docker context show
docker context ls
docker version
docker info --format "{{.Name}} {{.OperatingSystem}} {{.ServerVersion}}"

Konfigurace klienta je v ~/.docker/config.json na Linuxu a macOS a v %USERPROFILE%\.docker\config.json na Windows a hodnota exportovaná v aktuálním terminálu přepisuje uloženou jen pro tuto relaci. Pokud je endpoint název hostitele místo místního socketu, rozhoduje o tom, kam dopadne, překlad názvů a trasy, a právě ty klient VPN přepisuje. Tunel, který přidá trasu nebo vymění resolver, může poslat název, který dřív znamenal tento notebook, na adresu uvnitř firemní sítě.

Porovnávejte stav, ne konfiguraci. Spusťte docker ps -a a docker images s vypnutým tunelem a pak znovu se zapnutým. Jiný seznam kontejnerů je silnější důkaz než jakýkoli konfigurační soubor, protože ukazuje, že na váš požadavek odpověděl jiný daemon.

Zeptejte se daemona, zda tam cesta existuje

Když víte, ke kterému daemonovi jste se dostali, donuťte ho podívat se na adresář. Forma --mount selhává s jasnější zprávou než krátký přepínač, protože ověřuje zdroj dřív, než spustí kontejner:

docker run --rm --mount type=bind,source=/srv/app,target=/app alpine ls -la /app

Pokud oznámí zdroj jako chybějící, vytvořte ho na stroji, který odpověděl, nebo nasměrujte službu na pojmenovaný svazek a zkopírujte data tam. Co byste dělat neměli, je znovu vytvářet svazky a přeinstalovávat engine před touto kontrolou. Tyto akce mění prostředí natolik, že nesoulad skryjí, ale ponechají ho na místě.

Ještě jedna cesta běží úplně jinde: stahování image je práce daemona, ne klienta. Úspěšné stažení dokazuje jen, že se daemon dostane do registry, a fungující bind mount jen to, že se cesta vyhodnotila. Testujte každou cestu tam, kde se skutečně provádí, jinak strávíte odpoledne na té špatné.

Názvy z intranetu selhávají z jiného důvodu

Druhá polovina stejného hlášení bývá, že kontejner se nedostane na intranet.corp.example. To je samostatný mechanismus, ne druhý problém se svazkem. Kontejner dostane svůj /etc/resolv.conf při startu, vygenerovaný z nastavení resolveru daemona, takže server DNS, který VPN přidala po vytvoření kontejneru, se v něm neobjeví, dokud kontejner znovu nevytvoříte.

Vestavěný resolver Dockeru na uživatelsky definované síti předává externí dotazy nakonfigurovaným serverům hostitele, což pomáhá, když VPN přepisuje resolver hostitele, a škodí, když split DNS pošle interní zónu na server, který daemon už nevidí. Úzké, explicitní mapování obejde spor u názvů, které se nikdy nemění:

services:
  web:
    extra_hosts:
      - "intranet.corp.example:10.20.30.40"

Tím se zapíše záznam do souboru hosts kontejneru, takže se kontejner o tunelu nic nedozví, a také se adresa zafixuje. Když se interní hostitel přestěhuje, záznam zůstane špatný, dokud někdo neupraví soubor Compose. Použijte to pro pevné zařízení nebo přikovanou databázi a názvy, které se hýbou, nechte na DNS.

Co přeinstalace skutečně změní

Přeinstalace Docker Desktop znovu vytvoří VM, socket a seznam kontextů a připojení začne znovu fungovat. Tento výsledek je skutečný a nic nenaučí, a proto se stejná závada vrátí po další aktualizaci VPN. Přeinstalace nahradila endpoint, který klient používal; nesjednotila cestu, kterou váš projekt pojmenovává, se souborovým systémem, který daemon skutečně čte.

Můj postup je krátký. Potvrďte, který endpoint klient použije. Potvrďte, který daemon odpověděl, porovnáním seznamů kontejnerů. Požádejte toho daemona, aby vypsal cestu ke zdroji. Teprve potom upravte připojení, přidejte záznam hosts nebo změňte typ svazku. Pokud spravujete soubor Compose pro tým, který pracuje přes VPN, dávejte přednost pojmenovaným svazkům pro data, která má daemon vlastnit, aby se cesta hostitele nikdy nestala součástí kontraktu.

Související články