Un pacchetto privato che sulla vostra macchina si risolve senza problemi può fallire dentro la build con un 404 o con un timeout scaduto, e il Dockerfile raramente è la causa. Il passo di build gira in un altro spazio dei nomi di rete, con una vista DNS diversa e un archivio di credenziali diverso dalla shell in cui avete provato. Percorrete questi controlli in ordine e fermatevi al primo che fallisce, perché ogni controllo successivo dà per scontato che il precedente sia passato. Ogni passo nomina il comando che dirime la questione.

Iniziate nominando il builder, non il Dockerfile

BuildKit può essere locale, in un container o su un’altra macchina, e ognuno ha la propria rete predefinita. Eseguite docker buildx ls e leggete il nodo contrassegnato da un asterisco prima di cambiare qualsiasi cosa. Un docker-container driver o un builder cloud non condivide il percorso privato del vostro portatile solo perché avete digitato lì il comando. Se il builder attivo è remoto, ogni controllo restante deve girare contro quell’host e non contro la vostra postazione.

Il builder porta anche la propria configurazione del resolver e le proprie variabili proxy. Entrambe vengono lette al momento della build e non sono ereditate dal terminale che l’ha avviata.

Dimostrate il percorso di rete dall’interno di un passo di build

Scrivete uno stadio usa e getta che risolve l’host della dipendenza e apre una connessione verso di esso. È l’unico test che risponde alla domanda per il builder e non per la vostra 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/

Compilate quel file con lo stesso builder, la stessa modalità di rete e gli stessi montaggi di segreti che usa la vostra build reale: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. Se getent non stampa nulla, il guasto è nella risoluzione dei nomi e nessuna credenziale lo risolverà. Se il nome si risolve ma curl segnala un timeout, l’ostacolo è il percorso o la politica di uscita davanti al registro.

Eliminate la sonda appena risponde. È uno stadio diagnostico e non dovrebbe mai essere etichettato né inviato.

Montate la credenziale invece di copiarla

Quando il percorso funziona, l’autenticazione è il guasto successivo in coda. Un montaggio di segreto di BuildKit espone un file a un solo RUN passo senza scriverlo in uno strato, ed è ciò che serve allo strumento delle dipendenze e ciò che l’immagine non deve conservare.

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

Il segreto va fornito dall’esterno del Dockerfile: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. Il file resta sul client e non entra mai nella cronologia dell’immagine. Un ARG o una ENV con lo stesso token non svolgono questo compito, perché entrambe vengono registrate nella configurazione dell’immagine.

Un’immagine senza root ha bisogno del proprio percorso di destinazione, per esempio /home/app/.npmrc o il file equivalente per pip, Maven o Cargo. La destinazione del montaggio deve corrispondere all’utente che esegue il comando, altrimenti lo strumento segnalerà un file di configurazione mancante che in realtà è presente.

Verificate cosa lascia lo strumento delle dipendenze nell’immagine

Un montaggio temporaneo tiene la credenziale fuori da uno strato, ma non impedisce allo strumento di scrivere altro. I gestori di pacchetti lasciano file di lock, directory di cache e talvolta l’URL del registro già risolto.

Leggete il file system finito invece di fidarvi del Dockerfile. docker history --no-trunc image:tag elenca ogni comando di strato, e docker run --rm image:tag sh -c "ls -a /root" mostra cosa è sopravvissuto nel container in esecuzione. Anche quando il file è stato solo montato, un token scritto in una riga di log durante npm ci resta una fuga.

Leggete anche il log di build, perché --progress=plain stampa l’output dei comandi alla lettera. Se il token compare lì, ruotatelo prima di ogni altra cosa e fatelo passare attraverso un file che lo strumento legge in silenzio.

Verificate che l’immagine di esecuzione non abbia più bisogno del percorso privato

La build e l’applicazione in esecuzione sono due consumatori diversi della stessa dipendenza, e solo il primo ha bisogno del percorso privato. Un’immagine finita dovrebbe avviarsi, risolvere le proprie dipendenze di esecuzione e servire traffico senza la credenziale di build.

Provatelo dove il registro privato non è raggiungibile, oppure avviate semplicemente il container con --network none e confermate che parte senza il segreto montato. Un container che parte solo quando il segreto di build è presente è ancora accoppiato all’ambiente di build.

Se il container ha davvero bisogno del registro in esecuzione, è una decisione di accesso separata, e appartiene all’archivio dei segreti dell’orchestratore e non alla build. Documentate i due percorsi separatamente perché nessuno provi a riparare un pull in esecuzione con un flag di build. Quando tutti e cinque i controlli passano, il sintomo originale ha una causa nominata a ogni strato invece di una congettura sulla rete Docker.

Articoli correlati