Почти всяко описание на този проблем обвинява тома и точно затова поправката отнема толкова време. Имахте bind монтиране, което работеше, корпоративният VPN се свърза и docker compose up сега се проваля с липсващ път до източника, празна директория или монтиране, което машината отказва да създаде. В средите, които почистих, файлът Compose не беше променян и пътят беше правилен. Промени се кой демон получи заявката, а грешката при монтирането беше просто първото място, където тази разлика стана видима.

Томът никога не се премести; заявката се премести

Флагът -v /srv/app:/app не е копиране на директория, извършвано от вашата обвивка. Клиентът го превръща в API заявка, а демонът, който отговаря, разрешава /srv/app спрямо собствената си файлова система. Когато двете страни работят на едно и също ядро, този път е този, който виждате във файловия мениджър. Когато endpoint се промени, същият низ се търси на машина, която никога не е чувала за директорията на проекта ви, и демонът или съобщава източника като липсващ, или тихо създава празна директория на негово място.

Ето защо и именуваният том продължава да работи, докато bind монтирането — не. -v appdata:/app именува хранилище, което демонът притежава, така че никой път на хоста не трябва да съществува на конкретно място. Ако смяната на една услуга от bind монтиране към именуван том накара грешката да изчезне, вие не сте решили проблема. Потвърдили сте, че клиентът и демонът не са съгласни коя файлова система притежава пътя, и това несъгласие се връща в момента, в който отново ви потрябва истинска директория на хоста.

Отпечатайте endpoint, преди да пипате монтирането

Няколко настройки могат да насочат клиента към endpoint и те не винаги съвпадат: флагът --context , DOCKER_CONTEXT, DOCKER_HOST в текущата обвивка и контекстът, записан в конфигурацията на клиента. Вместо да разсъждавате за приоритета, отпечатайте всички и сравнете отговорите.

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

Конфигурацията на клиента се намира в ~/.docker/config.json на Linux и macOS и в %USERPROFILE%\.docker\config.json на Windows, а стойност, експортирана в текущия терминал, замества записаната само за тази сесия. Ако endpoint е име на хост, а не локален сокет, разрешаването на имена и маршрутите решават къде ще попадне, и точно тях пренаписва VPN клиентът. Тунел, който добавя маршрут или сменя резолвера, може да изпрати име, което преди означаваше този лаптоп, на адрес вътре в корпоративната мрежа.

Сравнявайте състояние, а не конфигурация. Изпълнете docker ps -a и docker images с изключен тунел, после отново с включен. Различен списък с контейнери е по-силно доказателство от всеки конфигурационен файл, защото показва, че различен демон е отговорил на заявката ви.

Попитайте демона дали пътят съществува там

След като знаете кой демон сте достигнали, накарайте го да погледне директорията. Формата --mount се проваля с по-ясно съобщение от краткия флаг, защото валидира източника, преди да стартира контейнера:

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

Ако той съобщи източника като липсващ, създайте го на машината, която отговори, или насочете услугата към именуван том и копирайте данните там. Това, което не трябва да правите, е да пресъздавате томове и да преинсталирате машината преди тази проверка. Тези действия променят средата достатъчно, за да скрият несъответствието, като го оставят на мястото му.

Още един път минава съвсем другаде: издърпването на образ е работа на демона, не на клиента. Успешното издърпване доказва само, че демонът може да достигне registry, а работещото bind монтиране — само че пътят е бил разрешен. Тествайте всеки път там, където реално се изпълнява, иначе ще прекарате следобеда на грешния.

Имената от вътрешната мрежа се провалят по друга причина

Втората половина на същия доклад обикновено е, че контейнерът не може да достигне intranet.corp.example. Това е отделен механизъм, не втори проблем с том. Контейнерът получава своя /etc/resolv.conf при стартиране, генериран от настройките на резолвера на демона, така че DNS сървър, който VPN добави след създаването на контейнера, няма да се появи там, докато контейнерът не бъде пресъздаден.

Вграденият резолвер на Docker в дефинирана от потребителя мрежа препраща външните заявки към конфигурираните сървъри на хоста, което помага, когато VPN пренаписва резолвера на хоста, и вреди, когато split DNS изпраща вътрешна зона към сървър, който демонът вече не вижда. Тясно, явно съпоставяне заобикаля спора за имена, които никога не се променят:

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

Това записва ред във файла hosts на контейнера, така че контейнерът никога не научава нищо за тунела, а също и замразява адреса. Когато вътрешният хост се премести, редът остава грешен, докато някой не редактира файла Compose. Използвайте го за фиксирано устройство или закрепена база данни, а имената, които се местят, оставете на DNS.

Какво всъщност променя преинсталирането

Преинсталирането на Docker Desktop пресъздава VM, сокета и списъка с контексти и монтирането отново започва да работи. Този резултат е реален и не учи на нищо, затова същата повреда се връща след следващата актуализация на VPN. Преинсталирането замени endpoint, който клиентът използваше; то не съгласува пътя, който вашият проект именува, с файловата система, която демонът действително чете.

Редът ми на работа е кратък. Потвърдете кой endpoint ще използва клиентът. Потвърдете кой демон е отговорил, като сравните списъците с контейнери. Помолете този демон да изброи пътя до източника. Едва след това редактирайте монтирането, добавете ред в hosts или сменете типа на тома. Ако поддържате файла Compose за екип, който работи през VPN, предпочитайте именувани томове за данни, които демонът трябва да притежава, така че път на хоста никога да не стане част от договора.

Подобни статии