Comment mettre à jour Docker conteneur après que son image a changé

disons que j'ai tiré l'officiel mysql:5.6.21 image .

j'ai déployé cette image en créant plusieurs conteneurs docker.

ces conteneurs ont fonctionné pendant un certain temps jusqu'à ce que MySQL 5.6.22 soit libéré. L'image officielle de mysql:5.6 est mise à jour avec la nouvelle version, mais mes conteneurs fonctionnent toujours 5.6.21.

comment propager les changements dans L'image (i.e. mettre à jour MySQL distribution) à tous mes les conteneurs existants? Quelle est la bonne Docker façon de faire cela?

360
demandé sur zkilnbqi 2014-11-04 14:48:22

13 réponses

après avoir évalué les réponses et étudié le sujet, j'aimerais résumer.

la façon dont Docker améliore les conteneurs semble être la suivante:

les contenants D'Application ne doivent pas contenir les données de l'application . De cette façon, vous pouvez remplacer app container avec sa nouvelle version à tout moment en exécutant quelque chose comme ceci:

docker pull mysql
docker stop my-mysql-container
docker rm my-mysql-container
docker run --name=my-mysql-container --restart=always \
  -e MYSQL_ROOT_PASSWORD=mypwd -v /my/data/dir:/var/lib/mysql -d mysql

vous pouvez stocker des données soit sur l'hôte (dans l'annuaire monté en volume) ou dans le(s) conteneur (s) Spécial (s) réservé aux données . Lire la suite de it ici , ici , et ici .

mise à niveau des applications (par exemple. avec yum/apt-get upgrade) dans les conteneurs est considéré comme un anti-modèle . Les conteneurs d'Application sont censés être immuable , ce qui doit garantir un comportement reproductible. Quelque les images d'application officielles (mysql: 5.6 en particulier) ne sont même pas conçues pour se mettre à jour (apt-get upgrade ne fonctionnera pas).

je voudrais remercier tous ceux qui ont donné leurs réponses, afin que nous puissions voir toutes les approches différentes.

418
répondu Yaroslav Stavnichiy 2017-05-23 11:33:24

Je n'aime pas monter des volumes comme un lien vers un répertoire hôte, donc j'ai inventé un modèle pour améliorer les conteneurs docker avec des conteneurs entièrement gérés par docker. La création d'un nouveau conteneur docker avec --volumes-from <container> donnera au nouveau conteneur avec les images mises à jour la propriété partagée des volumes gérés docker.

docker pull mysql
docker create --volumes-from my_mysql_container [...] --name my_mysql_container_tmp mysql

en ne retirant pas immédiatement l'original my_mysql_container encore, vous avez la possibilité de revenir au conteneur de travail connu si le conteneur mis à niveau n'a pas les bonnes données, ou échoue à un test de santé mentale.

à ce point, je vais généralement exécuter n'importe quels scripts de sauvegarde que j'ai pour le conteneur pour me donner un filet de sécurité en cas de quelque chose va mal

docker stop my_mysql_container
docker start my_mysql_container_tmp

Maintenant, vous avez la possibilité de vous assurer que les données que vous attendez d'être dans le nouveau conteneur est-il et d'exécuter un test de cohérence.

docker rm my_mysql_container
docker rename my_mysql_container_tmp my_mysql_container

les volumes docker resteront autour aussi longtemps que n'importe quel conteneur est de les utiliser, de sorte que vous pouvez supprimer le conteneur d'origine en toute sécurité. Une fois que le conteneur d'origine est enlevé, le nouveau conteneur peut assumer le nom de l'original pour faire tout aussi joli que ce qu'il était pour commencer.

il y a deux avantages majeurs à utiliser ce modèle pour améliorer les conteneurs docker. Tout d'abord, il élimine la nécessité de monter des volumes vers des répertoires hôtes en permettant aux volumes d'être directement transférés vers des conteneurs mis à niveau. Deuxièmement, vous êtes jamais dans une position où il n'y a pas de conteneur Docker fonctionnel; donc si la mise à niveau échoue, vous pouvez facilement revenir à la façon dont il fonctionnait avant en faisant tourner le conteneur docker original à nouveau.

59
répondu kMaiSmith 2015-11-05 03:56:18

je voudrais ajouter que si vous voulez faire ce processus automatiquement (télécharger, arrêter et redémarrer un nouveau conteneur avec les mêmes paramètres que ceux décrits par @Yaroslav), vous pouvez utiliser WatchTower. Un programme qui met automatiquement à jour vos conteneurs lorsqu'ils sont changés https://github.com/v2tec/watchtower

18
répondu Ricardo Polo 2017-07-06 10:21:35

compte de cette réponse:

  • le nom de la base de données est app_schema
  • le nom du conteneur est app_db
  • le mot de passe racine est root123

comment mettre à jour MySQL lors du stockage des données de l'application à l'intérieur du conteneur

il s'agit d'une mauvaise pratique , parce que si vous perdez le conteneur, vous perdre les données. Bien qu'il s'agisse d'une mauvaise pratique, voici une façon possible de le faire:

1) Faire un dump de base de données comme SQL:

docker exec app_db sh -c 'exec mysqldump app_schema -uroot -proot123' > database_dump.sql

2) Mettre à jour l'image:

docker pull mysql:5.6

3) Mettre à jour le conteneur:

docker rm -f app_db
docker run --name app_db --restart unless-stopped \
-e MYSQL_ROOT_PASSWORD=root123 \
-d mysql:5.6

4) restaurer le dump de base de données:

docker exec app_db sh -c 'exec mysql -uroot -proot123' < database_dump.sql

comment mettre à jour un conteneur MySQL en utilisant un volume externe

utilisant un volume externe est une meilleure façon de gérer les données, et il est plus facile de mettre à jour MySQL. Perdre le conteneur ne perdra pas de données. Vous pouvez utiliser docker-composer pour faciliter la gestion des applications Docker multi-conteneurs dans un seul hôte:

1) Créer le fichier docker-compose.yml pour gérer vos applications:

version: '2'
services:
  app_db:
    image: mysql:5.6
    restart: unless-stopped
    volumes_from: app_db_data
  app_db_data:
    volumes: /my/data/dir:/var/lib/mysql

2) Mettre à jour MySQL (à partir du même dossier que le fichier docker-compose.yml ):

docker-compose pull
docker-compose up -d

Note: la dernière commande ci-dessus mettra à jour L'image MySQL, recréera et lancera le conteneur avec la nouvelle image.

15
répondu Alexandre Verri 2017-01-15 04:35:30

réponse similaire à ci-dessus

docker images | awk '{print }' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull
11
répondu Eddie Jaoude 2016-10-08 03:46:54

juste pour fournir une réponse plus générale (pas spécifique à mysql)...

  1. en bref

synchroniser avec le Service image registry ( https://docs.docker.com/compose/compose-file/#image ):

docker-compose pull 

Recréer conteneur si docker-composition de fichier ou de l'image ont changé:

docker-compose up -d
  1. arrière-plan

la gestion D'image de conteneur est l'une des raisons pour utiliser docker-composer (voir https://docs.docker.com/compose/reference/up / )

S'il existe des conteneurs existants pour un service, et que la configuration ou l'image du service a été modifiée après la création du conteneur, docker-compose up reprend les changements en arrêtant et en recréant les conteneurs (en préservant les volumes montés). Pour empêcher Composez de ramasser des changements, utilisez le drapeau -- no-recreate.

aspect de la gestion des données étant également couvert par docker-composer à travers des "volumes" externes montés (voir https://docs.docker.com/compose/compose-file/#volumes ) ou contenant de données.

cela laisse les problèmes potentiels de rétrocompatibilité et de migration des données intacts, mais ce sont des problèmes" applicatifs", non spécifiques au Docker, qui doivent être vérifiés par rapport aux notes de version et aux tests...

10
répondu Ronan Fauglas 2017-04-20 09:45:33

voici à quoi ressemble l'utilisation de docker-compose lors de la construction d'une coutume Dockerfile .

  1. construisez d'abord votre fichier Dockerfile personnalisé, en ajoutant un numéro de version à différencier. Ex: docker build -t imagename:version . cela stockera votre nouvelle version localement.
  2. Exécuter docker-compose down
  3. modifiez votre fichier docker-compose.yml pour refléter le nouveau nom d'image que vous avez défini à l'étape 1.
  4. Exécuter docker-compose up -d . Il cherchez localement l'image et utilisez la version améliorée.

- EDIT -

mes pas ci-dessus sont plus verbeux qu'ils n'ont besoin d'être. J'ai optimisé mon workflow en incluant le paramètre build: . dans mon fichier docker-composer. Les étapes ressemble à ceci maintenant:

  1. vérifiez que mon fichier Dockerfile est ce que je veux qu'il ressemble.
  2. définir le numéro de version de mon nom d'image dans mon docker-composer fichier.
  3. si mon image n'est pas encore construite: Lancez docker-compose build
  4. Exécuter docker-compose up -d

Je n'avais pas réalisé à l'époque, mais docker-compose est assez intelligent pour simplement mettre à jour mon conteneur à la nouvelle image avec la commande one, au lieu d'avoir à l'abattre en premier.

7
répondu gdbj 2018-03-02 18:26:09

à partir de http://blog.stefanxo.com/2014/08/update-all-docker-images-at-once /

vous pouvez mettre à jour toutes vos images existantes en utilisant le pipeline de commande suivant:

docker images | awk '/^REPOSITORY|\<none\>/ {next} {print }' | xargs -n 1 docker pull
4
répondu gvlx 2015-08-31 11:45:21

vous devez soit reconstruire toutes les images et redémarrer tous les conteneurs, ou d'une façon ou d'une autre yum mettre à jour le logiciel et redémarrer la base de données. Il n'y a pas de chemin de mise à niveau mais que vous concevez vous-même.

3
répondu seanmcl 2014-11-04 12:58:43

si vous ne voulez pas utiliser Docker composer, je peux vous recommander portainer . Il a une fonction recréer qui vous permet de recréer une image tout en tirant la dernière image.

2
répondu beruic 2018-01-04 20:23:17

j'ai eu le même problème alors j'ai créé docker-run 151990920" , un outil en ligne de commande très simple qui fonctionne à l'intérieur d'un Docker container pour mettre à jour les paquets dans d'autres conteneurs en cours d'exécution.

Il utilise des docker-py pour communiquer avec l'exécution de conteneurs docker et les packages de mise à jour ou d'exécuter n'importe quelle commande unique

exemples:

docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run exec

par défaut, cela lancera la commande date dans tous les conteneurs en cours d'exécution et retournera les résultats, mais vous pouvez émettre n'importe quelle commande par exemple docker-run exec "uname -a"

pour mettre à jour les paquets (Utilisant actuellement apt-get):

docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run update

vous pouvez créer et alias et l'utiliser comme une ligne de commande régulière par exemple

alias docker-run='docker run --rm -v /var/run/docker.sock:/tmp/docker.sock itech/docker-run'

1
répondu iTech 2014-11-05 16:11:53

assurez-vous que vous utilisez des volumes pour toutes les données persistantes (configuration, journaux, ou données d'application) que vous stockez sur les conteneurs liés à l'état des processus à l'intérieur de ce conteneur. Mettez à jour votre fichier Dockerfile et reconstruisez l'image avec les changements que vous vouliez, et redémarrez les conteneurs avec vos volumes montés à leur endroit approprié.

1
répondu Daniel Dinnyes 2016-05-25 14:48:49

C'est quelque chose avec lequel j'ai aussi lutté pour mes propres images. J'ai un environnement serveur à partir duquel je crée une image Docker. Lorsque je mets à jour le serveur, j'aimerais que tous les utilisateurs qui utilisent des conteneurs basés sur mon image de Docker puissent passer au serveur le plus récent.

idéalement, je préférerais générer une nouvelle version de L'image du Docker et avoir tous les conteneurs basés sur une version précédente de cette image mise à jour automagiquement à la nouvelle image "en place." Mais ce mécanisme ne semble pas exister.

donc la meilleure conception que j'ai pu trouver jusqu'à présent est de fournir un moyen d'avoir le conteneur mise à jour lui-même--similaire à la façon dont une application bureautique vérifie les mises à jour et les mises à niveau elle-même. Dans mon cas, cela signifiera probablement l'élaboration d'un script qui implique git tire d'une étiquette bien connue.

l'image/le conteneur ne change pas réellement, mais les" internes " de ce conteneur changent. Vous pourrait imaginer faire la même chose avec apt-get, miam, ou tout ce qui est approprié pour votre environnement. Avec cela, je mettrais à jour le myserver:dernière image dans le Registre afin que tous les nouveaux conteneurs seraient basés sur la dernière image.

j'aimerais savoir s'il existe un État de la technique qui traite de ce scénario.

1
répondu bjlevine 2017-03-03 13:48:31