I contenitori Docker sono generalmente istanze di applicazioni temporanee prive di stato interno. Questo è il modo migliore per gestirli che ti consente di interrompere o riavviare i tuoi contenitori in qualsiasi momento.
Tuttavia, a volte le modifiche al filesystem di un contenitore sono inevitabili. Forse stai provando un software e desideri che un'istantanea torni in un secondo momento. Un altro caso d'uso potrebbe essere situazioni in cui il software all'interno di un container ha smesso di funzionare e si desidera salvare una replica di cui è possibile eseguire il debug in futuro.
Ecco come creare una nuova immagine Docker da un contenitore esistente. Potrai quindi avviarne un altro contenitore da quell'immagine che verrà popolata con il filesystem dalla prima.
Contenitori impegnati
Il docker commit
comando viene utilizzato per prendere un contenitore e produrre una nuova immagine da esso. Funziona con container fermi o in esecuzione.
La sintassi di base è la seguente:
docker commit example-container example-image:latest
Questo crea un'immagine dal contenitore denominata example-container
. Puoi anche identificare il contenitore per ID, se preferisci. Entrambe le informazioni sono disponibili dall'output di docker ps
che elenca tutti i contenitori sul tuo host.
All'immagine risultante viene assegnato il tag fornito come secondo parametro del comando. Questo è example-image:latest
nell'esempio mostrato sopra. Proprio come una normale operazione di codifica delle immagini, la nuova immagine sostituirà il riferimento del tag se esiste già.
Ora puoi usare la tua immagine per ripristinare il filesystem da example-container
in una nuova istanza del contenitore:
docker run -d example-image:latest
Il contenuto del filesystem corrisponderà al example-container
contenitore al momento del docker commit
comando è stato eseguito C'è un avvertimento importante:il contenuto dei volumi montati non sarà incluso, quindi le loro posizioni di montaggio saranno vuote nell'immagine del contenitore creata. Per eseguire un nuovo container con i dati del volume intatti, utilizza -v
flag per ricollegare i volumi dal primo contenitore quando avvii la seconda istanza con docker run
.
Un altro punto critico degno di nota è il modo in cui Docker gestisce i commit dei contenitori in esecuzione. Per la maggior parte, questo dovrebbe funzionare senza problemi, ma per impostazione predefinita mette in pausa il contenitore di destinazione prima che venga creato il commit. Tutti i processi all'interno del contenitore verranno sospesi e quindi ripresi al termine della creazione dell'immagine. Ciò migliora la coerenza dei dati nella nuova immagine ma lascia momentaneamente inaccessibile il contenitore. Puoi disabilitare questo comportamento includendo --pause false
con il tuo docker commit
comando.
Aggiunta di messaggi di commit
Il docker commit
comando supporta i messaggi di commit in modo simile al software di controllo della versione come Git. L'aggiunta di un messaggio quando crei un'immagine da un contenitore ti consente di documentare cosa è cambiato e il motivo del tuo commit.
Usa il --message
o -m
flag per applicare un messaggio di commit:
docker commit -m "Example commit" example-container example-image:latest
Puoi anche aggiungere informazioni sulla paternità con un flag dedicato. Fornisci una stringa nel comune First Name <[email protected]>
formattare in --author
o -a
bandiera. Verrà salvato insieme al messaggio di commit.
docker commit -a "Example Author <[email protected]>" -m "Example commit" example-container example-image:latest
I messaggi di commit vengono visualizzati quando utilizzi la docker history
comando per visualizzare i livelli in un'immagine. Verranno visualizzati nel COMMENT
colonna all'estrema destra.
Un altro modo per accedere a queste informazioni è usare docker inspect
in tandem con grep
per estrarre la paternità e i valori dei commenti dalla rappresentazione JSON di un'immagine:
docker inspect <image-id> | grep 'Created|Author|Comment'
Questo mostrerà i dati associati al livello più in alto nell'immagine.
Modifica delle istruzioni di Dockerfile
Il commit di un'immagine ti dà la possibilità di mutare alcune delle sue istruzioni Dockerfile. Puoi sovrascrivere i seguenti valori nella tua nuova immagine:
CMD
ENTRYPOINT
ENV
EXPOSE
LABEL
ONBUILD
USER
VOLUME
WORKDIR
Per impostare un'istruzione, usa il --change
o -c
bandiera:
docker commit --change 'ENTRYPOINT ["sh"]' example-container example-image:latest
Puoi ripetere il flag tutte le volte necessarie per applicare tutte le modifiche previste.
Sono supportate solo le istruzioni che influiscono sul livello più alto del filesystem. Non puoi estendere senza problemi un'immagine impegnata con nuovi livelli tramite istruzioni come RUN
e COPY
. Tuttavia potresti prendere il risultato di un commit e scrivere un nuovo Dockerfile che aggiunge nuovo contenuto se necessario:
# Created via `docker commit` FROM example-image:latest RUN apt install example-package
Se modifichi le istruzioni di Dockerfile al momento del commit, vale la pena aggiungere un messaggio di commit che spieghi cosa stai modificando e perché. Ciò aiuterà chiunque altro abbia accesso all'immagine a comprendere eventuali differenze di comportamento rispetto al contenitore da cui è stata creata.
Riepilogo
Le immagini Docker sono generalmente create da Dockerfiles e utilizzate per avviare contenitori usa e getta. Le modifiche allo stato del filesystem di un contenitore vengono apportate ricostruendo l'immagine, distruggendo il contenitore esistente e avviandone uno nuovo. In un mondo ideale, i container non hanno alcuno stato interno, ma questo non è sempre vero nella pratica.
Il commit di un container ti dà un modo per ripristinare il suo attuale filesystem in futuro. I commit sono utili per creare repliche di contenitori problematici in modo da poter eseguire il debug in un ambiente separato mantenendo l'accesso ai log e ai file temporanei generati in precedenza.
Sebbene i commit del contenitore siano spesso simili agli snapshot VM, non sono proprio la stessa cosa. Le macchine virtuali controllano l'hardware virtuale e lo stato di tale hardware sarà presente all'interno dello snapshot. I container Docker sono solo un insieme di processi in esecuzione sull'host; un commit è una nuova immagine Docker che rappresenta il filesystem del contenitore ma manca necessariamente di dati sullo stato dei processi, del kernel e dell'hardware.