Piccole immagini Docker che credono in se stesse*

[riferimento alla fiaba americana per bambini "La piccola locomotiva che poteva" - ca. sentiero]*

Piccole immagini Docker che credono in se stesse*

Come creare automaticamente piccole immagini Docker per le tue esigenze

Ossessione insolita

Negli ultimi due mesi sono stato ossessionato da quanto piccola possa essere un'immagine Docker e l'applicazione è ancora in esecuzione?

Capisco, l'idea è strana.

Prima di entrare nei dettagli e nei dettagli tecnici, vorrei spiegare perché questo problema mi ha disturbato così tanto e come ti preoccupa.

Perché le dimensioni contano

Riducendo il contenuto dell'immagine Docker, riduciamo così l'elenco delle vulnerabilità. Inoltre, rendiamo le immagini più pulite, perché contengono solo ciò che è necessario per eseguire le applicazioni.

C'è un altro piccolo vantaggio: le immagini vengono scaricate un po' più velocemente, ma, secondo me, non è così importante.

Nota: se sei preoccupato per la taglia, gli stessi modelli Alpine sono piccoli e probabilmente ti andranno bene.

Immagini senza distro

Progetto Distroless offre una selezione di immagini di base "senza distribuzione", non contengono gestori di pacchetti, shell e altre utilità che sei abituato a vedere sulla riga di comando. Di conseguenza, utilizzare gestori di pacchetti come pip и apt non funzionerà:

FROM gcr.io/distroless/python3
RUN  pip3 install numpy

Dockerfile utilizzando l'immagine senza distribuzione di Python 3

Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM gcr.io/distroless/python3
 ---> 556d570d5c53
Step 2/2 : RUN  pip3 install numpy
 ---> Running in dbfe5623f125
/bin/sh: 1: pip3: not found

Pip non è nell'immagine

Di solito questo problema viene risolto con una build in più fasi:

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/

Assemblaggio multistadio

Il risultato è un'immagine di 130 MB di dimensione. Non male! Per fare un confronto: l'immagine Python predefinita pesa 929 MB e quella "più sottile" (3,7-slim) - 179MB, immagine alpina (3,7-alpine) è di 98,6 MB, mentre l'immagine di base senza distribuzione utilizzata nell'esempio è di 50,9 MB.

È giusto sottolineare che nell'esempio precedente stiamo copiando un'intera directory /usr/local/lib/python3.7/site-packages, che potrebbe contenere dipendenze di cui non abbiamo bisogno. Sebbene sia chiaro che la differenza di dimensione di tutte le immagini di base Python esistenti varia.

Al momento in cui scrivo, Google Distroless non supporta molte immagini: Java e Python sono ancora in fase sperimentale e Python esiste solo per 2,7 e 3,5.

Piccole immagini

Torniamo alla mia ossessione per la creazione di piccole immagini.

In generale, volevo vedere come vengono costruite le immagini senza distro. Il progetto senza distribuzione utilizza lo strumento di creazione di Google bazel. Tuttavia, installare Bazel e scrivere le tue immagini ha richiesto molto lavoro (e, a dire il vero, reinventare la ruota è divertente ed educativo). Volevo semplificare la creazione di immagini più piccole: l'atto di creare un'immagine dovrebbe essere estremamente semplice, banale. In modo che non ci siano file di configurazione per te, solo una riga nella console: просто собрать образ для <приложение>.

Quindi, se vuoi creare le tue immagini, sappi: esiste un'immagine docker così unica, scratch. Scratch è un'immagine "vuota", non contiene file, anche se pesa per impostazione predefinita - wow! -77 byte.

FROM scratch

Gratta immagine

L'idea di un'immagine scratch è che puoi copiare qualsiasi dipendenza dal computer host al suo interno e usarla all'interno di un Dockerfile (è come copiarla su apt e installarlo da zero) o successivamente quando l'immagine Docker viene materializzata. Ciò consente di controllare completamente il contenuto del contenitore Docker e quindi di controllare completamente la dimensione dell'immagine.

Ora dobbiamo in qualche modo raccogliere queste dipendenze. Strumenti esistenti come apt consentono di scaricare pacchetti, ma sono vincolati alla macchina corrente e, dopo tutto, non supportano Windows o MacOS.

Quindi ho deciso di creare il mio strumento in grado di creare automaticamente un'immagine di base della dimensione più piccola possibile e di eseguire anche qualsiasi applicazione. Ho usato i pacchetti Ubuntu/Debian, ho fatto una selezione (ottenendo i pacchetti direttamente dai repository) e ho trovato ricorsivamente le loro dipendenze. Il programma avrebbe dovuto scaricare automaticamente l'ultima versione stabile del pacchetto, riducendo al minimo i rischi per la sicurezza.

Ho dato un nome allo strumento fetchy, perché lui... trova e porta... ciò che occorre [dall'inglese "prendere", "portare" - ca. sentiero]. Lo strumento funziona tramite un'interfaccia a riga di comando, ma allo stesso tempo offre un'API.

Per assemblare un'immagine utilizzando fetchy (prendiamo un'immagine Python questa volta), devi solo usare la CLI in questo modo: fetchy dockerize python. Potrebbe esserti chiesto il sistema operativo di destinazione e il nome in codice perché fetchy attualmente utilizza solo pacchetti basati su Debian e Ubuntu.

Ora puoi scegliere quali dipendenze non sono affatto necessarie (nel nostro contesto) ed escluderle. Ad esempio, Python dipende da Perl, sebbene funzioni bene senza Perl installato.

Giudizio

Immagine Python creata utilizzando il comando fetchy dockerize python3.5 pesa solo 35MB (sono più che sicuro che in futuro potrà essere reso ancora più leggero). Si scopre che siamo riusciti a eliminare altre 15 WW dall'immagine senza distro.

Puoi vedere tutte le immagini raccolte finora qui.

Progetto - qui.

Se ti mancano funzionalità, crea semplicemente una richiesta: sarò felice di aiutarti :) Inoltre, sto attualmente lavorando per integrare altri gestori di pacchetti in fetchy, in modo che non siano necessarie build in più fasi.

Fonte: habr.com

Aggiungi un commento