VPN е включен, браузърът достига вътрешни сайтове, а контейнерът все още не може да разреши същите имена. Инсталирането на пакет умира с грешка за разрешаване на име като EAI_AGAIN, или приложение не намира хост на база данни, който хост машината разрешава без оплакване. Контейнерът не използва резолвера, който VPN инсталира. Docker копира конфигурацията на резолвера на хоста при създаването на контейнера и нищо не я копира отново след това.

Два изгледа на резолвера на една машина

В Linux Docker дава на всеки контейнер копие на конфигурацията на резолвера на хоста в момента на създаване, филтрира loopback адресите и пуска вграден DNS сървър на 127.0.0.11, който препраща заявките навън. VPN клиент, който пренапише /etc/resolv.conf след стартирането на контейнера, не променя нищо вътре в него. Рестартирането на контейнера помага само ако резолверът на хоста случайно е правилен в този момент.

Docker Desktop на macOS или Windows добавя слой, защото демонът живее във виртуална машина. Резолверът на VPN на хоста може никога да не е видим за тази VM, така че рестартирането не променя нищо. Сравнете двата изгледа, преди да изберете решение: docker exec mycontainer cat /etc/resolv.conf до списъка с резолвери на хоста.

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

Вариант A: подаване на резолвера на тунела за всеки контейнер

Docker приема DNS настройки за всеки контейнер и това е най-малката промяна, която работи. Първо прочетете адресите на резолвера на VPN: scutil --dns на macOS, resolvectl status или собствения изход за състоянието на клиента на Linux. След това стартирайте контейнера с тях, например docker run --dns 192.168.2.1 --dns 192.168.123.1 myimage. В Compose същата настройка е списък под услугата, където живее в контрол на версиите, вместо в нечия история на командите.

Масив dns в /etc/docker/daemon.json се прилага за всеки нов контейнер, което звучи по-подредено, а не е. Прилага се и когато тунелът е спрян, и тогава резолвер, достъпен само през VPN, чупи обикновеното изтегляне на изображения. Настройките за отделен контейнер се обосновават по-лесно и се отменят по-лесно.

Вариант B: контейнерът да споделя мрежата на хоста

Мрежата на хоста заобикаля копирането напълно, защото контейнерът използва резолвера на хоста и тунела на хоста. Тя също премахва мрежовата изолация, която вероятно сте искали, и не се държи по същия начин под Docker Desktop. В Linux това е прагматичният избор за еднократен инструмент, който трябва да разрешава вътрешни имена.

За компилации не важи нито един от двата варианта, защото стъпките на компилация не наследяват флагове за време на изпълнение. Компилирайте с мрежа на хоста, където платформата позволява, или дръжте инсталирането на зависимости в етап, който не се нуждае от тунела.

Какво не поправя нито един вариант

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

Проверете подмрежата на мрежата на Docker спрямо подмрежата на VPN, преди да отстранявате проблеми в самия резолвер. Припокриването дава отказ, който изглежда точно като счупен DNS сървър.

Проверка вътре в контейнера

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

Пресъздайте контейнера, след като промените DNS настройките му. Редактирането на /etc/resolv.conf вътре в работещ контейнер изчезва с него и скрива конфигурационния проблем точно толкова дълго, колкото някой се нуждае, за да го рестартира.

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