Wie stelle ich einen Docker-Container und den zugehörigen Datencontainer einschließlich des Inhalts bereit?

18

Ich beginne damit, dass ich zugeben muss, dass ich für Docker ziemlich neu bin, und mich diesem Problem möglicherweise aus den falschen Annahmen nähere. Lassen Sie mich wissen, ob dies der Fall ist. Ich habe viele Diskussionen darüber gesehen, wie Docker für die Bereitstellung nützlich ist, aber keine Beispiele dafür, wie dies tatsächlich getan wird.

Hier ist die Art, wie ich dachte, dass es funktionieren würde:

  1. Erstellen Sie den Datencontainer, der einige beständige Daten auf Computer A enthält
  2. Erstellen Sie den Anwendungscontainer, der Volumes aus dem Datencontainer verwendet
  3. Führen Sie einige Arbeiten aus und ändern Sie möglicherweise die Daten im Datencontainer
  4. Stoppen Sie den Anwendungscontainer
  5. Commit & Tag des Datencontainers
  6. Verschieben Sie den Datencontainer in ein (privates) Repository
  7. Ziehen Sie das Bild aus Schritt 6 auf Maschine B und führen Sie es aus
  8. heben Sie auf, wo Sie auf Maschine B aufgehört haben

Der Schlüsselschritt hier ist Schritt 5, von dem ich dachte, dass er den aktuellen Status (einschließlich des Inhalts des Dateisystems) speichert. Sie können diesen Status dann in ein Repository verschieben und von einem anderen Ort abrufen, sodass Sie einen neuen Container erhalten, der im Wesentlichen mit dem Original identisch ist.

Aber es scheint nicht so zu funktionieren. Was ich finde, ist, dass entweder Schritt 5 nicht das tut, was ich denke, oder Schritt 7 (Ziehen und Ausführen des Bildes) den Container auf seinen Ausgangszustand "zurücksetzt".

Ich habe drei Docker-Images und -Container zusammengestellt, um dies zu testen: einen Datencontainer, einen Writer, der alle 30 Sekunden eine zufällige Zeichenfolge in eine Datei im Datencontainer schreibt, und einen Reader, der einfach echoden Wert in den Daten ermittelt Container-Datei und beendet.

Datencontainer

Hergestellt mit

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder

Schriftsteller

Hergestellt mit

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]

run.sh

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done

Dieses Skript schreibt eine zufällige Zeichenfolge und das Datum / die Uhrzeit /datafolder/data.txtin den Datencontainer.

Leser

Hergestellt mit

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

Wenn ich diese Container erstelle und ausführe, laufen sie einwandfrei und funktionieren so, wie ich es erwartet habe:

Stop & Start auf der Entwicklungsmaschine:

  1. Erstellen Sie den Datencontainer
  2. Führen Sie den Schriftsteller
  3. Den Reader sofort starten, siehe "Keine Daten hier!" Botschaft
  4. Warte eine Weile
  5. Führe den Reader aus, siehe die zufällige Zeichenfolge
  6. Stoppen Sie den Schriftsteller
  7. Starten Sie den Writer neu
  8. Führen Sie den Reader aus, und sehen Sie die gleiche zufällige Zeichenfolge

Aber Commitment & Pushing tun nicht das, was ich erwarte:

  1. Erstellen Sie den Datencontainer
  2. Führen Sie den Schriftsteller
  3. Den Reader sofort starten, siehe "Keine Daten hier!" Botschaft
  4. Warte eine Weile
  5. Führe den Reader aus, siehe die zufällige Zeichenfolge
  6. Stoppen Sie den Schriftsteller
  7. Commit & Tag des Datencontainers mit docker commit datatest_data myrepository:5000/datatest-data:latest
  8. Push in das Repository
  9. Lösche alle Container und erstelle sie neu

An diesem Punkt würde ich erwarten, dass der Reader ausgeführt und dieselbe zufällige Zeichenfolge angezeigt wird, da der Datencontainer festgeschrieben, in das Repository verschoben und dann aus demselben Image im Repository neu erstellt wurde. Was ich jedoch tatsächlich sehe, ist das "keine Daten hier!" Botschaft.

Kann jemand erklären, wo ich hier falsch liege? Oder zeigen Sie mir alternativ ein Beispiel für die Bereitstellung mit Docker.

Kryten
quelle

Antworten:

22

Sie haben eine falsche Annahme darüber, wie Volumes in Docker funktionieren. Ich werde versuchen zu erklären, wie sich Volumes auf Docker-Container und Docker-Images beziehen, und hoffentlich werden Unterschiede zwischen Daten-Volumes und Daten-Volume-Containern deutlich.

Erinnern wir uns zunächst an einige Definitionen

Docker-Bilder

Docker-Images sind im Wesentlichen ein Unionsdateisystem und Metadaten. Mit dem docker exportBefehl können Sie den Inhalt des Docker-Image-Union-Dateisystems überprüfen und mit dem Befehl können Sie Docker-Image-Metadaten überprüfen docker inspect.

Datenvolumen

aus dem Docker-Benutzerhandbuch :

Ein Daten-Volume ist ein speziell festgelegtes Verzeichnis in einem oder mehreren Containern, das das Union File System umgeht und mehrere nützliche Funktionen für persistente oder gemeinsam genutzte Daten bietet.

Hierbei ist zu beachten, dass ein bestimmtes Volume (als das Verzeichnis oder die Datei, die Daten enthält) nur dann wiederverwendbar ist, wenn mindestens ein Docker-Container vorhanden ist, der es verwendet. Docker-Images haben keine Volumes, sondern nur Metadaten, aus denen hervorgeht, wo die Volumes im Union-Dateisystem bereitgestellt werden. Datenvolumes gehören nicht zum Dateisystem der Docker-Container-Union. Wo befinden sie sich also? under /var/lib/docker/volumesauf dem Docker-Host (während Container unter gespeichert werden /var/lib/docker/containers).

Datenvolumenbehälter

Dieser spezielle Containertyp hat nichts Besonderes. Es handelt sich lediglich um angehaltene Container, die ein Datenvolumen verwenden, mit dem einzigen und eindeutigen Ziel, dass mindestens ein Container dieses Datenvolumen verwendet. Denken Sie daran, sobald der letzte Container (ausgeführt oder gestoppt), der ein bestimmtes Datenvolumen verwendet, gelöscht wird, wird dieses Volumen über die Andock-Ausführungsoption nicht mehr erreichbar --volumes-from.

Arbeiten mit Datenträgercontainern

So erstellen Sie einen Datenvolumencontainer

Das zum Erstellen eines Datenvolumen-Containers verwendete Image hat keine Bedeutung, da ein solcher Container angehalten bleiben und dennoch seinen Zweck erfüllen kann. Um einen Datencontainer mit dem Namen datatest_datafür ein Volume in zu erstellen, /datafoldermüssen Sie nur Folgendes ausführen:

docker run --name datatest_data --volume /datafolder busybox true

Hier baseist der Image-Name (ein praktischer kleiner) und trueein Befehl, den wir bereitstellen, um zu vermeiden, dass sich der Docker-Daemon über einen fehlenden Befehl beschwert. Jedenfalls, nachdem Sie einen angehaltenen Container datatest_datamit dem einzigen Zweck benannt haben, Ihnen zu erlauben, dieses Volumen mit der --volumes-fromOption des docker runBefehls zu erreichen.

So lesen Sie aus einem Datenvolumencontainer

Ich kenne zwei Möglichkeiten zum Lesen eines Datenvolumens: Die erste ist durch einen Container. Wenn Sie nicht über eine Shell in einem vorhandenen Container verfügen können, um auf dieses Datenvolumen zuzugreifen, können Sie einen neuen Container mit der --volumes-fromOption zum alleinigen Lesen dieser Daten ausführen .

Zum Beispiel:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

Die andere Möglichkeit besteht darin, das Volume aus dem /var/lib/docker/volumesOrdner zu kopieren . Sie können den Namen des Volumes in diesem Ordner ermitteln, indem Sie die Metadaten eines Containers mithilfe des Volumes überprüfen. Siehe diese Antwort für Details.

Arbeiten mit Volumes (seit Docker 1.9.0)

So erstellen Sie ein Volume (seit Docker 1.9.0)

Docker 1.9.0 hat einen neuen Befehl eingeführt docker volume, mit dem Sie Volumes erstellen können:

docker volume create --name hello

Lesen von einem Volume (seit Docker 1.9.0)

Lassen Sie sagen , Sie ein Volume erstellt mit dem Namen hellomit docker volume create --name hello, können Sie es in einem Behälter mit der Halterung kann -vOption:

docker run -v hello:/data busybox ls /data

Über das Festschreiben und Schieben von Containern

Es sollte jetzt klar sein, dass, da Datenvolumes nicht Teil eines Containers (des Union-Dateisystems) sind, das Festschreiben eines Containers zur Erstellung eines neuen Docker-Images keine Daten persistieren wird, die sich in einem Datenvolumen befinden würden.

Backups von Datenmengen erstellen

Das Docker-Benutzerhandbuch enthält einen schönen Artikel zum Erstellen von Backups von Datenmengen .


Guter Artikel zum Thema Volumes: http://container42.com/2014/11/03/docker-indepth-volumes/

Thomasleveil
quelle
Es scheint, dass "das zum Erstellen eines Datenvolumencontainers verwendete Image keine Bedeutung hat" nicht ganz korrekt ist. Versuchen Sie es einfach mit einem "Scratch" -Image, das "exec:" true "ergibt: ausführbare Datei nicht gefunden"
tcurdt
Trotz dieses Fehlers wird Ihr Container erstellt und erfüllt seine Rolle als Volumeninhaber
Thomasleveil
1
Hm - vielleicht lohnt es sich dann ein Thema dafür zu eröffnen.
tcurdt
Nein, dieses Verhalten wird erwartet, da das Scratch-Image ein leeres Image ist, das /bin/trueohnehin keine Binärdatei (oder keine andere) enthalten kann
Thomasleveil 10.11.14
1
Nur eine Sache. Sie sagten, dass "sobald der letzte Container (ausgeführt oder gestoppt), der ein bestimmtes Datenvolumen verwendet, gelöscht wird, wird dieses Datenvolumen von Docker aus / var / lib / docker / volume zerstört." docs.docker.com/userguide/dockervolumes ( Datenvolumes bleiben bestehen, auch wenn der Container selbst gelöscht wird. Sie müssen den docker rm -vBefehl für den letzten Container angeben, um auch ein Volume zu löschen.)
25.
1

Sie können auch einen Docker-Datencontainer zum Bereitstellen von Code verwenden

Ich weiß nicht, ob es eine gute Übung ist, aber ich mache es so:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

Sie können jetzt Ihr Bild pushen und Volumes von usw. verwenden.

jmny
quelle
Dies ist, was ich suche, aber die akzeptierte Antwort erwähnt ausdrücklich, dass dies nicht getan werden kann. Ich werde es jetzt ausprobieren.
Andho
1
Auf den zweiten Blick sagt eine akzeptierte Antwort, dass die Volumes (oder Daten darin) nicht festgeschrieben werden, aber Sie können die Daten mit COPYoder in den Container einfügen ADDund das Volume mit VOLUMEin der Docker-Datei erstellen.
Andho