Wanneer je Docker gebruikt, kom je vaak situaties tegen waarin je gegevens die zijn opgeslagen in een volume moet back-uppen of naar een ander volume moet kopiëren voor tests.

Je zou misschien denken aan het gebruik van het docker cp commando, maar dit commando ondersteunt alleen kopieën tussen de bestandssystemen van containers en de host, en je kunt niet rechtstreeks toegang krijgen tot volumes die door Docker worden beheerd.

In dit artikel introduceren we de juiste manier om Docker-volumes te kopiëren. We zullen niet alleen de commando's opsommen, maar we richten ons op waarom je deze methode moet gebruiken en de onderliggende principes. Door deze principes te begrijpen, kun je dit eenvoudig toepassen zonder de commando's uit je hoofd te hoeven leren.

Het belangrijkste principe is eenvoudig.

De veiligste en 'Docker-achtige' manier om met Docker-volumes te werken, is door een 'tijdelijke container' te gebruiken die toegang heeft tot dat volume als een brug.


1. Een bestaand volume naar een nieuw volume kopiëren (Volume-to-Volume)



Dit is het meest voorkomende scenario. Je wilt misschien het actieve db_data volume kopiëren naar een testvolume genaamd db_data_test.

🤔 WAAROM: Waarom een tijdelijke container gebruiken?

Docker-volumes worden ergens op het bestandssysteem van de host opgeslagen (/var/lib/docker/volumes/...), maar de Docker-daemon beheert dit pad. Het wordt niet aanbevolen om rechtstreeks naar dit pad te navigeren en het cp commando te gebruiken, omdat dit problemen met machtigingen of gegevensconsistentie kan veroorzaken.

In plaats daarvan draaien we een tijdelijke container die twee volumes tegelijk monteert.

  1. De container monteert het originele volume (source_volume) op het pad /from.

  2. De container monteert het doelvolume (new_volume) op het pad /to.

  3. De container voert onmiddellijk een eenvoudige Linux-opdracht uit om alle gegevens van /from naar /to te kopiëren (cp of tar).

  4. Wanneer de opdracht is voltooid, wordt de container automatisch verwijderd (--rm optie).

Deze container wordt alleen gebruikt als 'hulpmiddel' voor het kopiëren van gegevens.

🚀 HOE: Voorbeeld van het commando

Dit is een voorbeeld van het kopiëren van gegevens van het source_data volume naar het target_data volume.

  1. Maak een testvolume aan (optioneel)
docker volume create source_data
docker volume create target_data
# (ervan uitgaande dat er gegevens in source_data zijn.)
  1. Kopiëren met een tijdelijke container
docker run --rm \
       -v source_data:/from \
       -v target_data:/to \
       alpine \
       sh -c "cp -a /from/. /to/"

💡 Uitleg van het commando

  • docker run --rm: De --rm vlag geeft aan dat de container onmiddellijk moet worden verwijderd zodra deze klaar is met zijn taak. Dit is essentieel voor tijdelijke taken.

  • -v source_data:/from: Dit monteert het source_data volume in de /from map van de container.

  • -v target_data:/to: Dit monteert het target_data volume in de /to map van de container.

  • alpine: We gebruiken het alpine Linux-image, dat basisgereedschappen zoals cp en sh bevat, maar zeer klein is in omvang.

  • sh -c "...": Dit is het commando dat wordt gegeven wanneer de alpine-container wordt uitgevoerd.

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

    • -a (archief): Deze vlag is cruciaal. Het zorgt ervoor dat alle eigenschappen zoals eigenaar, machtigingen en tijdstempels behouden blijven tijdens de kopie. Dit is uiterst belangrijk bij het omgaan met gevoelige gegevens zoals databasebestanden.

    • /from/.: Dit betekent niet de map /from, maar alle inhoud binnen de map /from (inclusief verborgen bestanden).


2. Volumegegevens naar het host-bestandssysteem kopiëren (back-up)

Gebruik dit wanneer je de gegevens van een volume wilt back-uppen naar een specifieke map op je lokale machine of server in de vorm van een .tar bestand.

🤔 WAAROM: Hoe werkt het?

Het principe is hetzelfde als in punt 1. Het enige verschil is dat de bestemming veranderd is van 'docker volume' naar 'host map'.

Docker ondersteunt de bind mount functie, waarmee je een specifieke map van de host in de container kunt monteren.

  1. De container monteert het originele volume (source_volume) op het pad /data.

  2. De container monteert een specifieke map op de host ($(pwd)/backup) op het pad /backup.

  3. De container kopieert (of comprimeert) de inhoud van /data naar de map /backup.

  4. Deze taak vindt plaats binnen de container, maar de /backup map is verbonden met de echte host-map, dus de output blijft op de host.

🚀 HOE: Voorbeeld van het commando

Dit is het commando om de gegevens van het source_data volume naar de backup map op je huidige locatie ($(pwd)) te kopiëren.

# Maak de map aan waar de back-up naar moet worden geschreven
mkdir -p $(pwd)/backup

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

💡 Uitleg van het commando

  • -v source_data:/data:ro: We hebben de :ro (lees-slechts) vlag toegevoegd. Aangezien een back-up alleen de gegevens hoeft te lezen en je per ongeluk het originele volume wilt voorkomen, is het raadzaam om dit als lees-slechts te monteren.

  • -v $(pwd)/backup:/backup: In tegenstelling tot source_data (volume naam), verwijst een absolute of relatieve pad die begint met / of $(pwd) (huidige pad) naar een map op de host.


3. Belangrijke kopieertips (Tips)



Tip 1: Efficiënte kopie met tar (gecomprimeerde back-up)

Door tar in plaats van cp te gebruiken, zijn er meerdere voordelen. Het is vooral handig om gegevens samen te voegen tot een archiefbestand (.tar.gz) voor back-up.

Volume-to-Volume (met tar)

Het kan sneller zijn dan cp, vooral wanneer er veel bestanden zijn.

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 - .: Verandert naar /from en voegt de inhoud van de huidige map (.) samen met tar en verstuurt het naar de standaarduitvoer (-).

  • | (cd /to && tar -xf -): Ontvangt de standaarduitvoer via pipe (|) en pakt het uit in de /to map (x).

Volume-to-Host (gecomprimeerde back-up)

De inhoud van het source_data volume wordt gecomprimeerd en opgeslagen als backup.tar.gz bestand op de host.

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 ...: Dit geeft aan dat we c (creëren), z (gzip compressie), en f (bestand) creëren als /backup/backup.tar.gz.

  • -C /data .: Dit is belangrijk. We verplaatsen eerst naar de /data map en comprimeren dan alles daarin (.). Op deze manier komt er geen onnodig /data pad in het tar-bestand.

Tip 2: Herstellen van bestanden van de host naar het volume

Het herstellen van gegevens is het tegenovergestelde van een back-up; je hoeft alleen de richting van cp om te keren.

# Herstel de gegevens uit de $(pwd)/backup map naar het new_data volume
docker run --rm \
       -v new_data:/data \
       -v $(pwd)/backup:/backup:ro \
       alpine \
       cp -a /backup/. /data/

Samenvatting

De kern van het omgaan met Docker-volumes is de gedachtegang: "Gebruik containers als gereedschap". In plaats van rechtstreeks met volume-informatie op de host te werken, draaien we een tijdelijke container die de nodige volumes en mappen monteert, binnen welke we veilige Linux-opdrachten zoals cp of tar uitvoeren.

Als je dit principe onthoudt, zul je in staat zijn om volumegegevens te kopiëren, back-uppen en herstellen in elke situatie.