Ein privates Paket, das sich auf Ihrer Maschine problemlos auflösen lässt, kann im Build mit einem 404 oder einem Timeout scheitern, und der Dockerfile ist selten der Grund. Der Build-Schritt läuft in einem anderen Netzwerk-Namespace, mit einer anderen DNS-Sicht und einem anderen Credential-Store als die Shell, in der Sie getestet haben. Arbeiten Sie diese Prüfungen der Reihe nach durch und stoppen Sie bei der ersten, die scheitert, denn jede spätere Prüfung setzt voraus, dass die vorherige bestanden wurde. Jeder Schritt nennt den Befehl, der die Frage entscheidet.

Benennen Sie zuerst den Builder, nicht den Dockerfile

BuildKit kann lokal, in einem Container oder auf einer anderen Maschine laufen, und jede dieser Varianten hat ihr eigenes Standardnetzwerk. Führen Sie docker buildx ls aus und lesen Sie den mit einem Sternchen markierten Knoten, bevor Sie etwas ändern. Ein docker-container Treiber oder ein Cloud-Builder teilt die private Route auf Ihrem Laptop nicht, nur weil Sie den Befehl dort eingegeben haben. Ist der aktive Builder entfernt, muss jede weitere Prüfung gegen diesen Host laufen und nicht gegen Ihre Workstation.

Der Builder bringt außerdem seine eigene Resolver-Konfiguration und eigene Proxy-Variablenmit. Beides wird zur Build-Zeit gelesen und nicht von dem Terminal geerbt, das den Build gestartet hat.

Beweisen Sie den Netzwerkpfad aus einem Build-Schritt heraus

Schreiben Sie eine Wegwerf-Stufe, die den Host der Abhängigkeit auflöst und eine Verbindung dorthin öffnet. Das ist der einzige Test, der die Frage für den Builder beantwortet und nicht für Ihre Shell.

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/

Bauen Sie diese Datei mit demselben Builder, Netzwerkmodus und denselben Secret-Mounts, die Ihr echter Build verwendet: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. Wenn getent nichts ausgibt, liegt das Problem in der Namensauflösung, und keine Credentials beheben das. Löst der Name sich auf, meldet curl aber ein Timeout, ist die Route oder die Egress-Policy vor der Registry die Blockade.

Löschen Sie die Sonde, sobald sie antwortet. Sie ist eine Diagnose-Stufe und sollte niemals getaggt oder gepusht werden.

Binden Sie das Credential ein, statt es zu kopieren

Wenn der Pfad funktioniert, ist die Authentifizierung der nächste Fehler in der Reihe. Ein BuildKit-Secret-Mount stellt einem einzigen RUN Schritt eine Datei bereit, ohne sie in eine Schicht zu schreiben — genau das braucht das Abhängigkeitswerkzeug, und genau das darf das Image nicht behalten.

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

Das Secret muss von außerhalb des Dockerfile geliefert werden: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. Die Datei bleibt beim Client und gelangt nie in die Image-Historie. Ein ARG oder ENV mit demselben Token leisten diese Arbeit nicht, weil beide in der Image-Konfiguration festgehalten werden.

Ein Image ohne root braucht einen eigenen Zielpfad, etwa /home/app/.npmrc oder die entsprechende Datei für pip, Maven oder Cargo. Das Mount-Ziel muss zu dem Benutzer passen, der den Befehl ausführt, sonst meldet das Werkzeug eine fehlende Konfigurationsdatei, die tatsächlich vorhanden ist.

Prüfen Sie, was das Abhängigkeitswerkzeug im Image hinterlässt

Ein temporärer Mount hält das Credential aus einer Schicht heraus, hindert das Werkzeug aber nicht daran, etwas anderes zu schreiben. Paketmanager hinterlassen Lock-Dateien, Cache-Verzeichnisse und manchmal die aufgelöste Registry-URL.

Lesen Sie das fertige Dateisystem, statt dem Dockerfile zu vertrauen. docker history --no-trunc image:tag listet jeden Schichtbefehl auf, und docker run --rm image:tag sh -c "ls -a /root" zeigt, was in den laufenden Container überlebt hat. Selbst wenn die Datei nur eingebunden war, bleibt ein Token, das während npm ci in eine Logzeile geschrieben wird, ein Leck.

Lesen Sie auch das Build-Log, denn --progress=plain gibt die Befehlsausgabe wortwörtlich aus. Taucht das Token dort auf, rotieren Sie es vor allem anderen und reichen Sie es über eine Datei weiter, die das Werkzeug still liest.

Prüfen Sie, dass das Laufzeit-Image die private Route nicht mehr braucht

Der Build und die laufende Anwendung sind zwei verschiedene Nutzer derselben Abhängigkeit, und nur der erste braucht die private Route. Ein fertiges Image sollte starten, seine Laufzeitabhängigkeiten auflösen und Traffic bedienen, ohne das Build-Credential.

Testen Sie es dort, wo die private Registry nicht erreichbar ist, oder starten Sie den Container einfach mit --network none und bestätigen Sie, dass er ohne das eingebundene Secret hochkommt. Ein Container, der nur startet, wenn das Build-Secret vorhanden ist, hängt weiterhin an der Build-Umgebung.

Wenn der Container die Registry zur Laufzeit wirklich braucht, ist das eine eigene Zugriffsentscheidung, und sie gehört in den Secret Store des Orchestrators und nicht in den Build. Dokumentieren Sie beide Wege getrennt, damit niemand einen Laufzeit-Pull mit einem Build-Flag reparieren will. Wenn alle fünf Prüfungen bestehen, hat das ursprüngliche Symptom auf jeder Ebene eine benannte Ursache statt einer Vermutung über Docker-Netzwerke.

Ähnliche Artikel