La gestion des données entre un système hôte et des conteneurs isolés est une problématique récurrente pour tout développeur travaillant avec Docker. Qu'il s'gaisse de mettre à jour une configuration à la volée ou d'extraire des journaux d'erreurs, plusieurs approches permettent de fluidifier ces échanges sans avoir à reconstruire systématiquement vos images.
1. L'utilitaire docker cp : l'outil polyvalent pour les transferts ponctuels
La commande docker cp est sans doute la méthode la plus accessible pour effectuer des copies rapides. Elle fonctionne de manière bidirectionnelle, permettant de déplacer des fichiers ou des répertoires entiers entre l'hôte et un conteneur, que ce dernier soit en cours d'exécution ou à l'arrêt.
Syntaxe fondamentale et cas d'usage
Le fonctionnement de cette commande est calqué sur la commande standard cp d'Unix. Voici comment structurer vos commandes :
- De l'hôte vers le conteneur :
docker cp [chemin_source_hote] [nom_conteneur]:[chemin_destination_conteneur] - Du conteneur vers l'hôte :
docker cp [nom_conteneur]:[chemin_source_conteneur] [chemin_destination_hote]
Prenons un exemple concret : vous devez injecter un fichier de configuration nommé app-settings.json dans un conteneur nommé web-server-node localisé dans le dossier /usr/src/app/config/.
docker cp ./app-settings.json web-server-node:/usr/src/app/config/
À l'inverse, pour récupérer un fichier de log généré par votre application pour une analyse locale :
docker cp web-server-node:/var/log/app/error.log ./debug_logs/
Points de vigilance techniques
Bien que simple, docker cp comporte quelques subtilités :
- Gestion des chemins : Si votre chemin contient des espaces, utilisez des guillemets (ex:
"mon dossier/config.conf"). - Comportement des dossiers : Copier un dossier vers une destination existante placera le dossier à l'intérieur de celle-ci. Soyez précis sur l'usage du slash final pour éviter des arborescences imbriquées indésirables.
- Persistance : Cette méthode est manuelle. Si le conteneur est supprimé, les fichiers copiés à l'intérieur seront perdus s'ils ne se trouvent pas sur un volume.
2. Automatisation des transferts via scripts Shell
Pour les déploiements fréquents ou les mises à jour de ressources statiques, l'exécution manuelle devient vite fastidieuse. L'intégration de docker cp dans un script Bash permet de fiabiliser le processus.
Voici un exemple de script robuste pour synchroniser des assets de build vers un conteneur Nginx :
#!/bin/bash
# Configuration des variables
TARGET_CONTAINER="nginx-prod-instance"
LOCAL_BUILD_PATH="./dist/"
REMOTE_HTML_PATH="/usr/share/nginx/html/"
echo "Début de la synchronisation vers $TARGET_CONTAINER..."
# Vérification de l'existence du conteneur
if [ "$(docker ps -aq -f name=$TARGET_CONTAINER)" ]; then
# Nettoyage optionnel du dossier distant avant copie
docker exec $TARGET_CONTAINER rm -rf ${REMOTE_HTML_PATH}*
# Transfert des nouveaux fichiers
docker cp $LOCAL_BUILD_PATH. $TARGET_CONTAINER:$REMOTE_HTML_PATH
if [ $? -eq 0 ]; then
echo "Transfert réussi."
else
echo "Erreur lors de la copie."
fi
else
echo "Erreur : Le conteneur $TARGET_CONTAINER n'existe pas."
exit 1
fi
3. Utilisation des Bind Mounts pour une synchronisation en temps réel
Pour le développement actif, docker cp n'est pas la solution idéale car elle nécessite une action manuelle à chaque modification. Les Bind Mounts permettent de lier directement un dossier de votre machine hôte à un dossier interne au conteneur.
Toute modification effectuée sur l'hôte est instantanément reflétée dans le conteneur. Cela se définit généralement au démarrage du conteneur :
docker run -d \
--name dev-container \
-v $(pwd)/src:/app/src \
my-custom-image:latest
4. Les volumes Docker pour le partage entre conteneurs
Lorsque le besoin est de transférer ou de partager des données entre plusieurs conteneurs (par exemple, un générateur de rapports et un serveur web), les Volumes Docker sont la solution recommandée. Contrairement aux Bind Mounts, ils sont gérés par Docker et isolés du système de fichiers direct de l'hôte.
Création et utilisation d'un volume partagé :
# Création du volume
docker volume create data_shared
# Montage sur le premier conteneur (producteur)
docker run -d -v data_shared:/data --name producer-app worker-image
# Montage sur le second conteneur (consommateur)
docker run -d -v data_shared:/data:ro --name consumer-app web-display-image
Cette approche garantit que les données survivent même si les conteneurs sont supprimés ou mis à jour.