Conoscere i vari stati del Docker Container è essenziale per qualsiasi utente Docker serio.
Spiegherò il ciclo di vita del contenitore e poi mostrerò i comandi Docker per ogni fase del ciclo di vita.
Ma prima di imparare tutte queste cose, rivisitiamo ancora una volta il concetto di contenitore.
Cosa sono di nuovo i container Docker?
La maggior parte delle definizioni tradizionali di container è la seguente:
I container sono una forma di virtualizzazione del sistema operativo. Sebbene la tradizionale virtualizzazione basata su hypervisor richieda kernel separati per VM separate, i container condividono lo stesso kernel host ed è quindi molto più leggero e veloce da avviare
La definizione sarà diversa da fonte a fonte, ma l'essenza è la stessa.
Lo trovo noioso e inutilmente complicato. Vorrei usare qualcosa di diverso qui per definire i contenitori.
I container sono un insieme di processi che vengono ingannati.
Perché lo dico? Perché i container sono solo una raccolta di processi, a volte solo un singolo processo. E a questi processi vengono mentite su diverse risorse del suo host come reti, albero dei processi, filesystem, nome host ecc.
Puoi eseguire qualsiasi processo, anche una shell come bash
, e nascondi il tuo albero di processo effettivo da esso, assegnagli un diverso insieme di reti, nascondi il filesystem di root effettivo da esso, assegnagli un nome host diverso ed essenzialmente, ciò che finirai per fare è creare una versione containerizzata del processo.
Ciò si ottiene con spazi dei nomi, filesystem radice e cgroup separati.
Docker è solo un involucro attorno agli strumenti di livello inferiore che eseguono e gestiscono i contenitori, o più specificamente indica il ciclo di vita del contenitore .
Oltre a questo, Docker fa anche molte altre cose, come semplificare il collegamento in rete per i container, gestire l'archiviazione, estrarre e spingere le immagini dei container, ecc.
Docker è qui per semplificarci la vita.
Ora, diamo un'occhiata al ciclo di vita del container Docker
Il ciclo di vita del contenitore è fondamentalmente una serie di fasi, a partire dalla creazione del contenitore fino alla sua distruzione.
Il diagramma seguente lo renderà molto chiaro.
Lascia che ti spieghi ogni fase del ciclo di vita del contenitore.
- Creazione: Molte persone pensano che quando si esegue un container, è un unico passaggio. Ma non è così. C'è un processo che crea i contenitori prima di ogni altra cosa. Ne parleremo più avanti.
- Avviato/In esecuzione: Una volta creato, un container può essere avviato, dopodiché lo stato cambia in
Running
. Questo è quando il contenitore sta effettivamente facendo qualcosa. - In pausa: Tradizionalmente per mettere in pausa un processo (che sostanzialmente sono i contenitori), utilizziamo il segnale SIGSTOP e per riattivare il segnale SIGCONT. Ma poiché questo segnale è osservabile dai processi, invece dei segnali vengono utilizzati i congelatori cgroup. In questo modo i processi vengono sospesi congelando il cgroup.
- Uscita/Arrestato: L'opposto di
Running
, ma non è uguale aPaused
. Arrestare un contenitore significa inviare il segnale SIGTERM al processo del contenitore principale, ovvero PID 1 nello spazio dei nomi del contenitore. Attende quindi 10 secondi per consentire al processo di uscire con grazia. In caso contrario, unSIGKILL
viene inviato il segnale e sappiamo tutti cosa significa, vero? - Distrutto/eliminato: Il container non esiste più, tutte le risorse che un tempo erano state allocate ora sono sparite.
Spero che questo abbia reso più chiaro il concetto di ciclo di vita del contenitore ora. Nella sezione seguente esaminerò tutti i comandi della finestra mobile specifici che ti aiuteranno a gestire tutti questi stati dei contenitori.
Comandi Docker per gestire il ciclo di vita dei container
Tutti i comandi (sottocomandi, se più specifici) che controllano il ciclo di vita del contenitore appartengono al sottocomando container
.
In un terminale se esegui docker container --help
otterrai un elenco di sottocomandi associati a più operazioni eseguibili sui contenitori.
Ma non siamo preoccupati per tutti loro qui. Concentriamoci solo su un sottoinsieme specifico di quelli.
Creazione del contenitore
La creazione del container è gestita dai seguenti comandi:
docker container create
docker create
La prima è la forma lunga, mentre la seconda, avete indovinato, è la forma breve.
Ti consiglio di utilizzare il modulo lungo in quanto è più dettagliato e qualcosa che considero una buona pratica.
Cos'è la creazione di container?
La creazione del contenitore consiste nel creare il livello R/W sopra i livelli R/O dell'immagine specificata e prepararlo per eseguire il programma richiesto. La creazione di un contenitore non avvia il processo effettivo, puoi specificare tutti i parametri di configurazione come capacità, limite della CPU, limite di memoria, immagine del contenitore ecc. proprio nella fase di creazione e quindi avviare il contenitore ogni volta che vuoi senza dover specificare nuovamente quei parametri .
Leggi docker container create --help
per un elenco di opzioni configurabili.
Esempio
Per prima cosa crea un contenitore come il seguente (ho usato un alpine
image qui per eseguire il comando sleep infinity
)
docker container create \
--name alpine alpine:latest sleep infinity
Una volta creato il contenitore, dovresti ottenerne l'ID nella schermata del terminale. Ora puoi filtrare l'elenco dei contenitori per trovare i contenitori che non sono in esecuzione, ma appena creati .
docker container ls --filter=status=created
Qui sto filtrando l'elenco in modo da ottenere solo i contenitori creati. Dai un'occhiata allo STATUS
colonna, questo è ciò che specifica lo stato di un contenitore. Dovresti vedere qualcosa di simile al seguente:-
➟ docker container ls --filter=status=created
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f8d56fb3f78 alpine:3.13.4 "sleep infinity" 17 seconds ago Created alpine
Puoi anche ispezionare il contenitore e vedere in che stato si trova.
➟ docker container inspect -f '{{json .State.Status}}' alpine
"created"
Usando docker create
non ti darà niente di diverso.
Avvio del contenitore
Per avviare un container, usa uno dei seguenti due comandi:-
docker container start
docker start
Stessa cosa qui, una versione lunga e una corta. E ti consiglio di usare il ...container start
comando.
Cos'è l'avvio del container?
Una volta creato un contenitore, puoi avviarlo. Avviare il container significa eseguire effettivamente l'applicazione containerizzata.
Mentre la creazione di un contenitore prepara semplicemente tutta la configurazione (modalità di esecuzione del contenitore, ambiente di runtime, vincoli di runtime, nome del contenitore ecc.), Non alloca nessuna delle risorse.
L'avvio di un container alloca le risorse necessarie ed esegue l'applicazione.
Esempio
Considera il contenitore precedente che abbiamo creato. Avvia semplicemente il comando con il nome o l'ID del contenitore in questo modo:
docker container start alpine
Una volta avviato il contenitore, il suo stato cambia da Created
a Running
. Nell'elenco dei contenitori, puoi filtrare di nuovo in base allo stato come hai fatto in precedenza:-
docker container ls --filter=status=running
Sul STATUS
colonna, invece di Running
mostrerà da quanto tempo il contenitore è in esecuzione dall'avvio.
➟ docker container ls --filter=status=running
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f8d56fb3f78 alpine:3.13.4 "sleep infinity" 8 minutes ago Up 18 seconds alpine
Puoi anche ispezionare un contenitore per vederne lo stato. Userò i modelli Go per formattare l'output sull'unica cosa di cui ho bisogno, ovvero lo stato.
docker container inspect \
-f '{{json .State.Status}}' alpine
Dovresti vedere qualcosa del genere -
➟ docker container inspect -f '{{json .State.Status}}' alpine
"running"
Non per sembrare ridondante, ma docker start
farà esattamente la stessa cosa.
Il comando di esecuzione della finestra mobile speciale
Questo è un comando speciale che lega insieme la creazione e l'avvio del container e questo è il comando che tutti usiamo di più.
docker container run
docker run
Questi comandi essenzialmente (i) creano il contenitore e quindi immediatamente (ii) avviano lo stesso contenitore.
Questo è utile perché creare e lasciare un contenitore per iniziare in un secondo momento non è qualcosa che facciamo troppo spesso. Quando sei alla riga di comando, con la Docker CLI, sei qui per eseguire un container. Ed è esattamente ciò che ...container run
comando fa.
Esempio
L'esempio di questo comando è molto semplice. Per eseguire un container, invece di docker container create
, usa docker container run
.
Lo farai devi passare tutte le opzioni che passeresti a docker container create
a questa docker container run
comando. Questo perché Docker ha bisogno di tutte quelle informazioni in quel momento poiché non ci sono più secondi passaggi.
➟ docker container run --name echo-me alpine:3.13.4 echo "Subscribe to Linux Handbook"
Subscribe to Linux Handbook
Docker Run vs Start vs Create:Differenza spiegata Per un principiante di Docker, termini come Docker Start, Docker Run e Docker Create potrebbero creare confusione. Questo articolo spiega la differenza con esempi. Manuale LinuxAbhishek Prakash Contenitore in pausa
Mettere in pausa un contenitore significa esattamente come suona. Non stiamo fermando alcun processo, ma solo mettendolo in pausa. Quindi, se un processo all'interno di un contenitore conta da 1 a 100 ed è stato messo in pausa mentre era al conteggio 50 e quindi riattivato in un secondo momento, il conteggio riprenderà da 50.
Una cosa da capire è che mentre Paused
è uno stato attuale, Unpaused
non è. Quando riattivi un contenitore in pausa, in pratica stai cambiando lo stato da Paused
a Running
.
I comandi utilizzati per mettere in pausa un contenitore sono i seguenti:-
docker container pause
docker pause
Allo stesso modo puoi riattivare un contenitore con le controparti riattivate:-
docker container unpause
docker unpause
Come viene messo in pausa un container?
Un processo viene messo in pausa utilizzando il segnale SIGSTOP e, per riattivarlo, viene utilizzato il segnale SIGCONT. Poiché questi segnali possono essere osservati dai processi, invece dei segnali vengono utilizzati i congelatori cgroup. In questo modo i processi vengono sospesi congelando il cgroup. Il congelamento di un cgroup blocca tutte le sue attività e tutti i suoi cgroup figlio.
Esempio:
Per il bene di questa demo, ho creato un contenitore speciale. Estrai l'immagine eseguendo il seguente comando:-
docker image pull debdutdeb/pause-demo:v1
Puoi controllare il Dockerfile e il codice proprio qui.
Una volta estratto, su un terminale, avvia un container con questa immagine
docker container run --name pause-demo debdutdeb/pause-demo:v1
Ora dovrebbe mostrare il conteggio a partire da 0 e in corso. Dovrebbe assomigliare al seguente
➟ docker container run --name pause-demo debdutdeb/pause-demo:v1
Count at 30
Su un altro terminale, metti in pausa questo contenitore.
docker container pause pause-demo
Nel momento in cui metti in pausa il container, dovresti vedere il conto alla rovescia interrompersi, ma il terminale non è ancora tornato da te. Questo perché il contenitore non è ancora fermo (ne parlerò più avanti in questo articolo). Dopo aver riattivato questo contenitore, il conto alla rovescia dovrebbe riprendere, non ricominciare.
docker container unpause pause-demo
Per recuperare il terminale, esegui un terminale separato
docker container stop pause-demo
Ecco un breve video che lo mostrerà in azione:-
Prima di fermare il contenitore puoi mettere mi piace ai precedenti, controlla lo stato del contenitore in pausa in questo modo:
➟ docker container inspect -f '{{json .State.Status}}' pause-demo
"paused"
Arresto del contenitore
Puoi interrompere un contenitore Docker utilizzando uno dei seguenti due comandi:-
docker container stop
docker stop
Fermare un container significa fermare tutti i processi ad esso associati.
Questo non è lo stesso che mettere in pausa un contenitore. Se interrompi un contenitore, puoi riavviarlo, ma i processi non riprenderanno dallo stato in cui si trovavano in precedenza. Un processo può salvare le sue informazioni sullo stato in un "file" e ripristinare il suo stato da quel file, ma questo è un caso diverso.
Ad esempio, dopo aver interrotto la precedente pause-demo
container, se provi a riavviarlo usando il ...container start
comando, inizierà a contare dall'inizio, a differenza della sua pause
controparte che riprende il conteggio.
Come funziona il processo?
Quando chiedi a Docker di fermare un container, invia un SIGTERM
segnale al PID 1 del contenitore. Dopodiché, attende 10 secondi, che è il suo periodo di tempo aggraziato, al processo viene concesso questo tempo per uscire con grazia, in altre parole ripulire e finire tutto ciò che stava funzionando. Trascorsi i 10 secondi, Docker invia un SIGKILL
finale segnale, non devo dirti cosa succede dopo.
Docker invia il segnale al PID 1 del contenitore perché ogni altro processo è figlio del PID 1, se questo processo viene terminato/ucciso, i processi secondari cesseranno automaticamente di esistere.
Questo diventa più chiaro con l'esempio seguente.
Esempio:
Devi estrarre un'immagine, di nuovo.
docker image pull debdutdeb/stop-demo:v1
Per il Dockerfile e il codice sorgente, dai un'occhiata a questo succo.
In un terminale, avvia un container da questa immagine.
docker container run --name stop-demo debdutdeb/stop-demo:v1
Una volta eseguito, dovresti vedere una schermata che ti dice il suo PID e che è in attesa.
➟ docker container run --name stop-demo debdutdeb/stop-demo:v1
My PID in this container is 1
Waiting...
Apri un altro terminale ed esegui il comando stop su questo container.
docker container stop stop-demo
Una volta eseguito, dovresti vedere sul terminale che stava eseguendo il container, dicendoti cosa IT sta sperimentando, ovvero ricevendo il SIGTERM
segnale.
Successivamente inizia a contare i secondi e vedrai che dopo 10 secondi smette di contare. Questo non è perché l'ho codificato in quel modo, in realtà l'ho codificato per continuare all'infinito.
Ma dopo 10 secondi Docker invia un SIGKILL
segnale che non possiamo catturare o ignorare, il processo è destinato a essere interrotto.
Puoi modificare il tempo di attesa della finestra mobile prima di inviare il SIGKILL
segnale utilizzando il -t
opzione con docker container stop
.
Una volta terminato tutto, dovresti vedere qualcosa del genere
➟ docker container run --name stop-demo debdutdeb/stop-demo:v1
My PID in this container is 1
Waiting...
SIGTERM ignored,
Starting count..
10 seconds
Ecco un piccolo video che lo dimostra:-
Puoi controllare lo stato di questo container ora usando ...container inspect
così:-
➟ docker container inspect -f '{{json .State.Status}}' stop-demo
"exited"
Eliminazione contenitore
Un contenitore viene eliminato utilizzando uno dei seguenti due comandi:-
docker container rm
docker rm
L'eliminazione del contenitore è l'opposto della creazione del contenitore. Quando elimini un contenitore, non c'è più, non puoi portare quello specifico contenitore indietro. Puoi avviarne uno nuovo dalla stessa immagine usando la stessa configurazione, renderlo identico, ma non sarà esattamente quello precedente.
Esempio:
Per un esempio, rimuovi il precedente stop-demo
contenitore.
docker container rm stop-demo
Finora, tutti i container che hai creato e poi fermato possono essere rimossi con un solo comando:-
docker container prune
Questo cancellerà tutti i contenitori con lo stato Exited
.
Esempio di output:
✗ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
ffbdd621c01d0eb3f42d348eeb75c731ddd9bd85674bb90dece32bd70357e541
21b9ed6a6198cd6ee7e162aebd936ae3e93b3b0f738161924a825a27794f2b20
f5f5149866a6ced675ad3bfff0b7386f75ee3fdbddca86be8b8ba341dba4b27f
Total reclaimed space: 0B
Quindi, hai imparato il concetto di ciclo di vita del contenitore. E hai anche imparato i comandi Docker per gestire ogni fase del ciclo di vita dei container. Se desideri altri suggerimenti su Docker, potresti conoscere questi comandi Docker meno conosciuti ma utili.
3 Comandi Docker Gli utenti Docker avanzati dovrebbero sapere Ecco alcuni comandi Docker di cui potresti non essere a conoscenza, ma potrebbero tornare utili durante la gestione dei contenitori. Linux HandbookDebdut ChakrabortySpero davvero che questo articolo abbia reso facile la comprensione della teoria del ciclo di vita del contenitore e abbia anche cancellato tutti i comandi necessari per gestire questi diversi stati.
Se hai domande, lascia un commento qui sotto.