Il modo di base per applicare un aggiornamento dell'immagine consiste nell'estrarre la nuova immagine, distruggere i contenitori in esecuzione basati sulla versione precedente e quindi avviare nuovi contenitori al loro posto.
Ecco un esempio per un contenitore che utilizza l' nginx:latestimmagine:
# Pull new image
docker pull nginx:latest
# Delete old container by name
docker rm example-nginx
# Start a new container
docker run -d -p 80:80 --name example-nginx nginx:latest
Docker non dispone di un modo integrato per rilevare gli aggiornamenti delle immagini e sostituire i contenitori in esecuzione. Il risultato è un complicato processo di sostituzione manuale. Può essere semplificato utilizzando Docker Compose per avviare i contenitori invece del semplice docker runcomando.
Docker Compose consente di creare rappresentazioni dichiarative di pile di contenitori utilizzando un docker-compose.ymlfile. Lo stack viene avviato con docker-compose up, utilizzando la configurazione contenuta nel file. Questo sostituisce il lungo elenco di flag solitamente assegnato a docker run.
Docker Compose ha un pullcomando integrato che estrarrà versioni aggiornate di tutte le immagini nel tuo stack. È ancora una procedura in due fasi in quanto è necessario eseguirla di docker-compose upnuovo manualmente in seguito.
# Pull all images in the stack
docker-compose pull
# Restart the stack
# If a new image version has been pulled, containers
# using the old tag will be replaced with new instances.
docker-compose up -d
Docker Compose offre un'esperienza più semplice e memorabile in cui non è necessario digitare i nomi delle immagini o ricordare i flag a cui si è passati docker run. I due comandi possono essere facilmente abbreviati in un singolo alias di shell:
alias composePullUp="docker-compose pull && docker-compose up -d"
Devi fare riferimento al tag corretto quando estrai le immagini manualmente. Docker Compose lo gestirà per te e selezionerà i tag specificati nel tuo file docker-compose.yml.
L'estrazione della nuova versione di un tag non è necessariamente uguale all'utilizzo della versione più recente di un'immagine. Se desideri utilizzare l'ultima versione del software all'interno del contenitore, presta attenzione alle pratiche di tagging dell'autore dell'immagine.
Ad esempio, estraendo una nuova versione di node:14otterrai l'ultima versione della patch di Node.js 14. Tirando otterrai la versione node:latestpiù recente di Node.js, attualmente 16. Se un vecchio contenitore utilizzava questa immagine, un processo di pull e sostituzione attiverebbe un importante aumento della versione per il binario del nodo all'interno del contenitore.
Ricostruire le immagini
Finora abbiamo visto come gestire i contenitori iniziati da immagini che stai estraendo direttamente da Docker Hub o da un altro registro. Le immagini che stai costruendo tu stesso devono essere ricostruite quando la loro immagine di base cambia.
Prima ricostruisci l'immagine:
docker build --pull -t my-image:latest .
Quindi sostituisci i tuoi contenitori:
# Delete old container by name
docker rm my-container
# Start a new container
docker run -d --name my-container my-image:latest
Il flag --pull assegnato a docker build indica a Docker di estrarre l'immagine di base a cui si fa riferimento nel file Dockerfile. Senza questo flag, Docker riutilizzerebbe il riferimento al tag esistente se l'immagine fosse già presente nel sistema.
Gli utenti di Docker Compose possono ottenere gli stessi risultati con i docker-composecomandi corrispondenti :
docker-compose build --pull
docker-compose up -d
Compose offre ancora una volta un processo più semplice, anche se ancora in due fasi. Puoi dimenticare nomi e tag di immagini specifici, affidandoti invece a Compose per estrarre le immagini di base modificate, ricostruire i tuoi livelli sopra di esse e quindi ricreare i tuoi contenitori.
A volte può essere allettante aggiornare manualmente il software all'interno dei contenitori. Questo dovrebbe essere evitato in quanto vanno di nuovo i principi di Docker.
L'esecuzione in apt-get update && apt get upgrade -ybase a una pianificazione (o alle controparti del gestore di pacchetti) è una pratica standard quando si amministra un server Linux bare metal. Questi comandi non vengono normalmente eseguiti all'interno di un contenitore Docker, sebbene possano essere inclusi come parte di un programma Dockerfileper ottenere le ultime patch di sicurezza durante la creazione di un'immagine.
Tirare periodicamente l'immagine di base e ricreare i contenitori è il modo migliore per tenerli aggiornati. Ciò fornisce tutte le correzioni di sicurezza a monte e riduce la durata dei singoli contenitori. Gli ambienti container non devono essere modificati dopo la creazione di un'istanza; le modifiche al filesystem dovrebbero essere limitate alle scritture su percorsi temporanei e volumi Docker dedicati che sopravvivono al contenitore.
Puoi automatizzare il processo di verifica della presenza di tag immagine aggiornati e riavviare i contenitori utilizzando progetti di terze parti. La Watchtower è una scelta popolare che monitora i container in esecuzione e li sostituisce quando l'immagine dell'hub Docker cambia.
La stessa Watchtower viene distribuita come container:
docker run -d -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower
Ora hai un'installazione Watchtower funzionante. Il socket Docker del tuo host è montato nel contenitore Watchtower, consentendogli di eseguire comandi Docker per creare ed eliminare contenitori.
La Watchtower rileverà automaticamente le nuove versioni di immagini su Docker Hub, le trasferirà sul tuo computer e sostituirà i contenitori utilizzando l'immagine. I contenitori esistenti verranno chiusi e al loro posto ne verranno creati di nuovi identici. Le stesse bandiere a cui hai assegnato docker runverranno fornite ai contenitori sostitutivi.
La Watchtower funziona solo con Docker Hub per impostazione predefinita. Puoi usarlo con i registri di immagini privati fornendo le credenziali in un file di configurazione.
Crea un file JSON con il seguente contenuto:
{
"auths": {
"example.com": {
"auth": "credentials"
}
}
}
Sostituisci example.com con il percorso del tuo registro.
Quindi genera una stringa di credenziali dal nome utente e dalla password del registro:
echo -n 'username:password' | base64
Incolla la stringa con codifica Base64 risultante nel file di configurazione, sostituendo il credentialstesto segnaposto.
Monta il file di configurazione nel tuo contenitore Watchtower per consentire l'accesso al tuo registro:
docker run -d \
-v config.json:/config.json
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower
Docker non dispone di alcun meccanismo per rilevare e applicare gli aggiornamenti delle immagini upstream ai contenitori in esecuzione. Puoi utilizzare i comandi Docker CLI in sequenza, docker-composecome un'astrazione di livello superiore, o uno strumento di terze parti come Watchtower per sostituire i tuoi contenitori quando vengono rilasciate nuove versioni dell'immagine.
A seconda delle circostanze, potresti non sentire la necessità di aggiornare i contenitori in questo modo. Se il tuo team utilizza pipeline CI per creare un'immagine Docker su ogni commit, potresti già produrre e distribuire immagini aggiornate più volte al giorno. In questo caso, assicurati di utilizzare il flag --pull in docker buildmodo che le correzioni a monte siano incluse nelle tue immagini.