Сіздің Compose қызметіңіз сол машинадағы браузер еш шағымсыз ашатын API-ге қатысты уақыт шегінен өтіп кетеді. Осы айырмашылық — белгі: жұмыс істейтін сұрау VPN туннелі бар хосттан шығады, ал ілініп қалатын сұрау өз желілік стекі бар контейнерден шығады. Контейнердің ішінде ешнәрсе туннель маршруттарын білмейді, сондықтан атау қалай жазылса да жеке меже қолжетімсіз болып қалады. Шешім — хост арқылы әдейі жасалған секіру, ақылдырақ маршруттау кестесі емес.

Екі жолдың неге бөлінетінінен бастаңыз, содан кейін туннель қайда тұруы керегін шешіңіз.

Неге хост жұмыс істейді, ал контейнер істемейді

Туннельді көтеру хостқа интерфейс, маршруттар жиынын және әдетте VPN берген резолвер жазбасын береді. Контейнер бұның ешқайсысын мұра етпейді: ол қозғалтқыш көпіріндегі бір интерфейспен және сол көпірге бағытталған әдепкі маршрутпен басталады. Хостқа орнатылған маршруттар сол ат кеңістігінің ішінде жүгіретін ешнәрсеге көрінбейді.

Сондықтан симптомдар жай бұзылған емес, сәйкессіз көрінеді. Хост жеке атауды шешіп, қосылады, өйткені онда атау да, маршрут та бар. Контейнер пакетін көпір жолында ешнәрсе жете алмайтын жеке мекенжайға жібереді, ал сұрау уақыт шегінен өтеді. Атауды контейнердің hosts файлына қосу ештеңе өзгертпейді, өйткені мекенжайдың өзі контейнер отырған жерден қолжетімсіз.

Контейнердің ішінен хостқа жетіңіз

Контейнердегі localhost арқылы қоңырау шалатын процесс контейнерге қоңырау шалады. Docker Desktop host.docker.internal атауын қозғалтқышты жүргізетін машинаға кері сілтейтін атау ретінде жариялайды; Linux қозғалтқыштары қызмет сұрамаса, оны анықталмаған күйде қалдырады, төмендегі салыстыру дәл соны жасайды. Осымен қолданба жеке мекенжайдың орнына атау мен портты нысана етеді.

services:
  app:
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      INTERNAL_API_HOST: "host.docker.internal:8666"

Туннель секірудің хост жағында қалады, ал сол айнымалыдағы порт — прокси тыңдайтын порт. Туннельден айырылған контейнер енді ешқашан болмаған маршрутты байқап көрудің орнына бір белгілі секіруде сәтсіздікке ұшырайды.

Туннель қайда тұратынын таңдаңыз

Жеке API қажет Compose қызметі үшін үш пішін мүмкін, олар туннельді қай процесс ұстайтынымен ерекшеленеді. VPN клиенті контейнер бейнесінің ішінде жұмыс істей алады, бұл туннель құрылғысын ашу мен онымен бірге келетін желілік әкімшілік мүмкіндігін беруді талап етеді. Қолданба бөлек туннель контейнерінің желілік ат кеңістігін бөлісе алады, сонда екі процесс те бір стекті және бір маршруттау кестесін көреді. Немесе туннель хостта қала алады, хосттан контейнерге тар өткізгішпен.

Алғашқы екеуі профиль файлдарын, қайта қосылу мінезін және резолвер саясатын жобаға тартады және файлдағы әр қызметті туннельдің денсаулығына тәуелді етеді. Бір API шақыруы үшін бұл тым көп байланыс. Бір ішкі шеткі нүктені оқитын әзірлеу стегі үшін хост жағындағы өткізгіш — тіркелгі деректерін платформа командасы басқаратын жерде сақтайтын ең кіші өзгеріс.

Хостта бір тар жол жариялаңыз

Өткізгіш мұра ететіннен бастаңыз: оны туннельді ұстайтын тіркелгімен іске қосыңыз, сонда оның шығыс сокеттері хост маршруттарын және хост резолверін қабылдайды. nginx-тің бір location блогы бір жолды қамтиды.

server {
    listen 8666;
    location /search/ {
        proxy_pass http://10.20.30.40:8090/;
        proxy_set_header Host internal-api.example;
        proxy_read_timeout 60s;
    }
}

Мекенжай мен портты уақытша деп қарап, API шын мәнінде тыңдайтын жұпты қойыңыз. Әр қосымша upstream өз location блогын алады, ал әр блок тек осы қызмет шақыратын жолдарды жіберуі керек, сонда прокси жеке желіге жалпы есікке айналмайды. Тыңдаушыны host-gateway арқылы келетін клиенттер үшін көпір мекенжайына, клиент хосттың желілік ат кеңістігін бөліскенде ғана loopback-қа байланыстырыңыз, ал 0.0.0.0-ге ешқашан байланыстырмаңыз. Әлі бос портты да таңдаңыз: әлдеқашан алынған нөмір проксиді тыңдамайтын күйде қалдырады, ал контейнер уақыт шегінен өте береді, мұны сіз бастаған желілік ақаудан ажырату мүмкін емес.

Порттар, атаулар және TLS шешімі

Атауларды шешу маршруттау сияқты бөлінеді. Контейнердің жария іздеулері қозғалтқыш резолвері арқылы өтеді, сондықтан хостта шешілетін жеке атау контейнердің ішінде шешілмейді. Прокси — жеке атауды шешетін құрамдас, өйткені ол хост резолверін мұра етеді.

TLS — кейінге қалдырылатын, содан кейін келесі ақауды түсіндіретін шешім. Егер прокси байттарды тиіспестен жіберсе, контейнер API-дің өз сертификатын көреді және сенім қоймасында ішкі CA қажет болады. Егер прокси TLS-ті аяқтаса, бұл сенім хостқа ауысады және қолданба алған host тақырыбынан сілтемелер құра бастайды. Бір реттеуді таңдап, оны әр ресурсқа қолданыңыз, өйткені екіншісі шығарған қайта бағыттау контейнер шеше алмайтын хост атауына сілтейді.

Қызметтің ішінен тексеріңіз

Сұрауды хосттан емес, контейнерден жіберіңіз: прокси жолына қарапайым curl, содан кейін қолданбаның өз денсаулық тексерісі. Прокси жауап берсе де қолданба әлі сәтсіз болса, үш нәрсені салыстырыңыз: ол құратын негізгі URL, оның ортасындағы кез келген прокси айнымалысы және ол сенетін CA. Олардың бәрі контейнердің ортасы мен журналдарында, ал кез келгенін түзету VPN-ге тиіспейді.

Таңдалған реттеуді жобаның README файлына әлі жаңа кезінде жазыңыз. Әйтпесе осы уақыт шегіне тап болған келесі адам сол түстен кейінді туннельдің хостта тұратынын қайта ашуға жұмсайды.

Қатысты мақалалар