Compose-palvelusi aikakatkaisee API:a vasten, jonka saman koneen selain avaa valittamatta. Juuri tämä ero on vihje: toimiva pyyntö lähtee isännältä, jolla on VPN-tunneli, ja jumittuva pyyntö lähtee kontista, jolla on oma verkkopinonsa. Mikään kontin sisällä ei tunne tunnelin reittejä, joten yksityinen kohde pysyy tavoittamattomana riippumatta siitä, miten nimi kirjoitetaan. Korjaus on tarkoituksellinen hyppy isännän kautta, ei älykkäämpi reititystaulu.

Aloita siitä, miksi kaksi polkua eroavat, ja päätä sitten, missä tunnelin pitäisi elää.

Miksi isäntä toimii ja kontti ei

Tunnelin nostaminen antaa isännälle rajapinnan, joukon reittejä ja yleensä VPN:n tarjoaman resolver-merkinnän. Kontti ei peri mitään siitä: se alkaa yhdellä rajapinnalla moottorin sillalla ja oletusreitillä, joka osoittaa tuolle sillalle. Isännälle asennetut reitit ovat näkymättömiä kaikelle, mikä toimii tuon nimiavaruuden sisällä.

Siksi oireet näyttävät epäjohdonmukaisilta eivätkä vain rikkinäisiltä. Isäntä selvittää yksityisen nimen ja yhdistää, koska sekä nimi että reitti ovat siellä. Kontti lähettää pakettinsa yksityiseen osoitteeseen, johon mikään sillan polulla ei pääse, ja pyyntö aikakatkaisee. Nimen lisääminen kontin hosts-tiedostoon ei muuta mitään, koska osoite itsessään on tavoittamaton siitä, missä kontti sijaitsee.

Tavoita isäntä kontin sisältä

Kontin sisällä toimiva prosessi, joka soittaa localhost-osoitteeseen, soittaa kontille. Docker Desktop julkaisee host.docker.internal-nimen, joka osoittaa takaisin moottoria ajavalle koneelle; Linux-moottorit jättävät sen määrittelemättä, ellei palvelu pyydä sitä, ja juuri niin alla oleva kartoitus tekee. Sen kanssa sovellus kohdistaa nimeen ja porttiin yksityisen osoitteen sijaan.

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

Tunneli jää hypyn isäntäpuolelle, ja tuon muuttujan portti on se, jolla proxy kuuntelee. Tunnelin menettävä kontti epäonnistuu nyt yhdellä tunnetulla hypyllä sen sijaan, että yrittäisi reittiä, jota sillä ei koskaan ollut.

Valitse, missä tunneli elää

Yksityistä API:a tarvitsevalle Compose-palvelulle on mahdollista kolme muotoa, ja ne eroavat siinä, mikä prosessi omistaa tunnelin. VPN-asiakas voi toimia kontin imagen sisällä, mikä vaatii tunnelilaitteen paljastamisen ja siihen liittyvän verkonhallintakyvyn myöntämisen. Sovellus voi jakaa erillisen tunnelikontin verkkonimiavaruuden, jolloin molemmat prosessit näkevät yhden pinon ja yhden reititystaulun. Tai tunneli voi jäädä isännälle, kapealla edelleenlähettäjällä isännästä konttiin.

Kaksi ensimmäistä vetävät profiilitiedostot, uudelleenyhdistämiskäyttäytymisen ja resolver-käytännön projektiin ja tekevät jokaisesta tiedoston palvelusta tunnelin kunnosta riippuvan. Se on paljon kytkentää yhtä API-kutsua varten. Kehityspinolle, joka lukee yhtä sisäistä päätepistettä, isännän puolen edelleenlähettäjä on pienin muutos, joka silti pitää tunnistetiedot siellä, missä alustatiimi niitä hallinnoi.

Julkaise yksi kapea polku isännällä

Aloita siitä, mitä edelleenlähettäjä perii: aja se tilillä, joka omistaa tunnelin, niin sen lähtevät pistokkeet ottavat isännän reitit ja isännän resolverin. Yksi nginx location -lohko kattaa yhden polun.

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

Kohtele osoitetta ja porttia väliaikaisina ja aseta pari, jolla API todella kuuntelee. Jokainen lisä-upstream ansaitsee oman location-lohkonsa, ja jokaisen lohkon tulisi sallia vain ne polut, joita tämä palvelu kutsuu, jotta proxysta ei tule yleistä ovea yksityisverkkoon. Sido kuuntelija sillan osoitteeseen asiakkaille, jotka saapuvat host-gatewayn kautta, loopbackiin vain kun asiakas jakaa isännän verkkonimiavaruuden, ja ei koskaan 0.0.0.0:aan. Valitse myös portti, joka on vielä vapaa: jo varattu numero jättää proxyn kuuntelematta, kun kontti jatkaa aikakatkaisua, eikä sitä voi erottaa siitä verkkoviasta, jolla aloitit.

Portit, nimet ja TLS-päätös

Nimien selvitys jakautuu samoin kuin reititys. Kontin julkiset haut kulkevat moottorin resolverin kautta, joten yksityinen nimi, joka selvitetään isännällä, ei selviä kontin sisällä. Proxy on komponentti, joka selvittää yksityisen nimen, koska se perii isännän resolverin.

TLS on päätös, joka lykkääntyy ja sitten selittää seuraavan vian. Jos proxy välittää tavut koskemattomina, kontti näkee API:n oman varmenteen ja tarvitsee sisäisen CA:n luottamussäilöönsä. Jos proxy päättää TLS:n, luottamus siirtyy isännälle ja sovellus alkaa rakentaa linkkejä vastaanottamastaan host-otsikosta. Valitse yksi järjestely ja sovella sitä jokaiseen resurssiin, koska toisen myöntämä uudelleenohjaus osoittaa isäntänimeen, jota kontti ei voi selvittää.

Vahvista palvelun sisältä

Lähetä pyyntö kontista, ei isännältä: tavallinen curl proxyn polulle ja sitten sovelluksen oma kuntotarkistus. Kun proxy vastaa mutta sovellus epäonnistuu edelleen, vertaa kolmea asiaa: perus-URL, jonka se rakentaa, mitä tahansa proxymuuttujaa sen ympäristössä ja CA:ta, johon se luottaa. Kaikki ne ovat kontin ympäristössä ja lokeissa, ja minkä tahansa korjaaminen jättää VPN:n rauhaan.

Kirjoita valittu järjestely projektin README-tiedostoon, kun se on vielä tuore. Muuten seuraava tähän aikakatkaisuun törmäävä henkilö viettää saman iltapäivän uudelleen löytäen, että tunneli elää isännällä.

Aiheeseen liittyvät artikkelit