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:
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 echo
es la valeur dans le fichier de conteneur de données et quitte.
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
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.
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:
Mais commettre et pousser ne fait pas ce que j'attends:
docker commit datatest_data myrepository:5000/datatest-data:latest
À 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?
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.
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.
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
).
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.
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.
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.
Docker 1.9.0 a introduit une nouvelle commande docker volume
qui permet de créer des volumes:
docker volume create --name hello
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
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.
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/
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 ...