6.1 Introduzione all'ottimizzazione delle immagini
Le immagini Docker, anche se compatte, occupano comunque spazio. Quindi ridurne le dimensioni è una cosa importante, perché aiuta a migliorare le prestazioni, velocizzare il caricamento e il deploy dei container e a ridurre i costi di archiviazione. Si può ottimizzare un'immagine migliorando il Dockerfile, dato che si può organizzarlo in vari modi. In questa lezione vedremo alcune strategie e best practice per creare immagini Docker ottimizzate e leggere.
Perché è importante ridurre la dimensione delle immagini Docker?
- Velocità di deploy: immagini più piccole vengono caricate più velocemente dal registro Docker e deployate nei container, cosa particolarmente importante nei sistemi CI/CD automatizzati.
- Uso efficiente delle risorse: le immagini leggere occupano meno spazio su disco, risparmiano risorse di rete durante il trasferimento e garantiscono un utilizzo più efficiente della potenza di calcolo.
- Sicurezza: immagini più piccole di solito contengono meno componenti superflui, riducendo il rischio di vulnerabilità potenziali.
- Semplificazione degli aggiornamenti: aggiornare immagini leggere è più veloce e richiede meno risorse, accelerando il processo di manutenzione.
6.2 Strategie per ridurre la dimensione delle Docker images
1. Utilizzo di immagini base minimali
La scelta dell'immagine base influenza direttamente la dimensione dell'immagine Docker finale. L'utilizzo di immagini base minimali, come alpine
, consente di ridurre significativamente la dimensione dell'immagine.
Esempio:
Sostituire l'immagine ubuntu
con alpine
:
# FROM ubuntu:20.04
FROM alpine:3.12
alpine
è una distribuzione Linux leggera che occupa circa 5 MB, mentre un'immagine ubuntu
può occupare centinaia di megabyte.
2. Minimizzazione del numero di layer
Ogni istruzione nel Dockerfile aggiunge un nuovo layer all'immagine. Combinare più comandi in un'unica istruzione RUN
riduce il numero di layer, contribuendo a ridurre la dimensione complessiva dell'immagine.
Esempio:
Prima dell'ottimizzazione:
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
RUN rm -rf /var/lib/apt/lists/*
Dopo l'ottimizzazione:
RUN apt-get update && apt-get install -y curl git && rm -rf /var/lib/apt/lists/*
La rimozione della cache del package manager (rm -rf /var/lib/apt/lists/*)
riduce ulteriormente la dimensione dell'immagine, eliminando i file temporanei creati durante l'installazione.
3. Rimozione dei file temporanei
La rimozione dei file temporanei e dei dati inutili dopo l'installazione dei pacchetti aiuta a mantenere l'immagine pulita e leggera.
Esempio:
RUN apt-get update && apt-get install -y curl git && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
4. Uso di .dockerignore
Il file .dockerignore
consente di escludere file e directory inutili dal build context, riducendo così la dimensione dell'immagine e accelerando il processo di build.
Esempio di .dockerignore
:
node_modules
dist
*.log
Dockerfile*
.dockerignore
5. Build multi-stage (multi-stage builds)
Il build multi-stage consente di sfruttare più immagini intermedie per creare un'immagine finale leggera, contenente solo i file e le dipendenze necessarie.
Esempio:
# Fase di build
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Fase finale
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
In questo esempio, la prima fase crea il build dell'applicazione, mentre la fase finale utilizza solo i risultati del build, riducendo così la dimensione dell'immagine finale.
6. Ottimizzazione dell'installazione dei pacchetti
Installare solo i pacchetti necessari e utilizzare le opzioni dei package manager per installazioni minime aiuta a ridurre la dimensione dell'immagine.
Esempio:
Utilizzo del parametro --no-install-recommends
con apt-get
:
RUN apt-get update && apt-get install -y --no-install-recommends curl git && \
rm -rf /var/lib/apt/lists/*
7. Compressione e minimizzazione dei dati
L'uso di strumenti per la compressione e la minimizzazione dei dati contribuisce a ridurre la dimensione dell'immagine.
Esempio:
Compressione dei file di testo e dei log:
RUN gzip /path/to/large/file.log
8. Rimozione di librerie e dipendenze inutilizzate
La rimozione di librerie e dipendenze inutilizzate dopo l'installazione dei pacchetti necessari aiuta a mantenere l'immagine leggera.
Esempio:
Per le applicazioni Python:
RUN pip install --no-cache-dir -r requirements.txt
6.3 Esempi di Dockerfile ottimizzati
Esempio 1: Dockerfile ottimizzato per Node.js
FROM node:14-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
Questo esempio utilizza una build multi-step. Prima l'applicazione viene costruita in una fase intermedia, e poi solo i risultati della build vengono copiati nell'immagine finale basata su Nginx.
Esempio 2: Dockerfile ottimizzato per Python
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
In questo esempio viene utilizzata un'immagine di base leggera python:3.9-slim
. L'installazione delle dipendenze è spostata in uno step separato, il che permette di utilizzare la cache di Docker se il file requirements.txt
non è stato modificato.
GO TO FULL VERSION