Après quelques recherches et tests, j'ai constaté que j'avais des malentendus sur la durée de vie des conteneurs Docker. Le simple fait de redémarrer un conteneur ne permet pas à Docker d'utiliser une nouvelle image, lorsque l'image a été reconstruite entre-temps. Au lieu de cela, Docker récupère l'image uniquement avant de créer le conteneur. Ainsi, l'état après l'exécution d'un conteneur est persistant.
Pourquoi la suppression est nécessaire
Par conséquent, la reconstruction et le redémarrage ne suffisent pas. Je pensais que les conteneurs fonctionnaient comme un service: arrêter le service, faire vos modifications, le redémarrer et ils s'appliqueraient. C'était ma plus grosse erreur.
Les conteneurs étant permanents, vous devez d'abord les supprimer docker rm <ContainerName>
. Une fois qu'un conteneur est supprimé, vous ne pouvez pas simplement le démarrer docker start
. Cela doit être fait en utilisant docker run
, qui utilise elle-même la dernière image pour créer une nouvelle instance de conteneur.
Les conteneurs doivent être aussi indépendants que possible
Avec cette connaissance, on comprend pourquoi le stockage de données dans des conteneurs est qualifié de mauvaise pratique et Docker recommande plutôt des volumes de données / le montage de répertoires hôtes : puisqu'un conteneur doit être détruit pour mettre à jour les applications, les données stockées à l'intérieur seraient également perdues. Cela entraîne un travail supplémentaire pour arrêter les services, sauvegarder les données, etc.
C'est donc une solution intelligente pour exclure complètement ces données du conteneur: nous n'avons pas à nous soucier de nos données, lorsqu'elles sont stockées en toute sécurité sur l'hôte et que le conteneur ne contient que l'application elle-même.
Pourquoi -rf
ne peut pas vraiment vous aider
La docker run
commande a un commutateur de nettoyage appelé -rf
. Cela arrêtera le comportement de garder les conteneurs docker de manière permanente. En utilisant -rf
, Docker détruira le conteneur après sa sortie. Mais ce commutateur a deux problèmes:
- Docker supprime également les volumes sans nom associé au conteneur, ce qui peut tuer vos données
- En utilisant cette option, il n'est pas possible d'exécuter des conteneurs en arrière-plan à l'aide du
-d
commutateur
Bien que le -rf
commutateur soit une bonne option pour économiser du travail pendant le développement pour des tests rapides, il est moins adapté en production. Surtout à cause de l'option manquante pour exécuter un conteneur en arrière-plan, ce qui serait principalement nécessaire.
Comment retirer un conteneur
Nous pouvons contourner ces limitations en supprimant simplement le conteneur:
docker rm --force <ContainerName>
Le commutateur --force
(ou -f
) qui utilise SIGKILL sur des conteneurs en cours d'exécution. Au lieu de cela, vous pouvez également arrêter le conteneur avant:
docker stop <ContainerName>
docker rm <ContainerName>
Les deux sont égaux. docker stop
utilise également SIGTERM . Mais l'utilisation de --force
switch raccourcira votre script, en particulier lors de l'utilisation de serveurs CI: docker stop
génère une erreur si le conteneur n'est pas en cours d'exécution. Cela amènerait Jenkins et de nombreux autres serveurs CI à considérer à tort la construction comme un échec. Pour résoudre ce problème, vous devez d'abord vérifier si le conteneur fonctionne comme je l'ai fait dans la question (voir containerRunning
variable).
Script complet pour la reconstruction d'un conteneur Docker
En fonction de ces nouvelles connaissances, j'ai corrigé mon script de la manière suivante:
#!/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
Cela fonctionne parfaitement :)