143 votes

Reconstruire le conteneur Docker lors de modifications de fichiers

Pour l'exécution d'une ASP.NET application de Base, j'ai généré un dockerfile qui permettent de construire l'application et copys le code source dans le conteneur, qui est récupérée par Git à l'aide de Jenkins. Donc, dans mon espace de travail, je fais ce qui suit dans le dockerfile:

WORKDIR /app
COPY src src

Alors que Jenkins à jour les fichiers sur mon ordinateur hôte correctement avec Git, Docker ne s'applique pas à mon image.

Mon script de base pour la construction:

#!/bin/bash
imageName=xx:my-image
containerName=my-container

docker build -t $imageName -f Dockerfile  .

containerRunning=$(docker inspect --format="{{ .State.Running }}" $containerName 2> /dev/null)

if [ "$containerRunning" == "true" ]; then
        docker stop $containerName
        docker start $containerName
else
        docker run -d -p 5000:5000 --name $containerName $imageName
fi

J'ai essayé différentes choses, comme --rm et --no-cache paramètre docker run et aussi l'arrêt/retrait du récipient avant de la nouvelle construction. Je ne suis pas sûr de ce que je fais mal ici. Il semble que docker est mise à jour correctement l'image, comme l'appel d' COPY src src entraînerait une id de couche et pas de cache composez le:

Step 6 : COPY src src
 ---> 382ef210d8fd

Quelle est la méthode recommandée de mise à jour d'un conteneur?

Mon scénario typique serait: L'application est en cours d'exécution sur le serveur dans un conteneur Docker. Maintenant parties de l'application sont mises à jour, par exemple par la modification d'un fichier. Maintenant, le conteneur doit exécuter la nouvelle version. Docker semble recommander la construction d'une nouvelle image au lieu de modifier un conteneur existant, donc je pense que le chemin de la reconstruction, comme je le fais est juste, mais certains détails dans la mise en œuvre doit être améliorée.

208voto

Lion Points 2833

Après quelques recherches et essais, j'ai trouvé que j'ai eu quelques malentendus à propos de la durée de vie des conteneurs Docker. Il suffit de redémarrer un conteneur ne fait pas de menu fixe l'utilisation d'une nouvelle image, lorsque l'image a été reconstruite dans le temps. Au lieu de cela, Docker est de l'extraction de l'image seulement avant l'exécution du conteneur. Si 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 n'est pas suffisant. Je pensais que les conteneurs fonctionne comme un service: Arrêt du service, effectuez vos modifications, redémarrez-le et ils s'appliquent. C'était ma plus grosse erreur.

Parce que les conteneurs sont permanents, vous devez les enlever à l'aide de docker rm <ContainerName> première. Après un récipient est retiré, vous ne pouvez pas tout simplement commencer par docker start. Cela doit être fait à l'aide de docker run, qui lui-même utilise la dernière image pour la création d'un nouveau conteneur d'instance.

Les contenants doivent être aussi indépendants que possible

Avec cette connaissance, c'est de comprendre pourquoi le stockage des données dans des conteneurs est qualifié comme une mauvaise pratique et Docker recommande volumes de données/montage d'accueil répertoires au lieu de cela: Depuis un conteneur doit être détruit pour mettre à jour les applications, les données stockées à l'intérieur serait perdu trop. Cette entraîner un surcroît de travail pour l'arrêt des services, de sauvegarde de données et ainsi de suite.

Donc c'est une solution intelligente pour exclure les données à partir du conteneur: Nous n'avons pas à vous soucier de nos données, lorsqu'il est stocké en toute sécurité sur l'ordinateur hôte et le conteneur ne contient que l'application elle-même.

Pourquoi -rf peut pas vraiment vous aider

L' docker run de commande, a Nettoyer commutateur appelé -rf. Il fera cesser le comportement de garder les conteneurs docker en permanence. À l'aide de -rf, Docker va détruire le conteneur après qu'il a été quitté. Mais ce commutateur a deux problèmes:

  1. Menu fixe également supprimer les volumes sans nom associé avec le conteneur, qui peut tuer vos données
  2. En utilisant cette option, il n'est pas possible d'exécuter des conteneurs dans l'arrière-plan à l'aide de -d interrupteur

Alors que l' -rf switch est une bonne option pour enregistrer le travail en cours de développement pour les tests rapides, il est moins approprié dans la production. Surtout parce que la disparition de l'option pour exécuter un conteneur dans le fond, qui serait principalement requis.

Comment faire pour supprimer un conteneur

On peut contourner ces limitations en enlevant simplement le conteneur:

docker rm --force <ContainerName>

L' --force (ou -f) commutateur à utiliser SIGKILL sur l'exécution des conteneurs. Au lieu de cela, vous pouvez également arrêter le conteneur avant:

docker stop <ContainerName>
docker rm <ContainerName>

Les deux sont égaux. docker stop est également à l'aide de SIGTERM. Mais à l'aide de --force switch permettra de réduire votre script, en particulier lors de l'utilisation de serveurs CI: docker stop renvoie une erreur si le conteneur n'est pas en cours d'exécution. Ce serait la cause de Jenkins et de nombreux autres serveurs CI à envisager de le construire à tort comme ayant échoué. Pour résoudre ce problème, vous devez tout d'abord vérifier si le conteneur est en cours d'exécution comme je l'ai fait dans la question (voir containerRunning variable).

Le texte complet de la reconstruction d'un conteneur Docker

Selon cette nouvelle connaissance, 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 :)

90voto

yunus Points 165

Chaque fois que des modifications sont apportées dans dockerfile ou composition ou exigences, exécutez-le à nouveau avec docker-compose up --build . Pour que les images soient reconstruites et rafraîchies

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X