Quasi ogni testo su questo problema dà la colpa al volume, ed è proprio per questo che la correzione richiede così tanto tempo. Avevi un bind mount che funzionava, la VPN aziendale si è connessa e docker compose up ora fallisce con un percorso sorgente mancante, una directory vuota o un mount che il motore rifiuta di creare. Negli ambienti che ho ripulito, il file Compose non era cambiato e il percorso era corretto. Quello che era cambiato era quale daemon riceveva la richiesta, e l'errore di mount era solo il primo punto in cui quella differenza diventava visibile.

Il volume non si è mai spostato; si è spostata la richiesta

L'opzione -v /srv/app:/app non è una copia di directory eseguita dalla tua shell. Il client la trasforma in una richiesta API, e il daemon che risponde risolve /srv/app rispetto al proprio file system. Quando entrambi i lati girano sullo stesso kernel, quel percorso è quello che vedi nel gestore di file. Quando l'endpoint cambia, la stessa stringa viene cercata su una macchina che non ha mai sentito parlare della directory del tuo progetto, e il daemon segnala la sorgente come mancante o crea silenziosamente una directory vuota al suo posto.

È anche per questo che un volume con nome continua a funzionare mentre un bind mount no. -v appdata:/app nomina uno spazio di archiviazione che il daemon possiede, quindi nessun percorso host deve esistere in un punto preciso. Se sostituire un servizio da un bind mount a un volume con nome fa sparire l'errore, non hai risolto il problema. Hai confermato che il client e il daemon non sono d'accordo su a quale file system appartenga il percorso, e quel disaccordo torna nel momento in cui hai di nuovo bisogno di una vera directory host.

Stampa l'endpoint prima di toccare il mount

Diverse impostazioni possono puntare il client verso un endpoint, e non sempre sono d'accordo: l'opzione --context , DOCKER_CONTEXT, DOCKER_HOST nella shell corrente e il contesto salvato nella configurazione del client. Invece di ragionare sulla precedenza, stampali tutti e confronta le risposte.

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

La configurazione del client si trova in ~/.docker/config.json su Linux e macOS e in %USERPROFILE%\.docker\config.json su Windows, e un valore esportato nel terminale corrente sostituisce quello salvato solo per quella sessione. Se l'endpoint è un nome host invece di un socket locale, la risoluzione dei nomi e le rotte decidono dove atterra, e sono esattamente ciò che un client VPN riscrive. Un tunnel che aggiunge una rotta o cambia il resolver può inviare un nome che prima indicava questo portatile a un indirizzo all'interno della rete aziendale.

Confronta lo stato invece della configurazione. Esegui docker ps -a e docker images con il tunnel disattivato, poi di nuovo attivo. Un elenco di container diverso è una prova più solida di qualsiasi file di configurazione, perché mostra che un altro daemon ha risposto alla tua richiesta.

Chiedi al daemon se il percorso esiste lì

Una volta che sai quale daemon hai raggiunto, fallo guardare nella directory. La forma --mount fallisce con un messaggio più chiaro dell'opzione breve, perché convalida la sorgente prima di avviare il container:

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

Se segnala la sorgente come mancante, creala sulla macchina che ha risposto, oppure punta il servizio a un volume con nome e copia i dati lì. Quello che non dovresti fare è ricreare i volumi e reinstallare il motore prima di questo controllo. Quelle azioni cambiano l'ambiente abbastanza da nascondere la discrepanza lasciandola al suo posto.

Un altro percorso gira in un posto completamente diverso: scaricare un'immagine è lavoro del daemon, non del client. Un download riuscito dimostra solo che il daemon può raggiungere un registry, e un bind mount funzionante solo che un percorso è stato risolto. Prova ogni percorso dove viene effettivamente eseguito, altrimenti passerai un pomeriggio su quello sbagliato.

I nomi intranet falliscono per un altro motivo

La seconda metà dello stesso rapporto di solito è che il container non riesce a raggiungere intranet.corp.example. Questo è un meccanismo separato, non un secondo problema di volume. Un container ottiene il suo /etc/resolv.conf all'avvio, generato dalle impostazioni del resolver del daemon, quindi un server DNS che la VPN ha aggiunto dopo la creazione del container non apparirà lì finché il container non viene ricreato.

Il resolver integrato di Docker su una rete definita dall'utente inoltra le query esterne ai server configurati dell'host, il che aiuta quando la VPN riscrive il resolver dell'host e danneggia quando il DNS diviso invia una zona interna a un server che il daemon non vede più. Una mappatura stretta ed esplicita aggira la discussione per i nomi che non cambiano mai:

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

Questo scrive una voce nel file hosts del container, così il container non impara nulla del tunnel, e congela anche l'indirizzo. Quando l'host interno si sposta, la voce resta sbagliata finché qualcuno non modifica il file Compose. Usala per un dispositivo fisso o un database bloccato, e lascia che il DNS gestisca i nomi che si muovono.

Cosa cambia realmente una reinstallazione

Reinstallare Docker Desktop ricrea la VM, il socket e l'elenco dei contesti, e il mount ricomincia a funzionare. Quel risultato è reale e non insegna nulla, ed è per questo che lo stesso guasto torna dopo il successivo aggiornamento VPN. La reinstallazione ha sostituito l'endpoint che il client usava; non ha riconciliato il percorso che il tuo progetto nomina con il file system che il daemon legge davvero.

Il mio ordine di lavoro è breve. Conferma quale endpoint userà il client. Conferma quale daemon ha risposto confrontando gli elenchi dei container. Chiedi a quel daemon di elencare il percorso sorgente. Solo allora modifica il mount, aggiungi una voce hosts o cambia un tipo di volume. Se mantieni il file Compose per un team che lavora su VPN, preferisci i volumi con nome per i dati che il daemon dovrebbe possedere, così che un percorso host non diventi mai parte del contratto.

Articoli correlati