Lorsque vous utilisez Docker, il arrive souvent que vous deviez sauvegarder des données stockées dans un volume ou les dupliquer vers un autre volume pour des tests.

Vous pourriez penser à la commande docker cp, mais cette commande ne prend en charge que la copie entre le système de fichiers du conteneur et l'hôte, sans accès direct aux volumes gérés par Docker.

Dans cet article, nous allons vous montrer comment copier des volumes Docker de la bonne manière. Nous ne nous contenterons pas de lister des commandes, mais nous nous concentrerons sur la raison pour laquelle nous devons utiliser cette méthode. En comprenant ce principe, vous pourrez l'appliquer naturellement sans avoir à mémoriser les commandes.

Le principe clé est simple.

La méthode la plus sûre et 'Dockeresque' pour manipuler des volumes Docker est d'utiliser un 'conteneur temporaire' qui a accès à ce volume comme pont (bridge).


1. Copier un volume existant vers un nouveau volume (Volume-to-Volume)



C'est le scénario le plus courant. Vous pourriez vouloir cloner le volume db_data en un volume de test db_data_test.

🤔 POURQUOI : pourquoi utiliser un conteneur temporaire ?

Les volumes Docker sont stockés quelque part sur le système de fichiers de l'hôte (comme /var/lib/docker/volumes/...), mais le démon Docker gère ce chemin. Accéder directement à ce chemin pour utiliser la commande cp n'est pas recommandé, car cela peut entraîner des problèmes de permissions ou d'intégrité des données.

Au lieu de cela, nous exécutons un conteneur temporaire avec deux volumes montés simultanément.

  1. Le conteneur monte le volume source (source_volume) au chemin /from.

  2. Le conteneur monte le volume cible (new_volume) au chemin /to.

  3. Une fois le conteneur lancé, il exécute une commande Linux simple (cp ou tar) pour copier toutes les données de /from vers /to.

  4. Une fois la commande terminée, le conteneur est automatiquement détruit (--rm option).

Ce conteneur n'est qu'un 'outil' utilisé uniquement pour copier des données.

🚀 COMMENT : exemple de commande

Voici un exemple de copie des données du volume source_data vers le volume target_data.

  1. Création d'un volume de test (facultatif)
docker volume create source_data
docker volume create target_data
# (en supposant que des données existent dans source_data.)
  1. Copie à l'aide d'un conteneur temporaire
docker run --rm \
       -v source_data:/from \
       -v target_data:/to \
       alpine \
       sh -c "cp -a /from/. /to/"

💡 Explication de la commande

  • docker run --rm: L'option --rm signifie que le conteneur sera supprimé immédiatement une fois le travail terminé. C'est essentiel pour les travaux temporaires.

  • -v source_data:/from: Montre le volume source_data dans le répertoire /from du conteneur.

  • -v target_data:/to: Montre le volume target_data dans le répertoire /to du conteneur.

  • alpine: Utilisa l'image Linux alpine, qui est très légère tout en incluant des utilitaires de base comme cp et sh.

  • sh -c "...": C'est la commande qui sera exécutée lorsque le conteneur Alpine sera lancé.

  • cp -a /from/. /to/:

    • -a (archive): Cette option est essentielle. Elle conserve tous les attributs au lieu d'une simple copie (cp -r), y compris la propriété, les permissions et les horodatages. Cela est extrêmement important lors de la manipulation de fichiers sensibles comme des fichiers de base de données.

    • /from/.: Cela signifie toutes le contenu interne de /from, y compris les fichiers cachés, et non juste le répertoire lui-même.


2. Copier des données de volume vers le système de fichiers de l'hôte (sauvegarde)

Utilisé lorsque vous souhaitez sauvegarder les données d'un volume dans un répertoire spécifique sur votre machine locale ou sur un serveur, par exemple dans un fichier .tar.

🤔 POURQUOI : comment ça fonctionne ?

Le principe est le même que précédemment. La seule différence est que la destination est maintenant 'un répertoire sur l'hôte' au lieu d'un 'volume Docker'.

Docker prend en charge une fonctionnalité de montage bind (Bind Mount) qui permet de monter un répertoire spécifique de l'hôte dans un conteneur.

  1. Le conteneur monte le volume source (source_volume) au chemin /data.

  2. Le conteneur monte un répertoire spécifique de l'hôte ($(pwd)/backup) au chemin /backup.

  3. Le conteneur copie (ou compresse) le contenu de /data vers le répertoire /backup.

  4. Bien que cette opération se déroule dans le conteneur, le répertoire /backup est lié à un répertoire réel sur l'hôte, donc le résultat restera sur l'hôte.

🚀 COMMENT : exemple de commande

Copie des données du volume source_data vers le répertoire backup à la position actuelle ($(pwd)).

# Créer un répertoire sur l'hôte pour la sauvegarde
mkdir -p $(pwd)/backup

docker run --rm \
       -v source_data:/data:ro \
       -v $(pwd)/backup:/backup \
       alpine \
       cp -a /data/. /backup/

💡 Explication de la commande

  • -v source_data:/data:ro: Nous avons ajouté le drapeau :ro (Read-Only). La sauvegarde doit uniquement lire les données, donc il est préférable de monter en lecture seule pour éviter toute modification accidentelle du volume source.

  • -v $(pwd)/backup:/backup: Contrairement à source_data (nom de volume), / ou une $(pwd) (chemin actuel) avec un chemin absolue ou relative indiquer un répertoire sur l'hôte.


3. Conseils clés pour copier (Tips)



Conseil 1 : utiliser tar pour une copie efficace (sauvegarde compressée)

Utiliser tar à la place de cp présente plusieurs avantages, notamment lors de la sauvegarde de données dans un fichier d'archive (.tar.gz) en une seule fois.

Volume-to-Volume (utilisation de tar)

Cela peut être plus rapide que cp, surtout lorsque de nombreux fichiers sont présents.

docker run --rm \
       -v source_data:/from \
       -v target_data:/to \
       alpine \
       sh -c "cd /from && tar -cf - . | (cd /to && tar -xf -)"
  • cd /from && tar -cf - .: Se déplace vers /from et archive le contenu du répertoire actuel (.) en l'envoyant sur la sortie standard (-).

  • | (cd /to && tar -xf -): Utilise un pipe (|) pour accepter l'entrée depuis la sortie standard et désarchive dans le répertoire /to.

Volume-to-Host (sauvegarde compressée)

Archive le contenu du volume source_data dans un fichier backup.tar.gz sur l'hôte.

docker run --rm \
       -v source_data:/data:ro \
       -v $(pwd):/backup \
       alpine \
       tar -czf /backup/backup.tar.gz -C /data .
  • tar -czf /backup/backup.tar.gz ...: c (créer), z (gzip compression), f (fichier) crée le fichier /backup/backup.tar.gz.

  • -C /data .: Ce point est crucial. En changeant d'abord le répertoire en /data, on archive tout ce qui s'y trouve (.

    ) sans inclure le chemin /data dans le fichier tar. Cela élimine les chemins inutiles dans l'archive.

Conseil 2 : Restaurer un fichier de l'hôte vers le volume

Restaurer est l'inverse de la sauvegarde et utilise le même principe. Il suffit d'inverser la direction de cp.

# Restaurer les données du répertoire $(pwd)/backup vers le volume new_data
docker run --rm \
       -v new_data:/data \
       -v $(pwd)/backup:/backup:ro \
       alpine \
       cp -a /backup/. /data/

Résumé

La clé pour travailler avec des volumes Docker est cette mentalité de "utiliser des conteneurs comme outils". Au lieu d'interagir directement avec les fichiers de volume depuis l'hôte, vous exécutez un conteneur temporaire monté avec les volumes nécessaires et les répertoires, puis exécutez des commandes standard Linux comme cp ou tar en toute sécurité à l'intérieur de celui-ci.

Si vous retenez ce principe, vous pourrez copier, sauvegarder et restaurer librement les données de volumes dans n'importe quelle situation.