Docker ermöglicht es Container an sogenannte Volumes zu mounten. Dadurch ergibt sich die Möglichkeit, Daten vom Container abzukapseln und somit über die Lebensdauer des Containers hinweg aufrecht zu erhalten.

Ein weiter Vorteil ist der, dass unterschiedliche Container auf solch ein Volume Zugriff haben können, sodass ein und die selben Daten für zwei unterschiedliche Container zur Verfügung stehen.

Zuletzt sei noch erwähnt, dass Volumes komplett von Docker gehandhabt werden, d.h. für jedes Volume wird von Docker ein neues Verzeichnis innerhalb dessen Speicherverzeichnisses auf der Hostmaschine angelegt (Linux bspw. /var/lib/docker/volumes/).

Hinweis

Es gibt 2 Möglichkeiten solche Volumes zu mounten

  1. mittels -v bzw. --volume
  2. mittels --mount

Docker empfiehlt neuen Benutzern --mount zu verwenden. Das liegt daran, dass man mit --mount explizit den Typen (bind, volume, tmpfs) mit angeben muss. Mit -v hingegen ist allein die Syntax des Befehls ausschlaggebend dafür, welcher Typ verwendet wird. Diese feinen Nuancen in der Syntax führen nun aber oft zu Leichtsinnsfehlern, die eben mit --mount nicht passieren können.

Wir betrachten daher im Folgenden nur den --mount Befehl.

Postgres Container an ein neues, externes Volume mounten

Wir werden einen postgres alpine Container starten und diesen an ein von uns spezifiziertes Volume namens myvol mounten.

Zunächst lassen wir uns jedoch auf unserem Computer (=Hostmaschine) alle bisherigen Volumes ausgeben

apoehlmann $ docker volume ls
DRIVER              VOLUME NAME
local               d2b7c9c12cafe507265d84e180d1d1a80de01c684d6963b898adcb12426c8aff
local               e9c8d47f1aa39674699d6e78ad279526e19110cf4dde87e5b7bb8e42b6502727

Nun starten wir einen postgres:alpine Container namens test und zwar mit interaktiver Shell. Wir spezifizieren, dass im Container das Verzeichnis /mydata an ein Volume namens myvol gemounted wird (insofern diese nicht bereits existieren, werden sie neu erstellt). Mit --rm geben wir an, dass der Container gelöscht wird, sobald wir die Shell schließen:

apoehlmann $ docker run --rm -it \
 --name test1 \
 --mount source=myvol,target=/mydata \
 postgres:alpine sh

In meinem Fall lag noch kein postgres:alpine Image vor, daher sieht der Output wie folgt aus

Unable to find image 'postgres:alpine' locally
alpine: Pulling from library/postgres
ff3a5c916c92: Already exists 
a503b44e1ce0: Pull complete 
211706713093: Pull complete 
ea28caf317dd: Pull complete 
a9b37749335b: Pull complete 
f7e94ebc5400: Pull complete 
77dd3a51253d: Pull complete 
633a37734b12: Pull complete 
872e6b940bbb: Pull complete 
Digest: sha256:89c84fcccc147d403916f4d9964bc4d83297ea7c782d79b05dad5b6c172a7dce
Status: Downloaded newer image for postgres:alpine
/ #

Das /# in der letzten Zeile signalisiert, dass wir uns in der Shell des postgres Containers befinden. Mittels ls können wir nun checken, ob das /mydata Verzeichnis vorliegt

/ # ls
bin                         docker-entrypoint.sh        lib                         mydata                      run                         sys                         var
dev                         etc                         media                       proc                        sbin                        tmp
docker-entrypoint-initdb.d  home                        mnt                         root                        srv                         usr
/ #

was tatsächlich der Fall ist. Mit docker -ps auf der Hostmaschine lassen wir uns alle aktuell laufenden Container ausgeben

apoehlmann $ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
89c449b4bc63        postgres:alpine     "docker-entrypoint.s…"   1 second ago        Up 4 seconds        5432/tcp            test1

Nun überprüfen wir auf unseren Host PC nochmals alle vorhandenen Volumes

apoehlmann $ docker volume ls
DRIVER              VOLUME NAME
local               78a6c197848b36afb5d47bae967e2628e3ac2cf25c08adc4b4e1002359ac38e6
local               d2b7c9c12cafe507265d84e180d1d1a80de01c684d6963b898adcb12426c8aff
local               e9c8d47f1aa39674699d6e78ad279526e19110cf4dde87e5b7bb8e42b6502727
local               myvol

und wir erkennen, dass von Docker ein neues Volumen namens myvol kreiert wurde.

Zum Testen stellen wir eine neue Datei namens persistent.txt im Container her. Anschließend schließen wir die Shell (CTRL + D). Wegen dem --rm Flag wird der Container gelöscht.

/ # touch /mydata/persistent.txt
/ # ls /mydata/
persistent.txt

Wir werden nun versuchen, die Datei einem neuen Container zur Verfügung zu stellen.

Neuen Container an bereits vorhandenes, externes Volume mounten

Um die Datenpersistenz zu überprüfen, bauen wir nun einen neuen, zweiten Container namens test2. Der Befehl ist bis auf --name test2 der selbe

docker run --rm -it \
 --name test2 \
 --mount source=myvol,target=/mydata \
 postgres:alpine sh
/ #

Dieses Mal wurden keine Images gedownloaded. Auch überprüft Docker automatisch, ob das als source spezifizierte Volume bereits existiert. Da dies der Fall ist, wird dieses bereits bestehende Volume verwendet. docker -ps auf der Hostmaschine liefert

apoehlmann $ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
d7377a064d17        postgres:alpine     "docker-entrypoint.s…"   47 seconds ago      Up 50 seconds       5432/tcp            test2

und wir erkennen anhand der ID und dem Namen, dass es sich hierbei in der Tat um einen neuen Container handelt.

In der Shell des Containers lassen wir uns nun den Inhalt des /mydata Verzeichnisses ausgeben

/ # ls /mydata/
persistent.txt
/ #

Die Datei, die wir im vorherigen Container hergestellt haben ist trotz Löschung des alten Containers immer noch vorhanden. Wenn wir auf den Host ein Linux Betriebssystem benutzen, können wir uns den Inhalt des neu erstellten Docker Volumes mydata ausgeben lassen (auf macOS etc. ist dies nicht ohne weiteres möglich, da Docker hinter einer Virtualisierung läuft. Für mehr Info siehe https://stackoverflow.com/questions/38532483/where-is-var-lib-docker-on-mac-os-x)

apoehlmann $ ls /var/lib/docker/volumes/myvol/_data/
persistent.txt

Wie erwartet befindet sich die Datei im _data Verzeichnis des neu erstellten Docker Volumes.

Postgres Datenverzeichnis eines Containers an externes Volume mounten

Wir wissen nun, wie man ein Verzeichnis innerhalb eines Containers an ein externes Docker Volume mounten kann, und haben dies auch schon für ein selbst gewähltes Verzeichnis anhand zweier Beispiele gesehen.

Doch was, wenn wir sämtliche Postgres Daten innerhalb unseres Containers an ein Docker Volume mounten möchten?

Dafür müssen wir den Dateipfad kennen, unter dem postgres sämttliche Daten abspeichert, um dieses Verzeichnis als target angeben zu können. Unter Linux ist dies /var/lib/postgresql/data.

Getagged mit:
Docker Tutorial German
blog comments powered by Disqus