[riferimento alla fiaba americana per bambini “Il piccolo locomotore che poteva” (“The Little Engine That Could”) — nota del traduttore]*

Come creare automaticamente piccolissimi docker image per le proprie esigenze
Un'ossessione insolita
Negli ultimi due mesi sono stato ossessionato da un’idea fissa: quanto si può ridurre un'immagine Docker mantenendo l'applicazione funzionante?
Capisco, l'idea è strana.
Prima di approfondire i dettagli e gli aspetti tecnici, vorrei spiegare perché questo problema mi ha così colpito e come riguarda anche voi.
Perché la dimensione conta
Riducendo il contenuto di un'immagine Docker, limitiamo anche l'elenco delle vulnerabilità. Inoltre, rendiamo le immagini più pulite, poiché contengono solo ciò che è necessario per eseguire le applicazioni.
C'è anche un piccolo vantaggio — le immagini vengono scaricate un po' più rapidamente, ma a mio parere, non è così rilevante.
Nota: Se siete preoccupati per la dimensione, le immagini Alpine sono piccole di per sé e sicuramente si adatteranno alle vostre esigenze.
Immagini Distroless
offre una selezione di immagini «distroless» di base, che non contengono gestori di pacchetti, shell e altre utilità che sei abituato a vedere nella riga di comando. Di conseguenza, gestire pacchetti come pip e apt non sarà possibile:
FROM gcr.io/distroless/python3
RUN pip3 install numpyDockerfile che utilizza l'immagine distroless Python 3
Invio del contesto di build al demone Docker 2.048kB
Step 1/2 : FROM gcr.io/distroless/python3
---> 556d570d5c53
Step 2/2 : RUN pip3 install numpy
---> Esecuzione in dbfe5623f125
/bin/sh: 1: pip3: non trovatoPip non è presente nell'immagine
Di solito, questo problema è risolvibile attraverso una build multi-stage:
FROM python:3 as builder
RUN pip3 install numpy
FROM gcr.io/distroless/python3
COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.5/Build multi-stage
Di conseguenza, si ottiene un'immagine di dimensione 130 MB. Non è affatto male! A titolo di confronto: l'immagine Python di default pesa 929 MB, mentre quella «snellita» (3.7-slim) pesa 179 MB, e l'immagine alpine (3.7-alpine) pesa 98,6 MB, mentre l'immagine distroless di base utilizzata nell'esempio pesa 50,9 MB.
Si può giustamente sottolineare che nell'esempio precedente stiamo copiando un intero catalogo /usr/local/lib/python3.7/site-packages, che potrebbe contenere dipendenze non necessarie. Anche se è chiaro che la differenza nelle dimensioni di tutte le immagini di base Python esistenti varia.
Al momento della scrittura di queste righe, Google distroless supporta un numero limitato di immagini: Java e Python sono ancora in fase di sperimentazione, mentre Python esiste solo per le versioni 2.7 e 3.5.
Immagini minuscole
Tornando alla mia ossessione per la creazione di immagini piccole.
In realtà, volevo vedere come sono costruite le immagini distroless. Il progetto distroless utilizza l'outil di build di Google bazel. Tuttavia, per installare Bazel e creare le proprie immagini, è stato necessario faticare (e per essere completamente onesti, reinventare la ruota — è divertente e formativo). Volevo semplificare la creazione di immagini ridotte: il processo di creazione dell'immagine dovrebbe essere estremamente semplice, banale. Senza file di configurazione, solo una riga nel terminale: basta costruire l'immagine per.
Quindi, se vuoi creare le tue immagini, sappi che esiste un'immagine docker unica, scratch. Scratch è un'immagine "vuota", non contiene file, anche se di default pesa — wow! — 77 byte.
FROM scratchL'immagine scratch
L'idea dell'immagine scratch è che puoi copiare al suo interno tutte le dipendenze dalla macchina host e utilizzarle nel Dockerfile (è come copiarle in apt e installarlo da zero), oppure più tardi, quando l'immagine Docker si materializza. Questo consente di controllare completamente il contenuto del container Docker e, di conseguenza, di controllare anche completamente le dimensioni dell'immagine.
Ora dobbiamo trovare un modo per raccogliere queste dipendenze. Gli strumenti esistenti come apt consentono di scaricare pacchetti, ma sono legati alla macchina attuale e, alla fine, non supportano Windows o MacOS.
Così ho deciso di creare un mio strumento che potesse costruire automaticamente un'immagine di base delle dimensioni minime possibili e fosse in grado di eseguire qualsiasi applicazione. Ho utilizzato pacchetti Ubuntu/Debian, effettuando il download (prendendo i pacchetti direttamente dai repository) e trovando ricorsivamente le loro dipendenze. Il programma doveva scaricare automaticamente l'ultima versione stabile disponibile del pacchetto, riducendo al minimo i rischi per la sicurezza.
Ho chiamato lo strumento fetchy, perché... trova e porta... ciò che serve [dal termine inglese «fetch», «portare» — nota del traduttore.]. Lo strumento funziona tramite interfaccia a riga di comando, ma offre anche un'API.
Per costruire l'immagine usando fetchy (prendiamo questa volta l'immagine di Python), devi soltanto usare la CLI in questo modo: fetchy dockerize python. Potrebbe essere richiesta la tua piattaforma di destinazione e il nome in codice, poiché fetchy attualmente utilizza solo pacchetti basati su Debian e Ubuntu.
Ora puoi scegliere quali dipendenze non sono necessarie (nel nostro contesto) ed escluderle. Ad esempio, Python dipende da perl, anche se funziona perfettamente senza perl installato.
Risultati
L'immagine Python creata con il comando fetchy dockerize python3.5 pesa solo 35MB (sono più che sicuro che in futuro si possa alleggerire ulteriormente). Si scopre che siamo riusciti a 'ridurre' altri 15MB dall'immagine distroless.
Puoi vedere tutte le immagini raccolte fino ad ora .
Progetto — .
Se ti mancano delle funzionalità, crea semplicemente una richiesta — sarò felice di aiutarti 🙂. Inoltre, attualmente sto lavorando all'integrazione di altri gestori di pacchetti in fetchy, in modo che non ci sia più bisogno di compilazioni a più fasi.
Fonte: habr.com
