Les conteneurs Docker sont des environnements intentionnellement isolés. Chaque conteneur possède son propre système de fichiers auquel les autres conteneurs ou votre hôte ne peuvent pas accéder directement.
Parfois, les conteneurs peuvent avoir besoin de partager des données. Bien que vous deviez viser l'autosuffisance des conteneurs, il existe des scénarios où le partage de données est inévitable. Cela peut être pour qu'un deuxième conteneur puisse accéder à un cache combiné, utiliser une base de données sauvegardée sur fichier, créer une sauvegarde ou effectuer des opérations sur des données générées par l'utilisateur, comme un conteneur d'optimiseur d'image qui traite les photos de profil téléchargées via un conteneur de serveur Web distinct .
Dans ce guide, nous examinerons quelques méthodes pour transmettre des données entre vos conteneurs Docker. Nous supposerons que vous avez déjà configuré Docker et que vous connaissez les concepts fondamentaux tels que les conteneurs, les images, les volumes et les réseaux.
Utilisation de volumes pour partager un répertoire
Les volumes sont le moyen de facto de mettre en place le partage de données. Ce sont des systèmes de fichiers indépendants qui stockent leurs données en dehors de tout conteneur individuel. Le montage d'un volume sur un chemin de système de fichiers dans un conteneur fournit un accès en lecture-écriture aux données du volume.
Les volumes peuvent être attachés à plusieurs conteneurs simultanément. Cela facilite le partage transparent des données et la persistance gérée par Docker.
Créez un volume pour commencer :
docker volume create --name shared-data
Créez ensuite vos conteneurs, en montant le volume sur le chemin du système de fichiers attendu par chaque image :
docker run -d -v shared-data:/data --name example example-image:latest docker run -d -v shared-data:/backup-source --name backup backup-image:latest
Dans cet exemple, la backup
conteneur obtiendra un accès effectif à l'example
/data
du conteneur annuaire. Il sera monté en tant que /backup-source
; les modifications apportées par l'un ou l'autre des conteneurs seront reflétées dans l'autre.
Démarrage rapide des conteneurs avec des volumes correspondants
L'exemple ci-dessus pourrait être simplifié en utilisant le docker run
--volumes-from
de la commande drapeau. Cela fournit un mécanisme pour monter automatiquement des volumes qui sont déjà utilisés par un conteneur existant :
docker run -d --volumes-from example --name backup backup-image:latest
Cette fois, la backup
le conteneur recevra les shared-data
volume monté dans son /data
annuaire. Le --volumes-from
flag extrait toutes les définitions de volume attachées à l'example
récipient. Il est particulièrement idéal pour les tâches de sauvegarde et autres conteneurs de courte durée qui agissent comme composants auxiliaires de votre service principal.
Améliorer la sécurité avec les montages en lecture seule
Les volumes sont toujours montés en mode lecture-écriture par défaut. Tous vos conteneurs ayant accès à un volume sont autorisés à modifier son contenu, ce qui peut entraîner une perte de données involontaire.
Il est recommandé de monter des volumes partagés en mode lecture seule lorsqu'un conteneur n'est pas censé apporter de modifications. Dans l'exemple ci-dessus, la backup
le conteneur n'a besoin que de lire le contenu des shared-data
le volume. La définition du montage en mode lecture seule applique cette attente, empêchant les bogues ou les binaires malveillants de l'image de supprimer les données utilisées par l'example
conteneur.
docker run -d -v shared-data:/backup-source:ro --name backup backup-image:latest
Ajout de ro
comme troisième paramètre séparé par deux-points au -v
indique que le volume doit être monté en mode lecture seule. Vous pouvez également écrire readonly
au lieu de ro
comme une alternative plus explicite.
Partage de données sur un réseau
Vous pouvez utiliser les échanges réseau comme approche alternative au partage de données via des volumes de système de fichiers. Joindre deux conteneurs au même réseau Docker leur permet de communiquer de manière transparente à l'aide de noms d'hôte attribués automatiquement :
docker network create demo-network docker run -d --net demo-network --name first example-image:latest docker run -d --net demo-network --name second another-image:latest
Ici first
pourra envoyer un ping second
et vice versa. Vos conteneurs pourraient exécuter un service d'API HTTP leur permettant d'interagir avec les données des autres.
Poursuivant l'exemple de sauvegarde, maintenant votre backup
le conteneur pourrait faire une requête réseau à http://example:8080/backup-data
pour acquérir les données à sauvegarder. L'example
Le conteneur doit répondre avec une archive contenant toutes les données qui doivent être stockées. Le conteneur de sauvegarde a ensuite la responsabilité de conserver l'archive dans un emplacement de stockage approprié.
Faire en sorte que le partage de données se produise sur un réseau facilite souvent les efforts de découplage. Vous vous retrouvez avec des interfaces clairement définies qui ne créent pas de dépendances dures entre les services. L'accès aux données peut être contrôlé plus précisément en exposant des API pour chaque type de données, au lieu de donner à chaque conteneur un accès total à un volume.
Il est important de prendre en compte la sécurité si vous utilisez cette approche. Assurez-vous que les API HTTP conçues pour un accès interne par vos autres conteneurs Docker n'ont pas de ports exposés sur le réseau de pont de votre hôte Docker. Il s'agit du comportement par défaut lors de l'utilisation des options réseau présentées ci-dessus ; lier un port avec -p 8080:8080
autoriserait l'accès à l'API de sauvegarde via les interfaces réseau de votre hôte. Ce serait un problème de sécurité.
Résumé
Les conteneurs Docker sont des environnements isolés qui ne peuvent pas accéder aux systèmes de fichiers des autres. Néanmoins, vous pouvez partager des données en créant un volume qui est monté dans tous les conteneurs participants. L'utilisation d'un réseau Docker partagé est une option alternative qui offre une séparation plus forte dans les scénarios où les interactions directes avec le système de fichiers ne sont pas nécessaires.
Il est de bon ton de limiter au maximum les interactions entre conteneurs. Les cas où vous avez besoin de partager des données doivent être clairement définis pour éviter de coupler étroitement vos services. Conteneurs qui dépendent de manière rigide des données d'un autre conteneur peut être plus difficile à déployer et à maintenir au fil du temps, érodant les avantages plus larges de la conteneurisation et de l'isolement.