Comment partager des données entre des conteneurs Docker

introduction

Docker est un outil de conteneurisation très utilisé pour fournir aux applications logicielles un système de fichiers contenant tout ce dont elles ont besoin pour s'exécuter. L'utilisation des conteneurs Docker garantit que le logiciel se comportera de la même manière, quel que soit l'endroit où il est déployé, car son environnement d'exécution est cohérent.

En général, les conteneurs Docker sont éphémères et s’exécutent aussi longtemps que nécessaire pour que la commande émise dans le conteneur s’achève. Parfois, cependant, les applications doivent partager l'accès aux données ou conserver des données après la suppression d'un conteneur. Les bases de données, le contenu généré par l'utilisateur pour un site Web et les fichiers journaux ne sont que quelques exemples de données qu'il est impossible ou impossible d'inclure dans une image Docker, mais auxquelles les applications doivent accéder. L'accès permanent aux données est fourni avecDocker Volumes.

Les volumes Docker peuvent être créés et attachés dans la même commande que celle qui crée un conteneur, ou ils peuvent être créés indépendamment de tout conteneur et attachés ultérieurement. Dans cet article, nous allons examiner quatre manières différentes de partager des données entre des conteneurs.

Conditions préalables

Pour suivre cet article, vous aurez besoin d’un serveur Ubuntu 18.04 avec les éléments suivants:

[.note] #Note: Même si les prérequis donnent des instructions pour installer Docker sur Ubuntu 18.04, les commandesdocker pour les volumes de données Docker dans cet article devraient fonctionner sur d'autres systèmes d'exploitation tant que Docker est installé et l'utilisateur sudo a été ajouté au groupedocker.
#

[[step-1 -—- Creating-an-Independent-Volume]] == Étape 1 - Création d'un volume indépendant

Introduite dans la version 1.9 de Docker, la commandedocker volume create vous permet de créer un volume sans le relier à un conteneur particulier. Nous utiliserons cette commande pour ajouter un volume nomméDataVolume1:

docker volume create --name DataVolume1

Le nom est affiché, indiquant que la commande a réussi:

OutputDataVolume1

Pour utiliser le volume, nous allons créer un nouveau conteneur à partir de l'image Ubuntu, en utilisant l'indicateur--rm pour le supprimer automatiquement lorsque nous quitterons. Nous utiliserons également-v pour monter le nouveau volume. -v nécessite le nom du volume, un signe deux-points, puis le chemin absolu vers l'endroit où le volume doit apparaître à l'intérieur du conteneur. Si les répertoires du chemin ne font pas partie de l’image, ils seront créés lors de l’exécution de la commande. S'ils existentdo, le volume monté masquera le contenu existant:

docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu

Dans le conteneur, écrivons des données sur le volume:

echo "Example1" > /datavolume1/Example1.txt

Parce que nous avons utilisé l'indicateur--rm, notre conteneur sera automatiquement supprimé lorsque nous quitterons. Notre volume, cependant, sera toujours accessible.

exit

Nous pouvons vérifier que le volume est présent sur notre système avecdocker volume inspect:

docker volume inspect DataVolume1
Output[
    {
        "CreatedAt": "2018-07-11T16:57:54Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data",
        "Name": "DataVolume1",
        "Options": {},
        "Scope": "local"
    }
]

[.note] #Note: Nous pouvons même regarder les données sur l'hôte au chemin indiqué commeMountpoint. Nous devons éviter de le modifier, car cela peut entraîner une corruption des données si les applications ou les conteneurs ne sont pas conscients des modifications.
#

Ensuite, commençons un nouveau conteneur et attachonsDataVolume1:

docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu

Vérifier le contenu:

cat /datavolume1/Example1.txt
OutputExample1

Quittez le conteneur:

exit

Dans cet exemple, nous avons créé un volume, l'avons attaché à un conteneur et vérifié sa persistance.

[[step-2 -—- creation-a-volume-that-persists-when-the-container-is-removed]] == Étape 2 - Création d'un volume qui persiste lorsque le conteneur est supprimé

Dans notre exemple suivant, nous allons créer un volume en même temps que le conteneur, supprimer le conteneur, puis l'attacher au nouveau conteneur.

Nous utiliserons la commandedocker run pour créer un nouveau conteneur à l'aide de l'image Ubuntu de base. -t nous donnera un terminal, et-i nous permettra d'interagir avec lui. Pour plus de clarté, nous utiliserons--name pour identifier le conteneur.

L'indicateur-v nous permettra de créer un nouveau volume, que nous appelleronsDataVolume2. Nous utiliserons deux points pour séparer ce nom du chemin où le volume doit être monté dans le conteneur. Enfin, nous allons spécifier l'image Ubuntu de base et nous nous baserons sur la commande par défaut dans lesUbuntu base image’s Docker file,bash, pour nous déposer dans un shell:

docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu

[.Remarque]##

Note: L'indicateur-v est très flexible. Il peut lier ou nommer un volume avec juste un léger ajustement de syntaxe. Si le premier argument commence par un/ ou~/, vous créez un bindmount. Supprimez cela et vous nommez le volume. Par exemple:

  • -v /path:/path/in/container monte le répertoire hôte,/path au/path/in/container

  • -v path:/path/in/container crée un volume nommépath sans relation avec l'hôte.

Pour plus d'informations sur le montage d'un répertoire à partir de l'hôte, consultezHow To Share Data between a Docker Container and the Host

Dans le conteneur, nous écrirons des données sur le volume:

echo "Example2" > /datavolume2/Example2.txt
cat /datavolume2/Example2.txt
OutputExample2

Quittons le conteneur:

exit

Lorsque nous redémarrons le conteneur, le volume sera monté automatiquement:

docker start -ai Container2

Vérifions que le volume est bien monté et que nos données sont toujours en place:

cat /datavolume2/Example2.txt
OutputExample2

Enfin, sortons et nettoyons:

exit

Docker ne nous laissera pas supprimer un volume s’il est référencé par un conteneur. Voyons ce qui se passe lorsque nous essayons:

docker volume rm DataVolume2

Le message nous indique que le volume est toujours en cours d'utilisation et fournit la version longue de l'ID de conteneur:

OutputError response from daemon: unable to remove volume: remove DataVolume2: volume is in use - [d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63]

Nous pouvons utiliser cet ID pour supprimer le conteneur:

docker rm d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63
Outputd0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

Le retrait du conteneur n’affectera pas le volume. Nous pouvons voir qu'il est toujours présent sur le système en listant les volumes avecdocker volume ls:

docker volume ls
OutputDRIVER              VOLUME NAME
local               DataVolume2

Et nous pouvons utiliserdocker volume rm pour le supprimer:

docker volume rm DataVolume2

Dans cet exemple, nous avons créé un volume de données vide en même temps que nous avons créé un conteneur. Dans notre exemple suivant, nous allons explorer ce qui se passe lorsque nous créons un volume avec un répertoire de conteneur contenant déjà des données.

[[step-3 -—- creation-a-volume-from-an-existing-directory-with-data]] == Étape 3 - Création d'un volume à partir d'un répertoire existant avec des données

En général, créer un volume indépendamment avecdocker volume create et en créer un lors de la création d'un conteneur sont équivalents, à une exception près. Si nous créons un volume en même temps que nous créons un conteneurand, nous fournissons le chemin vers un répertoire contenant des données dans l'image de base, ces données seront copiées dans le volume.

À titre d'exemple, nous allons créer un conteneur et ajouter le volume de données à/var, un répertoire qui contient des données dans l'image de base:

docker run -ti --rm -v DataVolume3:/var ubuntu

Tout le contenu du répertoire/var de l'image de base est copié dans le volume et nous pouvons monter ce volume dans un nouveau conteneur.

Quittez le conteneur actuel:

exit

Cette fois, plutôt que de nous fier à la commandebash par défaut de l’image de base, nous émettrons notre propre commandels, qui affichera le contenu du volume sans entrer dans le shell:

docker run --rm -v DataVolume3:/datavolume3 ubuntu ls datavolume3

Le répertoiredatavolume3 a maintenant une copie du contenu du répertoire/var de l’image de base:

Outputbackups
cache
lib
local
lock
log
mail
opt
run
spool
tmp

Il est peu probable que nous souhaitons monter/var/ de cette manière, mais cela peut être utile si nous avons créé notre propre image et que nous voulons un moyen simple de préserver les données. Dans notre exemple suivant, nous montrerons comment un volume peut être partagé entre plusieurs conteneurs.

[[step-4 -—- sharing-data-between-multiple-docker-containers]] == Étape 4 - Partage de données entre plusieurs conteneurs Docker

Jusqu'à présent, nous avons attaché un volume à un conteneur à la fois. Souvent, nous souhaitons que plusieurs conteneurs soient attachés au même volume de données. C’est relativement simple à réaliser, mais il ya une mise en garde cruciale: pour le moment, Docker ne gère pas le verrouillage de fichier. Si vous avez besoin que plusieurs conteneurs écrivent sur le volume, les applications exécutées dans ces conteneursmust doivent être conçues pour écrire dans des magasins de données partagés afin d'éviter la corruption des données.

Créer Container4 et DataVolume4

Utilisezdocker run pour créer un nouveau conteneur nomméContainer4 avec un volume de données attaché:

docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu

Ensuite, nous allons créer un fichier et ajouter du texte:

echo "This file is shared between containers" > /datavolume4/Example4.txt

Ensuite, nous allons sortir du conteneur:

exit

Cela nous ramène à l'invite de commande de l'hôte, où nous allons créer un nouveau conteneur qui monte le volume de données à partir deContainer4.

Créer Container5 et monter des volumes à partir de Container4

Nous allons créerContainer5 et monter les volumes à partir deContainer4:

docker run -ti --name=Container5 --volumes-from Container4 ubuntu

Vérifions la persistance des données:

cat /datavolume4/Example4.txt
OutputThis file is shared between containers

Ajoutons maintenant du texte deContainer5:

echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt

Enfin, nous allons sortir du conteneur:

exit

Ensuite, nous vérifierons que nos données sont toujours présentes dansContainer4.

Afficher les modifications apportées dans le conteneur5

Vérifions les modifications qui ont été écrites sur le volume de données parContainer5 en redémarrantContainer4:

docker start -ai Container4

Vérifiez les modifications:

cat /datavolume4/Example4.txt
OutputThis file is shared between containers
Both containers can write to DataVolume4

Maintenant que nous avons vérifié que les deux conteneurs sont capables de lire et d’écrire à partir du volume de données, nous allons quitter le conteneur:

exit

Encore une fois, Docker ne gère aucun verrouillage de fichier, donc les applicationsmust tiennent compte du verrouillage de fichier elles-mêmes. Il est possible de monter un volume Docker en lecture seule pour garantir que la corruption des données ne se produira pas par accident lorsqu'un conteneur nécessite un accès en lecture seule en ajoutant:ro. Voyons comment cela fonctionne.

Démarrer le conteneur 6 et monter le volume en lecture seule

Une fois qu'un volume a été monté dans un conteneur, plutôt que de le démonter comme avec un système de fichiers Linux classique, vous pouvez créer un nouveau conteneur monté comme vous le souhaitez et, si nécessaire, supprimer le conteneur précédent. Pour rendre le volume en lecture seule, nous ajoutons:ro à la fin du nom du conteneur:

docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu

Nous allons vérifier le statut en lecture seule en essayant de supprimer notre exemple de fichier:

rm /datavolume4/Example4.txt
Outputrm: cannot remove '/datavolume4/Example4.txt': Read-only file system

Enfin, nous allons sortir du conteneur et nettoyer nos conteneurs et volumes de test:

exit

Maintenant que nous avons terminé, nettoyons nos conteneurs et notre volume:

docker rm Container4 Container5 Container6
docker volume rm DataVolume4

Dans cet exemple, nous avons montré comment partager des données entre deux conteneurs à l'aide d'un volume de données et comment monter un volume de données en lecture seule.

Conclusion

Dans ce didacticiel, nous avons créé un volume de données qui permettait aux données de persister pendant la suppression d'un conteneur. Nous avons partagé des volumes de données entre des conteneurs, en précisant que les applications devront être conçues pour gérer le verrouillage de fichiers afin d'empêcher la corruption des données. Enfin, nous avons montré comment monter un volume partagé en mode lecture seule. Si vous souhaitez en savoir plus sur le partage de données entre les conteneurs et le système hôte, consultezHow To Share Data between the Docker Container and the Host.