web-dev-qa-db-fra.com

Comment déployer un conteneur Docker et un conteneur de données associé, y compris le contenu?

Je commencerai par admettre que je suis assez nouveau pour Docker et que je peux aborder ce problème à partir d'un mauvais ensemble d'hypothèses ... faites-moi savoir si c'est le cas. J'ai vu beaucoup de discussions sur la façon dont Docker est utile pour le déploiement, mais aucun exemple de la façon dont cela est réellement fait.

Voici comment je pensais cela fonctionnerait:

  1. créer le conteneur de données pour contenir des données persistantes sur la machine A
  2. créer le conteneur d'application qui utilise les volumes du conteneur de données
  3. faire du travail, potentiellement changer les données dans le conteneur de données
  4. arrêter le conteneur d'application
  5. valider et baliser le conteneur de données
  6. Poussez le conteneur de données vers un référentiel (privé)
  7. tirer et exécuter l'image de l'étape 6 sur la machine B
  8. reprendre là où vous vous étiez arrêté sur la machine B

L'étape clé ici est l'étape 5, qui, à mon avis, sauverait l'état actuel (y compris le contenu du système de fichiers). Vous pouvez ensuite pousser cet état vers un référentiel et le retirer ailleurs, vous donnant un nouveau conteneur qui est essentiellement identique à l'original.

Mais cela ne semble pas fonctionner de cette façon. Ce que je trouve, c'est que l'étape 5 ne fait pas ce que je pense ou l'étape 7 (tirer et exécuter l'image) "réinitialise" le conteneur à son état initial.

J'ai mis en place un ensemble de trois images et conteneurs Docker pour tester cela: un conteneur de données, un écrivain qui écrit une chaîne aléatoire dans un fichier dans le conteneur de données toutes les 30 s, et un lecteur qui simplement echoes la valeur dans le fichier de conteneur de données et quitte.

Conteneur de données

Créé avec

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder

Écrivain

Créé avec

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done

Ce script écrit une chaîne aléatoire et la date/heure dans /datafolder/data.txt dans le conteneur de données.

Lecteur

Créé avec

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

Lorsque je crée et exécute ces conteneurs, ils fonctionnent correctement et fonctionnent comme je m'y attendais:

Stop & Start sur la machine de développement:

  1. créer le conteneur de données
  2. exécuter l'écrivain
  3. lancez le lecteur immédiatement, voir le "pas de données ici!" message
  4. attends un moment
  5. exécuter le lecteur, voir la chaîne aléatoire
  6. arrêter l'écrivain
  7. redémarrer l'écrivain
  8. exécuter le lecteur, voir la même chaîne aléatoire

Mais commettre et pousser ne fait pas ce que j'attends:

  1. créer le conteneur de données
  2. exécuter l'écrivain
  3. lancez le lecteur immédiatement, voir le "pas de données ici!" message
  4. attends un moment
  5. exécuter le lecteur, voir la chaîne aléatoire
  6. arrêter l'écrivain
  7. valider et baliser le conteneur de données avec docker commit datatest_data myrepository:5000/datatest-data:latest
  8. Poussez vers le référentiel
  9. supprimer tous les conteneurs et les recréer

À ce stade, je m'attends à exécuter le lecteur et à voir la même chaîne aléatoire, car le conteneur de données a été validé, poussé vers le référentiel, puis recréé à partir de la même image dans le référentiel. Cependant, ce que je vois en fait, c'est "pas de données ici!" message.

Quelqu'un peut-il expliquer où je me trompe ici? Ou, sinon, montrez-moi un exemple de la façon dont le déploiement se fait avec Docker?

18
Kryten

Vous vous trompez sur le fonctionnement des volumes dans Docker. Je vais essayer d'expliquer comment les volumes sont liés aux conteneurs Docker et aux images Docker et j'espère que les différences entre les volumes de données et les données les conteneurs de volume deviendront clairs.

Rappelons d'abord quelques définitions

Images Docker

Les images Docker sont essentiellement un système de fichiers union + métadonnées. Vous pouvez inspecter le contenu du système de fichiers union image docker avec le docker export , et vous pouvez inspecter les métadonnées d'une image docker avec la docker inspect commande.

Volumes de données

dans le Docker user guide :

Un volume de données est un répertoire spécialement désigné dans un ou plusieurs conteneurs qui contourne le système de fichiers Union pour fournir plusieurs fonctionnalités utiles pour les données persistantes ou partagées.

Il est important de noter ici qu'un volume donné (comme le répertoire ou le fichier qui contient des données) n'est réutilisable que s'il existe au moins un conteneur Docker l'utilisant. Les images Docker n'ont pas de volumes, elles n'ont que des métadonnées qui indiquent finalement où les volumes seraient montés sur le système de fichiers union. Les volumes de données ne font pas non plus partie du système de fichiers union des conteneurs Docker, alors où sont-ils? en dessous de /var/lib/docker/volumes sur l'hôte docker (alors que les conteneurs sont stockés sous /var/lib/docker/containers).

Conteneurs de volume de données

Ce type spécial de conteneur n'a rien de spécial. Ce sont simplement des conteneurs arrêtés utilisant un volume de données dans le seul et unique but d'avoir au moins un conteneur utilisant ce volume de données. N'oubliez pas que dès que le dernier conteneur (en cours d'exécution ou arrêté) utilisant un volume de données donné est supprimé, ce volume deviendra inaccessible via le runer docker --volumes-from option.

Utilisation de conteneurs de volumes de données

Comment créer un conteneur de volume de données

L'image utilisée pour créer un conteneur de volume de données n'a pas d'importance car un tel conteneur peut rester arrêté et remplir sa fonction. Donc, pour créer un conteneur de données nommé datatest_data pour un volume en /datafolder il suffit d'exécuter:

docker run --name datatest_data --volume /datafolder busybox true

Ici base est le nom de l'image (une petite taille pratique) et true est une commande que nous fournissons juste pour éviter de voir le démon docker se plaindre d'une commande manquante. Quoi qu'il en soit, après avoir un conteneur arrêté nommé datatest_data dans le seul but de vous permettre d'atteindre ce volume avec le --volumes-from option du docker run commande.

Comment lire à partir d'un conteneur de volume de données

Je connais deux façons de lire un volume de données: la première est à travers un conteneur. Si vous ne pouvez pas avoir un Shell dans un conteneur existant pour accéder à ce volume de données, vous pouvez exécuter un nouveau conteneur avec le --volumes-from option dans le seul but de lire ces données.

Par exemple:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

L'autre méthode consiste à copier le volume à partir du /var/lib/docker/volumes dossier. Vous pouvez découvrir le nom du volume dans ce dossier en inspectant les métadonnées de l'un des conteneurs utilisant le volume. Voir cette réponse pour plus de détails.

Travailler avec des volumes (depuis Docker 1.9.0)

Comment créer un volume (depuis Docker 1.9.0)

Docker 1.9.0 a introduit une nouvelle commande docker volume qui permet de créer des volumes:

docker volume create --name hello

Comment lire à partir d'un volume (depuis Docker 1.9.0)

Supposons que vous ayez créé un volume nommé hello avec docker volume create --name hello, vous pouvez le monter dans un conteneur avec le -v option:

docker run -v hello:/data busybox ls /data

À propos de la validation et de la poussée des conteneurs

Il doit maintenant être clair que, puisque les volumes de données ne font pas partie d'un conteneur (le système de fichiers union), la validation d'un conteneur pour produire une nouvelle image docker ne conservera aucune donnée qui serait dans un volume de données.

Faire des sauvegardes de volumes de données

Le guide de l'utilisateur du docker contient un bel article sur faire des sauvegardes de volumes de données .


Bon article concernant les volumes: http://container42.com/2014/11/03/docker-indepth-volumes/

22
Thomasleveil

Vous pouvez également utiliser un conteneur de données Docker pour déployer le code

Je ne sais pas si c'est une bonne pratique, mais je le fais comme ça:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

Vous pouvez maintenant pousser votre image et utiliser des volumes de, etc ...

1
jmny