Un pachet privat care pe mașina dumneavoastră se rezolvă fără probleme poate eșua în interiorul build-ului cu un 404 sau cu un timeout, iar Dockerfile este rareori cauza. Pasul de build rulează într-un alt spațiu de nume de rețea, cu o altă vedere a DNS-ului și un alt depozit de acreditări decât shell-ul în care ați testat. Parcurgeți aceste verificări în ordine și opriți-vă la prima care eșuează, pentru că fiecare verificare ulterioară presupune că precedenta a trecut. Fiecare pas numește comanda care lămurește problema.

Începeți prin a numi builderul, nu Dockerfile

BuildKit poate fi local, într-un container sau pe o altă mașină, iar fiecare are propria rețea implicită. Rulați docker buildx ls și citiți nodul marcat cu un asterisc înainte de a schimba ceva. Un docker-container driver sau un builder în cloud nu partajează ruta privată de pe laptopul dumneavoastră doar pentru că ați tastat comanda acolo. Dacă builderul activ este la distanță, fiecare verificare rămasă trebuie rulată pe acea gazdă, nu pe stația dumneavoastră de lucru.

Builderul poartă și propria configurație de resolver și propriile variabile proxy. Ambele sunt citite în momentul build-ului și nu sunt moștenite de la terminalul care l-a pornit.

Demonstrați calea de rețea din interiorul unui pas de build

Scrieți un stagiu de unică folosință care rezolvă gazda dependenței și deschide o conexiune către ea. Este singurul test care răspunde la întrebare pentru builder, nu pentru shell-ul dumneavoastră.

FROM alpine:3.20
RUN apk add --no-cache curl bind-tools  && getent hosts registry.example.internal  && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/

Construiți acel fișier cu același builder, mod de rețea și aceleași montări de secrete pe care le folosește build-ul real: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. Dacă getent nu tipărește nimic, defectul este în rezolvarea numelor și nicio acreditare nu îl repară. Dacă numele se rezolvă, dar curl raportează un timeout, obstacolul este ruta sau politica de ieșire din fața registrului.

Ștergeți sonda imediat ce răspunde. Este un stagiu de diagnostic și nu ar trebui niciodată etichetat sau împins.

Montați acreditarea în loc să o copiați

După ce ruta funcționează, autentificarea este următorul eșec din listă. O montare de secret BuildKit expune un fișier unui singur RUN pas fără a-l scrie într-un strat, ceea ce are nevoie instrumentul de dependențe și ceea ce imaginea nu trebuie să păstreze.

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc     npm ci --omit=dev

Secretul trebuie furnizat din afara Dockerfile: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. Fișierul rămâne la client și nu intră niciodată în istoricul imaginii. Un ARG sau un ENV cu același token nu fac această treabă, pentru că ambele sunt înregistrate în configurația imaginii.

O imagine fără root are nevoie de propria cale țintă, de exemplu /home/app/.npmrc sau fișierul echivalent pentru pip, Maven sau Cargo. Ținta montării trebuie să corespundă utilizatorului care execută comanda, altfel instrumentul va raporta un fișier de configurare lipsă care de fapt există.

Verificați ce lasă instrumentul de dependențe în imagine

O montare temporară ține acreditarea în afara unui strat, dar nu împiedică instrumentul să scrie altceva. Managerii de pachete lasă fișiere lock, directoare cache și uneori adresa URL a registrului deja rezolvată.

Citiți sistemul de fișiere final în loc să vă încredeți în Dockerfile. docker history --no-trunc image:tag listează fiecare comandă de strat, iar docker run --rm image:tag sh -c "ls -a /root" arată ce a supraviețuit în containerul care rulează. Chiar și când fișierul a fost doar montat, un token scris într-o linie de jurnal în timpul npm ci rămâne o scurgere.

Citiți și jurnalul de build, pentru că --progress=plain tipărește ieșirea comenzilor cuvânt cu cuvânt. Dacă tokenul apare acolo, rotiți-l înainte de orice altceva și transmiteți-l printr-un fișier pe care instrumentul îl citește în liniște.

Verificați că imaginea de execuție nu mai are nevoie de calea privată

Build-ul și aplicația care rulează sunt doi consumatori diferiți ai aceleiași dependențe, și doar primul are nevoie de calea privată. O imagine terminată ar trebui să pornească, să își rezolve dependențele de execuție și să servească trafic fără acreditarea din build.

Testați-o acolo unde registrul privat este inaccesibil, sau porniți pur și simplu containerul cu --network none și confirmați că pornește fără secretul montat. Un container care pornește doar când secretul de build este prezent este încă cuplat la mediul de build.

Dacă containerul are într-adevăr nevoie de registru la execuție, aceasta este o decizie de acces separată și îi revine depozitului de secrete al orchestratorului, nu build-ului. Documentați cele două căi separat, ca nimeni să nu încerce să repare un pull de execuție cu un flag de build. Când toate cele cinci verificări trec, simptomul original are o cauză numită la fiecare strat în loc de o presupunere despre rețeaua Docker.

Articole similare