VPN працуе, браўзер дасягае ўнутраных сайтаў, а кантэйнер усё яшчэ не можа развязаць тыя ж імёны. Усталёўка пакета падае з памылкай развязання імёнаў, такой як EAI_AGAIN, або праграма не знаходзіць хост базы даных, які машына-хост развязвае без ніякіх скаргаў. Кантэйнер не выкарыстоўвае рэзалвер, які ўсталяваў VPN. Docker скапіяваў канфігурацыю рэзалвера хоста ў момант стварэння кантэйнера, і пасля гэтага нішто яе зноў не капіявала.

Два погляды на рэзалвер на адной машыне

У Linux Docker дае кожнаму кантэйнеру копію канфігурацыі рэзалвера хоста у момант стварэння, адфільтроўвае адрасы loopback і запускае ўбудаваны DNS-сервер на 127.0.0.11, які перасылае запыты навонкі. Кліент VPN, які перапісвае /etc/resolv.conf пасля запуску кантэйнера, нічога ўнутры не змяняе. Перазапуск кантэйнера дапамагае толькі тады, калі рэзалвер хоста ў гэты момант выпадкова правільны.

Docker Desktop на macOS або Windows дадае пласт, бо дэман жыве ў віртуальнай машыне. Рэзалвер VPN хоста можа ніколі не быць бачным для гэтай ВМ, таму перазапуск не змяняе нічога зусім. Параўнайце два погляды перад выбарам рашэння: 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 унутры працуючага кантэйнера знікае разам з ім і хавае праблему канфігурацыі роўна на столькі, колькі камусьці спатрэбіцца на яго перазапуск.

Падобныя артыкулы