Kontajner sa nedostane na API dostupné len cez VPN? Dajte proxy na hostiteľa
Tunel žije na hostiteľovi, takže kontajner nemá trasu k privátnej adrese. Publikujte úzku reverznú proxy a volajte ju ako host.docker.internal.
Vaša služba v Compose vyprší časový limit voči API, ktoré prehliadač na tom istom stroji otvorí bez sťažnosti. Práve tento rozdiel je stopa: požiadavka, ktorá funguje, vychádza z hostiteľa s tunelom VPN, a požiadavka, ktorá visí, vychádza z kontajnera s vlastným sieťovým zásobníkom. Nič vnútri kontajnera nepozná trasy tunela, takže privátny cieľ zostáva nedostupný, nech sa meno napíše akokoľvek. Riešením je zámerný skok cez hostiteľa, nie múdrejšia smerovacia tabuľka.
Začnite tým, prečo sa obe cesty líšia, a potom rozhodnite, kde má tunel žiť.
Prečo hostiteľ funguje a kontajner nie
Spustenie tunela dá hostiteľovi rozhranie, sadu trás a zvyčajne záznam v resolveri, ktorý dodá VPN. Kontajner nič z toho nededia: začína s jedným rozhraním na moste enginu a predvolenou trasou, ktorá na ten most ukazuje. Trasy nainštalované na hostiteľovi sú pre čokoľvek bežiace v tomto mennom priestore neviditeľné.
Preto príznaky vyzerajú nekonzistentne, nie len pokazene. Hostiteľ preloží privátne meno a pripojí sa, pretože tam existuje aj meno, aj trasa. Kontajner pošle paket na privátnu adresu, na ktorú sa nič na ceste cez most nedostane, a požiadavka vyprší. Pridanie mena do súboru hosts kontajnera nič nezmení, pretože samotná adresa je z miesta, kde kontajner sedí, nedostupná.
Dostaňte sa na hostiteľa zvnútra kontajnera
Proces v kontajneri, ktorý vytáča localhost, vytáča kontajner. Docker Desktop publikuje host.docker.internal ako meno, ktoré ukazuje späť na stroj prevádzkujúci engine; linuxové enginy ho nechávajú nedefinované, kým oň služba nepožiada, a to robí mapovanie nižšie. S tým aplikácia cieli na meno a port namiesto privátnej adresy.
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
INTERNAL_API_HOST: "host.docker.internal:8666"Tunel zostáva na strane hostiteľa tohto skoku a port v tejto premennej je ten, na ktorom bude proxy počúvať. Kontajner, ktorý stratí tunel, teraz zlyhá na jednom známom skoku namiesto toho, aby skúšal trasu, ktorú nikdy nemal.
Zvoľte, kde tunel žije
Pre službu v Compose, ktorá potrebuje privátne API, sú možné tri podoby a líšia sa tým, ktorý proces tunel vlastní. Klient VPN môže bežať v obraze kontajnera, čo vyžaduje vystaviť zariadenie tunela a udeliť s tým spojenú schopnosť správy siete. Aplikácia môže zdieľať sieťový menný priestor samostatného kontajnera s tunelom, takže oba procesy vidia jeden zásobník a jednu smerovaciu tabuľku. Alebo môže tunel zostať na hostiteľovi, s úzkym preposielačom z hostiteľa do kontajnera.
Prvé dve vtiahnu do projektu profilové súbory, správanie pri opätovnom pripojení a politiku resolvera a učinia každú službu v súbore závislou od zdravia tunela. To je príliš veľa previazania na jedno volanie API. Pre vývojový zásobník, ktorý číta jediný interný koncový bod, je preposielač na strane hostiteľa najmenšia zmena, ktorá však udrží prihlasovacie údaje tam, kde ich spravuje tím platformy.
Publikujte jednu úzku cestu na hostiteľovi
Začnite tým, čo preposielač dedí: spustite ho pod účtom, ktorý vlastní tunel, a jeho odchádzajúce sockety prevezmú trasy hostiteľa a resolver hostiteľa. Jeden blok location v nginx pokrýva 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 ako zástupné a vložte dvojicu, na ktorej API skutočne počúva. Každý ďalší upstream si zaslúži vlastný blok location a každý blok by mal prepúšťať len cesty, ktoré táto služba volá, aby sa proxy nestala všeobecnými dverami do privátnej siete. Pripevnite poslucháča k adrese mosta pre klientov, ktorí prichádzajú cez host-gateway, k loopbacku len vtedy, keď klient zdieľa sieťový menný priestor hostiteľa, a nikdy k 0.0.0.0. Zvoľte aj port, ktorý je ešte voľný: obsadené číslo nechá proxy nepočúvať, zatiaľ čo kontajneru ďalej vyprší časový limit, čo sa nedá odlíšiť od sieťovej poruchy, s ktorou ste začali.
Porty, mená a rozhodnutie o TLS
Preklad mien sa delí rovnako ako smerovanie. Verejné vyhľadávania kontajnera idú cez resolver enginu, takže privátne meno, ktoré sa preloží na hostiteľovi, sa vnútri kontajnera nepreloží. Proxy je komponent, ktorý privátne meno prekladá, pretože dedí resolver hostiteľa.
TLS je rozhodnutie, ktoré sa odkladá a potom vysvetlí ďalšie zlyhanie. Ak proxy preposiela bajty nedotknuté, kontajner vidí vlastný certifikát API a potrebuje internú CA vo svojom úložisku dôvery. Ak proxy TLS ukončuje, tá dôvera sa presúva na hostiteľa a aplikácia začne stavať odkazy z hlavičky host, ktorú dostáva. Zvoľte jedno usporiadanie a uplatnite ho na každý zdroj, pretože presmerovanie vydané tým druhým ukazuje na meno hostiteľa, ktoré kontajner nevie preložiť.
Overte to zvnútra služby
Pošlite požiadavku z kontajnera, nie z hostiteľa: obyčajný curl na cestu proxy a potom vlastná kontrola zdravia aplikácie. Keď proxy odpovedá, ale aplikácia stále zlyháva, porovnajte tri veci: základnú URL, ktorú stavia, akúkoľvek proxy premennú v jej prostredí a CA, ktorej dôveruje. Všetko to je v prostredí a záznamoch kontajnera a oprava ktorejkoľvek z nich nechá VPN na pokoji.
Zapíšte zvolené usporiadanie do README projektu, kým je čerstvé. Inak ďalší človek, ktorý na tento časový limit narazí, strávi to isté popoludnie znovuobjavovaním, že tunel žije na hostiteľovi.