Kontejner ne može do API-ja samo preko VPN-a? Postavite proxy na hostu
Tunel živi na hostu, pa kontejner nema rutu do privatne adrese. Objavite uzak obrnuti proxy i pozovite ga kao host.docker.internal.
Vaša Compose usluga prelazi u vremensku granicu prema API-ju koji preglednik na istom stroju otvara bez ikakve primjedbe. Ta razlika je trag: zahtjev koji radi napušta host s VPN tunelom, a zahtjev koji visi napušta kontejner s vlastitim mrežnim stogom. Ništa unutar kontejnera ne zna rute tunela, pa privatno odredište ostaje nedostupno kako god se ime napisalo. Ispravka je namjerni skok kroz host, a ne pametnija tablica rutiranja.
Počnite s tim zašto se ta dva puta razlikuju, a zatim odlučite gdje tunel treba živjeti.
Zašto host radi, a kontejner ne
Podizanje tunela daje hostu sučelje, skup ruta i obično zapis u resolveru koji osigurava VPN. Kontejner ne nasljeđuje ništa od toga: počinje s jednim sučeljem na mostu pogona i zadanom rutom koja pokazuje na taj most. Rute instalirane na hostu nevidljive su svemu što radi unutar tog imenskog prostora.
Zato simptomi izgledaju nedosljedno, a ne jednostavno pokvareno. Host razrješava privatno ime i povezuje se, jer tamo postoje i ime i ruta. Kontejner šalje svoj paket na privatnu adresu do koje ništa na putu preko mosta ne može stići i zahtjev istječe. Dodavanje imena u datoteku hosts kontejnera ne mijenja ništa, jer je sama adresa nedostupna s mjesta na kojem kontejner stoji.
Dođite do hosta iz unutrašnjosti kontejnera
Proces u kontejneru koji poziva localhost poziva kontejner. Docker Desktop objavljuje host.docker.internal kao ime koje pokazuje natrag na stroj koji pokreće pogon; Linux pogoni ga ostavljaju nedefiniranim osim ako usluga to zatraži, a upravo to čini mapiranje ispod. S tim na mjestu aplikacija cilja ime i port umjesto privatne adrese.
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
INTERNAL_API_HOST: "host.docker.internal:8666"Tunel ostaje na strani hosta ovog skoka, a port u toj varijabli je onaj na kojem će proxy slušati. Kontejner koji izgubi tunel sada pada na jednom poznatom skoku umjesto da pokušava rutu koju nikada nije imao.
Odaberite gdje tunel živi
Za Compose uslugu kojoj treba privatni API moguća su tri oblika, a razlikuju se po tome koji proces posjeduje tunel. VPN klijent može raditi unutar slike kontejnera, što zahtijeva izlaganje tunelskog uređaja i dodjelu sposobnosti administracije mreže koja ide s tim. Aplikacija može dijeliti mrežni imenski prostor zasebnog kontejnera s tunelom, pa oba procesa vide jedan stog i jednu tablicu rutiranja. Ili tunel može ostati na hostu, s uskim prosljeđivačem s hosta u kontejner.
Prva dva uvlače profilne datoteke, ponašanje ponovnog povezivanja i politiku resolvera u projekt i čine svaku uslugu u datoteci ovisnom o zdravlju tunela. To je previše povezanosti za jedan poziv API-ja. Za razvojni stog koji čita jednu internu krajnju točku, prosljeđivač na strani hosta najmanja je promjena koja ipak čuva vjerodajnice tamo gdje ih upravlja tim platforme.
Objavite jedan uzak put na hostu
Počnite od onoga što prosljeđivač nasljeđuje: pokrenite ga pod računom koji posjeduje tunel i njegovi izlazni soketi preuzimaju rute hosta i resolver hosta. Jedan nginx location blok pokriva jedan put.
server {
listen 8666;
location /search/ {
proxy_pass http://10.20.30.40:8090/;
proxy_set_header Host internal-api.example;
proxy_read_timeout 60s;
}
}Tretirajte adresu i port kao privremene zamjene i uvrstite par na kojem API zapravo sluša. Svaki daljnji upstream zaslužuje vlastiti location blok i svaki blok treba propuštati samo putanje koje ova usluga poziva, kako proxy ne bi postao opća vrata u privatnu mrežu. Vežite slušatelja na adresu mosta za klijente koji dolaze kroz host-gateway, na loopback samo kada klijent dijeli mrežni imenski prostor hosta, i nikada na 0.0.0.0. Odaberite i port koji je još slobodan: već zauzet broj ostavlja proxy da ne sluša dok kontejner nastavlja istjecati, što se ne može razlikovati od mrežne greške s kojom ste počeli.
Portovi, imena i odluka o TLS-u
Razrješavanje imena dijeli se isto kao rutiranje. Javne pretrage kontejnera idu kroz resolver pogona, pa se privatno ime koje se razrješava na hostu neće razriješiti unutar kontejnera. Proxy je komponenta koja razrješava privatno ime, jer nasljeđuje resolver hosta.
TLS je odluka koja se odgađa i zatim objašnjava sljedeći neuspjeh. Ako proxy prosljeđuje bajtove netaknute, kontejner vidi vlastiti certifikat API-ja i treba interni CA u svom spremištu povjerenja. Ako proxy završava TLS, to se povjerenje seli na host i aplikacija počinje graditi poveznice iz host zaglavlja koje prima. Odaberite jedan raspored i primijenite ga na svaki resurs, jer preusmjerenje koje izda drugi upućuje na ime hosta koje kontejner ne može razriješiti.
Provjerite iz unutrašnjosti usluge
Pošaljite zahtjev iz kontejnera, ne s hosta: obični curl na put proxyja, zatim vlastita provjera zdravlja aplikacije. Kada proxy odgovori, a aplikacija i dalje ne uspijeva, usporedite tri stvari: osnovni URL koji gradi, bilo koju proxy varijablu u svojem okruženju i CA kojem vjeruje. Sve to stoji u okruženju i zapisima kontejnera, a popravak bilo koje od njih ostavlja VPN na miru.
Zapišite odabrani raspored u README projekta dok je svjež. Inače će sljedeća osoba koja naiđe na ovo istjecanje provesti isto poslijepodne otkrivajući iznova da tunel živi na hostu.