Dopo alcune ricerche e test, ho scoperto di avere dei malintesi sulla durata dei container Docker. Il semplice riavvio di un contenitore non fa sì che Docker utilizzi una nuova immagine, quando nel frattempo l'immagine è stata ricostruita. Invece, Docker sta recuperando l'immagine solo prima di creare il contenitore. Quindi lo stato dopo l'esecuzione di un contenitore è persistente.
Perché è necessaria la rimozione
Pertanto, la ricostruzione e il riavvio non sono sufficienti. Pensavo che i contenitori funzionassero come un servizio: arrestare il servizio, apportare le modifiche, riavviarlo e verranno applicate. Questo è stato il mio più grande errore.
Poiché i contenitori sono permanenti, devi docker rm <ContainerName>
prima rimuoverli utilizzando . Dopo che un contenitore è stato rimosso, non puoi semplicemente avviarlo docker start
. Questo deve essere fatto utilizzando docker run
, che a sua volta utilizza l'immagine più recente per creare una nuova istanza di contenitore.
I contenitori dovrebbero essere il più indipendenti possibile
Con questa conoscenza, è comprensibile il motivo per cui l'archiviazione dei dati nei contenitori è considerata una cattiva pratica e Docker consiglia invece i volumi di dati / il montaggio di directory host : poiché un contenitore deve essere distrutto per aggiornare le applicazioni, anche i dati memorizzati all'interno andrebbero persi. Ciò causa un lavoro extra per i servizi di arresto, i dati di backup e così via.
Quindi è una soluzione intelligente escludere completamente quei dati dal contenitore: non dobbiamo preoccuparci dei nostri dati, quando sono archiviati in modo sicuro sull'host e il contenitore contiene solo l'applicazione stessa.
Perché -rf
potrebbe non aiutarti davvero
Il docker run
comando ha un'opzione Clean up chiamata -rf
. Si interromperà il comportamento di mantenere i container docker in modo permanente. Usando -rf
, Docker distruggerà il contenitore dopo che è stato chiuso. Ma questo interruttore ha due problemi:
- Docker rimuove anche i volumi senza un nome associato al contenitore, il che potrebbe uccidere i tuoi dati
- Utilizzando questa opzione, non è possibile eseguire contenitori in background utilizzando
-d
interruttore
Sebbene l' -rf
interruttore sia una buona opzione per risparmiare lavoro durante lo sviluppo per test rapidi, è meno adatto in produzione. Soprattutto a causa dell'opzione mancante per eseguire un contenitore in background, che sarebbe per lo più richiesta.
Come rimuovere un contenitore
Possiamo aggirare queste limitazioni semplicemente rimuovendo il contenitore:
docker rm --force <ContainerName>
L' opzione --force
(o -f
) che utilizza SIGKILL sui container in esecuzione. Invece, potresti anche fermare il contenitore prima:
docker stop <ContainerName>
docker rm <ContainerName>
Entrambi sono uguali. docker stop
utilizza anche SIGTERM . Ma l'utilizzo di --force
switch ridurrà lo script, soprattutto quando si utilizzano server CI: docker stop
genera un errore se il contenitore non è in esecuzione. Ciò indurrebbe Jenkins e molti altri server CI a considerare la build erroneamente come fallita. Per risolvere questo problema, devi prima controllare se il contenitore è in esecuzione come ho fatto nella domanda (vedi containerRunning
variabile).
Script completo per la ricostruzione di un container Docker
In base a questa nuova conoscenza, ho corretto il mio script nel modo seguente:
#!/bin/bash
imageName=xx:my-image
containerName=my-container
docker build -t $imageName -f Dockerfile .
echo Delete old container...
docker rm -f $containerName
echo Run new container...
docker run -d -p 5000:5000 --name $containerName $imageName
Funziona perfettamente :)