Kontejner se nedostane na API jen přes VPN? Proxy ho na hostiteli
Tunel žije na hostiteli, takže kontejner nemá trasu k privátní adrese. Publikujte úzkou reverzní proxy a volejte ji jako host.docker.internal.
Vaše služba v Compose vyprší časový limit vůči API, které prohlížeč na stejném stroji otevře bez stížnosti. Právě tento rozdíl je stopa: požadavek, který funguje, vychází z hostitele s tunelem VPN, a požadavek, který visí, vychází z kontejneru s vlastním síťovým zásobníkem. Nic uvnitř kontejneru nezná trasy tunelu, takže privátní cíl zůstává nedostupný, ať se jméno napíše jakkoli. Řešením je záměrný skok přes hostitele, ne chytřejší směrovací tabulka.
Začněte tím, proč se obě cesty liší, a pak rozhodněte, kde má tunel žít.
Proč hostitel funguje a kontejner ne
Spuštění tunelu dá hostiteli rozhraní, sadu tras a obvykle záznam v resolveru, který dodá VPN. Kontejner nic z toho nedědí: startuje s jedním rozhraním na mostu enginu a výchozí trasou, která ukazuje na tento most. Trasy nainstalované na hostiteli jsou pro cokoli běžící uvnitř tohoto jmenného prostoru neviditelné.
Proto příznaky vypadají nekonzistentně, ne jen rozbitě. Hostitel přeloží privátní jméno a připojí se, protože tam existuje jméno i trasa. Kontejner pošle paket na privátní adresu, na kterou se nic na cestě přes most nedostane, a požadavek vyprší. Přidání jména do souboru hosts kontejneru nic nezmění, protože samotná adresa je z místa, kde kontejner sedí, nedostupná.
Dostaňte se na hostitele zevnitř kontejneru
Proces v kontejneru, který vytáčí localhost, vytáčí kontejner. Docker Desktop publikuje host.docker.internal jako jméno, které ukazuje zpět na stroj provozující engine; linuxové enginy je nechávají nedefinované, dokud o ně služba nepožádá, což dělá mapování níže. S tím aplikace cílí na jméno a port místo privátní adresy.
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
INTERNAL_API_HOST: "host.docker.internal:8666"Tunel zůstává na straně hostitele tohoto skoku a port v této proměnné je ten, na kterém bude proxy naslouchat. Kontejner, který tunel ztratí, teď selže na jednom známém skoku místo toho, aby zkoušel trasu, kterou nikdy neměl.
Zvolte, kde tunel žije
Pro službu v Compose, která potřebuje privátní API, jsou možné tři podoby a liší se tím, který proces tunel vlastní. Klient VPN může běžet uvnitř image kontejneru, což vyžaduje vystavit zařízení tunelu a udělit s tím spojenou schopnost správy sítě. Aplikace může sdílet síťový jmenný prostor samostatného kontejneru s tunelem, takže oba procesy vidí jeden zásobník a jednu směrovací tabulku. Nebo může tunel zůstat na hostiteli, s úzkým předávačem z hostitele do kontejneru.
První dvě vtahují do projektu profilové soubory, chování při opětovném připojení a politiku resolveru a činí každou službu v souboru závislou na zdraví tunelu. To je pro jedno volání API příliš mnoho provázanosti. Pro vývojový zásobník, který čte jediný interní koncový bod, je předávač na straně hostitele nejmenší změna, která přesto udrží přihlašovací údaje tam, kde je spravuje tým platformy.
Publikujte jednu úzkou cestu na hostiteli
Začněte tím, co předávač dědí: spusťte ho pod účtem, který vlastní tunel, a jeho odchozí sockety převezmou trasy hostitele a resolver hostitele. Jeden blok location v nginx pokrývá jednu cestu.
server {
listen 8666;
location /search/ {
proxy_pass http://10.20.30.40:8090/;
proxy_set_header Host internal-api.example;
proxy_read_timeout 60s;
}
}Berte adresu a port jako zástupné a nahraďte je dvojicí, na které API skutečně naslouchá. Každý další upstream si zaslouží vlastní blok location a každý blok by měl propouštět jen cesty, které tato služba volá, aby se proxy nestala obecnými dveřmi do privátní sítě. Přivažte posluchač k adrese mostu pro klienty, kteří přicházejí přes host-gateway, k loopback jen tehdy, když klient sdílí síťový jmenný prostor hostitele, a nikdy k 0.0.0.0. Zvolte také port, který je ještě volný: obsazené číslo nechá proxy nenaslouchat, zatímco kontejneru dál vyprší časový limit, což nelze rozeznat od síťové závady, se kterou jste začali.
Porty, jména a rozhodnutí o TLS
Překlad jmen se dělí stejně jako směrování. Veřejná vyhledávání kontejneru jdou přes resolver enginu, takže privátní jméno, které se přeloží na hostiteli, se uvnitř kontejneru nepřeloží. Proxy je komponenta, která privátní jméno překládá, protože dědí resolver hostitele.
TLS je rozhodnutí, které se odkládá a pak vysvětlí další selhání. Pokud proxy předává bajty nedotčené, kontejner vidí vlastní certifikát API a potřebuje interní CA ve svém úložišti důvěry. Pokud proxy TLS ukončuje, tato důvěra se přesouvá na hostitele a aplikace začne stavět odkazy z hlavičky host, kterou dostává. Zvolte jedno uspořádání a uplatněte je na každý zdroj, protože přesměrování vydané tím druhým ukazuje na jméno hostitele, které kontejner nedokáže přeložit.
Ověřte to zevnitř služby
Pošlete požadavek z kontejneru, ne z hostitele: obyčejný curl na cestu proxy a poté vlastní kontrola zdraví aplikace. Když proxy odpovídá, ale aplikace stále selhává, porovnejte tři věci: základní URL, kterou staví, případnou proxy proměnnou ve svém prostředí a CA, které důvěřuje. Všechno to je v prostředí a záznamech kontejneru a oprava kterékoli z nich nechá VPN na pokoji.
Zapište zvolené uspořádání do README projektu, dokud je čerstvé. Jinak další člověk, který na tento timeout narazí, stráví stejné odpoledne znovuobjevováním, že tunel žije na hostiteli.