El vostre servei de Compose es queda sense temps amb una API que el navegador de la mateixa màquina obre sense cap queixa. Aquesta diferència és la pista: la petició que funciona surt d’un amfitrió amb un túnel VPN, i la que es penja surt d’un contenidor amb la seva pròpia pila de xarxa. Res dins del contenidor no coneix les rutes del túnel, així que la destinació privada continua inabastable digui’s com digui’s el nom. La solució és un salt deliberat per l’amfitrió, no una taula de rutes més enginyosa.

Comenceu per per què difereixen els dos camins i després decidiu on ha de viure el túnel.

Per què l’amfitrió funciona i el contenidor no

Pujar el túnel dóna a l’amfitrió una interfície, un conjunt de rutes i, normalment, una entrada de resolutor que proporciona la VPN. Un contenidor no n’hereta res: arrenca amb una interfície al pont del motor i una ruta per defecte que apunta a aquest pont. Les rutes instal·lades a l’amfitrió són invisibles per a tot el que s’executa dins d’aquest espai de noms.

Per això els símptomes semblen incoherents i no simplement espatllats. L’amfitrió resol el nom privat i es connecta, perquè tant el nom com la ruta hi existeixen. El contenidor envia el seu paquet a una adreça privada que res del camí del pont pot assolir, i la petició caduca. Afegir el nom al fitxer hosts del contenidor no canvia res, perquè l’adreça mateixa és inabastable des d’on se situa el contenidor.

Arribeu a l’amfitrió des de dins del contenidor

Un procés dins del contenidor que marca localhost està marcant el contenidor. Docker Desktop publica host.docker.internal com un nom que assenyala la màquina que executa el motor; els motors de Linux el deixen indefinit tret que el servei el demani, que és el que fa el mapatge de sota. Amb això, l’aplicació apunta a un nom i un port en lloc de l’adreça privada.

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

El túnel es queda al costat de l’amfitrió del salt, i el port d’aquesta variable és el que farà servir el proxy per escoltar. Un contenidor que perd el túnel ara falla en un sol salt conegut en lloc d’intentar una ruta que mai no va tenir.

Trieu on viu el túnel

Hi ha tres formes possibles per a un servei de Compose que necessita una API privada, i es diferencien en quin procés posseeix el túnel. Un client VPN pot córrer dins de la imatge del contenidor, cosa que requereix exposar un dispositiu de túnel i concedir la capacitat d’administració de xarxa que hi va lligada. L’aplicació pot compartir l’espai de noms de xarxa d’un contenidor de túnel separat, de manera que tots dos processos veuen una pila i una taula de rutes. O el túnel es pot quedar a l’amfitrió, amb un reenviador estret de l’amfitrió cap al contenidor.

Les dues primeres arrosseguen fitxers de perfil, comportament de reconnexió i política de resolutor dins del projecte, i fan que cada servei del fitxer depengui de la salut del túnel. És massa acoblament per a una sola crida a l’API. Per a una pila de desenvolupament que llegeix un sol punt final intern, el reenviador a l’amfitrió és el canvi més petit que encara manté les credencials on les gestiona l’equip de plataforma.

Publiqueu un sol camí estret a l’amfitrió

Comenceu pel que hereta el reenviador: executeu-lo amb el compte que posseeix el túnel i els seus sòcols de sortida agafaran les rutes de l’amfitrió i el resolutor de l’amfitrió. Un bloc location de nginx cobreix un camí.

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

Tracteu l’adreça i el port com a suplents i substituïu-los pel parell on l’API escolta realment. Cada upstream addicional guanya el seu propi bloc location, i cada bloc hauria d’admetre només els camins que crida aquest servei, perquè el proxy no es converteixi en una porta general cap a la xarxa privada. Lligueu l’oient a l’adreça del pont per als clients que arriben via host-gateway, a loopback només quan el client comparteix l’espai de noms de xarxa de l’amfitrió, i mai a 0.0.0.0. Trieu també un port que encara sigui lliure: un número ja ocupat deixa el proxy sense escoltar mentre el contenidor continua caducant, cosa que no es pot distingir de la fallada de xarxa amb què vau començar.

Ports, noms i la decisió de TLS

La resolució de noms es divideix igual que l’encaminament. Les consultes públiques del contenidor passen pel resolutor del motor, així que un nom privat que es resol a l’amfitrió no es resoldrà dins del contenidor. El proxy és el component que resol el nom privat, perquè hereta el resolutor de l’amfitrió.

TLS és la decisió que s’ajorna i després explica la fallada següent. Si el proxy reenvia els bytes intactes, el contenidor veu el certificat propi de l’API i necessita la CA interna al seu magatzem de confiança. Si el proxy acaba el TLS, aquesta confiança passa a l’amfitrió i l’aplicació comença a construir enllaços a partir de la capçalera host que rep. Trieu un sol arranjament i apliqueu-lo a cada recurs, perquè una redirecció emesa per l’altre apunta a un nom d’amfitrió que el contenidor no pot resoldre.

Verifiqueu des de dins del servei

Envieu la petició des del contenidor, no des de l’amfitrió: un curl senzill contra el camí del proxy i després la comprovació de salut de l’aplicació. Quan el proxy respon però l’aplicació encara falla, compareu tres coses: l’URL base que construeix, qualsevol variable de proxy al seu entorn i la CA en què confia. Totes són a l’entorn i als registres del contenidor, i arreglar-ne qualsevol deixa la VPN tranquil·la.

Escriviu l’arranjament triat al README del projecte mentre és fresc. Si no, la propera persona que topi amb aquest temps esgotat passarà la mateixa tarda descobrint de nou que el túnel viu a l’amfitrió.

Articles relacionats