Umgang mit persistentem Speicher (z. B. Datenbanken) in Docker

992

Wie gehen die Leute mit der dauerhaften Speicherung Ihrer Docker-Container um?

Ich verwende derzeit diesen Ansatz: Erstellen Sie das Image, z. B. für PostgreSQL, und starten Sie den Container mit

docker run --volumes-from c0dbc34fd631 -d app_name/postgres

IMHO, das hat den Nachteil, dass ich niemals (aus Versehen) den Container "c0dbc34fd631" löschen darf.

Eine andere Idee wäre, Host-Volumes "-v" in den Container zu mounten. Die Benutzer-ID im Container stimmt jedoch nicht unbedingt mit der Benutzer-ID des Hosts überein , und dann können die Berechtigungen durcheinander gebracht werden.

Hinweis: Statt --volumes-from 'cryptic_id'Sie kann auch verwendet werden, --volumes-from my-data-containerwo my-data-containerein Name , den Sie einen Nur - Daten-Container zugeordnet ist, zum Beispiel docker run --name my-data-container ...(siehe akzeptierte Antwort)

Juwalter
quelle
Entschuldigung, ich habe das falsch formuliert, ich wollte sagen: Alle meine zukünftigen Instanzen von diesem Bild hängen von diesem Container ab. Wenn ich diesen Container versehentlich lösche, habe ich Probleme.
Juwalter
@AntonStrogonoff - yep, Phrasierungsfehler - Ich wollte sagen: Ich muss sicherstellen, dass ich diesen (möglicherweise) alten Container niemals löschen werde, da dann auch die Referenz des "persistenten" Speichers weg wäre
juwalter
es sollte sein --name. Sie haben-name
Shammel Lee

Antworten:

986

Docker 1.9.0 und höher

Verwenden Sie die Volume-API

docker volume create --name hello
docker run -d -v hello:/container/path/for/volume container_image my_command

Dies bedeutet, dass das Nur-Daten-Containermuster zugunsten der neuen Volumes aufgegeben werden muss.

Tatsächlich ist die Volumen-API nur ein besserer Weg, um das Datencontainer-Muster zu erreichen.

Wenn Sie einen Container mit einem -v volume_name:/container/fs/pathDocker erstellen, wird automatisch ein benanntes Volume für Sie erstellt, das:

  1. Seien Sie durch die gelistet docker volume ls
  2. Durch die identifiziert werden docker volume inspect volume_name
  3. Als normales Verzeichnis gesichert
  4. Nach wie vor über eine --volumes-fromVerbindung gesichert

Die neue Volume-API fügt einen nützlichen Befehl hinzu, mit dem Sie baumelnde Volumes identifizieren können:

docker volume ls -f dangling=true

Und dann entfernen Sie es durch seinen Namen:

docker volume rm <volume name>

Wie @mpugach in den Kommentaren unterstreicht, können Sie alle baumelnden Bände mit einem schönen Einzeiler entfernen:

docker volume rm $(docker volume ls -f dangling=true -q)
# Or using 1.13.x
docker volume prune

Docker 1.8.x und darunter

Der Ansatz, der für die Produktion am besten zu funktionieren scheint, ist die Verwendung eines Nur-Daten-Containers .

Der Nur-Daten-Container wird auf einem Barebone-Image ausgeführt und führt nur ein Datenvolumen aus.

Anschließend können Sie einen beliebigen anderen Container ausführen, um Zugriff auf die Datencontainervolumes zu erhalten:

docker run --volumes-from data-container some-other-container command-to-execute
  • Hier können Sie sich ein gutes Bild von der Anordnung der verschiedenen Container machen.
  • Hier gibt es einen guten Einblick in die Funktionsweise von Volumes.

In diesem Blog-Beitrag gibt es eine gute Beschreibung des sogenannten Containers als Volumenmuster, die den Hauptpunkt verdeutlicht, dass nur Datencontainer vorhanden sind .

Die Docker-Dokumentation enthält jetzt die DEFINITIVE Beschreibung des Containers als Volume / s- Muster.

Im Folgenden wird das Sicherungs- / Wiederherstellungsverfahren für Docker 1.8.x und niedriger beschrieben.

SICHERUNG:

sudo docker run --rm --volumes-from DATA -v $(pwd):/backup busybox tar cvf /backup/backup.tar /data
  • --rm: Entferne den Container beim Verlassen
  • --volumes-from DATA: Wird an die vom DATA-Container gemeinsam genutzten Volumes angehängt
  • -v $ (pwd): / backup: bind mounte das aktuelle Verzeichnis in den Container; um die TAR-Datei zu schreiben
  • Busybox: Ein kleines, einfacheres Bild - gut für eine schnelle Wartung
  • tar cvf /backup/backup.tar / data: Erstellt eine unkomprimierte tar-Datei aller Dateien im Verzeichnis / data

WIEDERHERSTELLEN:

# Create a new data container
$ sudo docker run -v /data -name DATA2 busybox true
# untar the backup files into the new container᾿s data volume
$ sudo docker run --rm --volumes-from DATA2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
data/
data/sven.txt
# Compare to the original container
$ sudo docker run --rm --volumes-from DATA -v `pwd`:/backup busybox ls /data
sven.txt

Hier ist ein schöner Artikel von Brian Goff, der erklärt, warum es gut ist, dasselbe Bild für einen Container und einen Datencontainer zu verwenden.

Tommasop
quelle
8
Es ist ein anderes Werkzeug für einen anderen Bedarf. --volumes-fromMit dem Speicherplatz können --linkSie Dienste gemeinsam nutzen.
Tommasop
3
Es gibt ein anderes Projekt in den Werken, das speziell für diese Art von Dingen gedacht ist. Vielleicht fügen Sie es dieser Antwort als Referenz zum Anschauen hinzu? github.com/ClusterHQ/flocker
Andre
9
Datencontainer haben keine Bedeutung und sind wirklich eine schlechte Idee! Container bedeutet nur etwas, wenn ein Prozess darin ausgeführt wird, andernfalls ist es nur ein Teil des Host-Dateisystems. Sie können ein Volume einfach mit -v mounten, was die einzige und beste Option ist. Sie haben die Kontrolle über das Dateisystem und die physische Festplatte, die Sie verwenden.
Boynux
11
Ja, ab Docker 1.9 wird das Erstellen benannter Volumes mit der Volumes-API ( docker volume create --name mydata) einem Datenvolumen-Container vorgezogen. Die Mitarbeiter von Docker selbst schlagen vor, dass Datenvolumen- Container „ nicht mehr als empfohlenes Muster angesehen werden“, „ benannte Datenträger sollten in den meisten (wenn nicht allen) Fällen nur Daten-Datenträger ersetzen können “ und „ kein Grund, den ich verwenden kann Nur-Daten-Container . “
Quinn Comendant
8
@coding, ich bin traurig, dass Sie traurig sind, teilweise, weil Sie Antworten mit einer Verzögerung von 3 Jahren beurteilen, und teilweise, weil die Antwort in ihrer gesamten Geschichte im Wesentlichen richtig ist. Wenn Sie einen Rat haben, können Sie ihn
gerne
75

In Docker Release v1.0 kann das Binden eines Mount einer Datei oder eines Verzeichnisses auf dem Hostcomputer mit dem folgenden Befehl erfolgen:

$ docker run -v /host:/container ...

Das oben genannte Volume kann als dauerhafter Speicher auf dem Host verwendet werden, auf dem Docker ausgeführt wird.

Amitmula
quelle
3
Dies sollte die empfohlene Antwort sein, da sie weitaus weniger komplex ist als der Volumen-Container-Ansatz, der derzeit mehr Stimmen hat
insitusec
2
Ich wünschte, es gäbe ein Flag, um eine Zuordnung von host-uid: container-uid und host-gid: container-gid anzugeben, wenn dieser Befehl zum Einhängen von Volumes verwendet wird.
Rampion
35

Ab Docker Compose 1.6 wird die Unterstützung für Datenmengen in Docker Compose jetzt verbessert. Die folgende Erstellungsdatei erstellt ein Datenbild, das zwischen dem Neustart (oder sogar dem Entfernen) der übergeordneten Container erhalten bleibt:

Hier ist die Blog-Ankündigung: Compose 1.6: Neue Compose-Datei zum Definieren von Netzwerken und Volumes

Hier ist ein Beispiel für eine Erstellungsdatei:

version: "2"

services:
  db:
    restart: on-failure:10
    image: postgres:9.4
    volumes:
      - "db-data:/var/lib/postgresql/data"
  web:
    restart: on-failure:10
    build: .
    command: gunicorn mypythonapp.wsgi:application -b :8000 --reload
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    links:
      - db

volumes:
  db-data:

Soweit ich verstehen kann: Dadurch wird ein Datenvolumencontainer ( db_data) erstellt, der zwischen den Neustarts bestehen bleibt.

Wenn Sie ausführen: docker volume lsIhr Volume sollte aufgelistet sein:

local               mypthonapp_db-data
...

Weitere Informationen zum Datenvolumen erhalten Sie:

docker volume inspect mypthonapp_db-data
[
  {
    "Name": "mypthonapp_db-data",
    "Driver": "local",
    "Mountpoint": "/mnt/sda1/var/lib/docker/volumes/mypthonapp_db-data/_data"
  }
]

Einige Tests:

# Start the containers
docker-compose up -d

# .. input some data into the database
docker-compose run --rm web python manage.py migrate
docker-compose run --rm web python manage.py createsuperuser
...

# Stop and remove the containers:
docker-compose stop
docker-compose rm -f

# Start it back up again
docker-compose up -d

# Verify the data is still there
...
(it is)

# Stop and remove with the -v (volumes) tag:

docker-compose stop
docker=compose rm -f -v

# Up again ..
docker-compose up -d

# Check the data is still there:
...
(it is).

Anmerkungen:

  • Sie können auch verschiedene Treiber im volumesBlock angeben . Sie können beispielsweise den Flocker-Treiber für db_data angeben:

    volumes:
      db-data:
        driver: flocker
    
  • Da sie die Integration zwischen Docker Swarm und Docker Compose verbessern (und möglicherweise Flocker in das Docker-Ökosystem integrieren (ich habe ein Gerücht gehört, dass Docker Flocker gekauft hat), sollte dieser Ansatz meiner Meinung nach immer leistungsfähiger werden.

Haftungsausschluss: Dieser Ansatz ist vielversprechend und ich verwende ihn erfolgreich in einer Entwicklungsumgebung. Ich wäre besorgt, dies noch in der Produktion zu verwenden!

toast38coza
quelle
Flocker wurde geschlossen und es gibt nicht viel Aktivität auf dem Github Repo
Krishna
17

Falls aus Update 5 der ausgewählten Antwort ab Docker 1.9 nicht ersichtlich ist, können Sie Volumes erstellen, die existieren können, ohne einem bestimmten Container zugeordnet zu sein, wodurch das Muster "Nur-Daten-Container" veraltet ist.

Siehe Nur-Daten-Container, die mit Docker 1.9.0 veraltet sind. # 17798 .

Ich denke, die Docker-Betreuer haben erkannt, dass das Nur-Daten-Containermuster ein wenig nach Design riecht, und beschlossen, Volumes zu einer separaten Entität zu machen, die ohne zugehörigen Container existieren kann.

ben_frankly
quelle
13

Während dies immer noch ein Teil von Docker ist , der einige Arbeit benötigt , sollten Sie das Volume mit der Anweisung VOLUME in die Docker-Datei einfügen, damit Sie die Volumes nicht aus einem anderen Container kopieren müssen.

Dadurch werden Ihre Container weniger voneinander abhängig und Sie müssen sich keine Sorgen mehr machen, dass ein Container einen anderen beeinflusst.

Tim Dorr
quelle
Das Kehrseite-Argument ist, dass die "Nur-Daten" docker rm
-Container
2
In diesem offiziellen Handbuch von Docker wird Folgendes vorgeschlagen : docs.docker.com/userguide/dockervolumes/… " Datenvolumes sind so konzipiert, dass sie Daten unabhängig vom Lebenszyklus des Containers beibehalten . Docker löscht daher Volumes niemals automatisch, wenn Sie einen Container entfernen, und wird dies auch nicht tun "Garbage Collect" -Volumes, auf die kein Container mehr verweist. "
Alex
12

Fügen Sie bei Verwendung von Docker Compose einfach ein benanntes Volume hinzu, zum Beispiel:

version: '2'
services:
  db:
    image: mysql:5.6
    volumes:
      - db_data:/var/lib/mysql:rw
    environment:
      MYSQL_ROOT_PASSWORD: root
volumes:
  db_data:
Zar Pino
quelle
9

Die Antwort von @ tommasop ist gut und erklärt einige der Mechanismen der Verwendung von Nur-Daten-Containern. Aber als jemand, der anfangs dachte, dass Datencontainer dumm waren, wenn man nur ein Volume an den Host binden konnte (wie in mehreren anderen Antworten vorgeschlagen), aber jetzt erkennt, dass reine Datencontainer tatsächlich ziemlich ordentlich sind, kann ich mein eigenes vorschlagen Blogbeitrag zu diesem Thema: Warum Docker-Datencontainer (Volumes!) gut sind

Siehe auch: Meine Antwort auf die Frage " Wie lassen sich Berechtigungen für gemeinsam genutzte Docker-Volumes (am besten) verwalten? " Ein Beispiel für die Verwendung von Datencontainern, um Probleme wie Berechtigungen und UID / GID-Zuordnung mit dem Host zu vermeiden.

Um eines der ursprünglichen Bedenken des OP auszuräumen: Der Datencontainer darf nicht gelöscht werden. Selbst wenn der Datencontainer gelöscht wird, gehen die Daten selbst nicht verloren, solange ein Container auf dieses Volume verweist, dh auf einen Container, über den das Volume bereitgestellt wurde --volumes-from. Wenn also nicht alle zugehörigen Container gestoppt und gelöscht werden (man könnte dies als das Äquivalent eines Unfalls betrachten rm -fr /), sind die Daten sicher. Sie können den Datencontainer jederzeit neu erstellen, indem Sie einen --volumes-frombeliebigen Container ausführen, der auf dieses Volume verweist.

Machen Sie aber wie immer Backups!

UPDATE: Docker verfügt jetzt über Volumes, die unabhängig von Containern verwaltet werden können, was die Verwaltung weiter vereinfacht.

Raman
quelle
9

Abhängig von Ihren Anforderungen gibt es verschiedene Ebenen für die Verwaltung persistenter Daten:

  • Speichern Sie es auf Ihrem Host
    • Verwenden Sie das Flag, -v host-path:container-pathum Containerverzeichnisdaten in einem Hostverzeichnis zu speichern.
    • Sicherungen / Wiederherstellungen erfolgen durch Ausführen eines Sicherungs- / Wiederherstellungscontainers (z. B. tutumcloud / dockup), der im selben Verzeichnis bereitgestellt ist.
  • Erstellen Sie einen Datencontainer und hängen Sie seine Volumes in Ihren Anwendungscontainer ein
    • Erstellen Sie einen Container, der ein Datenvolumen exportiert, --volumes-fromund hängen Sie diese Daten in Ihren Anwendungscontainer ein.
    • Sichern / Wiederherstellen wie oben beschrieben.
  • Verwenden Sie ein Docker-Volume-Plugin, das einen externen Dienst / Dienst eines Drittanbieters unterstützt
    • Mit Docker-Volume-Plugins kann Ihre Datenquelle von überall her kommen - NFS, AWS (S3, EFS und EBS)
    • Abhängig vom Plugin / Service können Sie einzelne oder mehrere Container an ein einzelnes Volume anhängen.
    • Je nach Dienst können Sicherungen / Wiederherstellungen für Sie automatisiert werden.
    • Während dies manuell umständlich sein kann, haben einige Orchestrierungslösungen - wie Rancher - es eingebrannt und sind einfach zu verwenden.
    • Konvoi ist die einfachste Lösung, um dies manuell zu tun.
Will Stern
quelle
8

Wenn Sie Ihre Volumes verschieben möchten, sollten Sie sich auch Flocker ansehen .

Aus der README:

Flocker ist ein Datenvolumen-Manager und ein Docker-Cluster-Management-Tool für mehrere Hosts. Damit können Sie Ihre Daten mit denselben Tools steuern, die Sie für Ihre zustandslosen Anwendungen verwenden, indem Sie die Leistung von ZFS unter Linux nutzen.

Dies bedeutet, dass Sie Ihre Datenbanken, Warteschlangen und Schlüsselwertspeicher in Docker ausführen und so einfach verschieben können wie der Rest Ihrer Anwendung.

Johann Romefort
quelle
1
Danke Johann. Ich arbeite bei ClusterHQ und wollte nur darauf hinweisen, dass wir nicht nur ZFS-basierten Speicher verwenden. Sie können Flocker jetzt mit Speicher wie Amazon EBS oder Google Persistent Disk verwenden. Hier ist eine vollständige Liste der Speicheroptionen: docs.clusterhq.com/de/latest/supported/…
Ferrantim
1
Flocker ist eingestellt und sollte nicht verwendet werden portworx.com/…
jesugmz
5

Dies hängt von Ihrem Szenario ab (dies ist für eine Produktionsumgebung nicht wirklich geeignet), aber hier ist eine Möglichkeit:

Erstellen eines MySQL Docker-Containers

Das Wesentliche dabei ist, ein Verzeichnis auf Ihrem Host für die Datenpersistenz zu verwenden.

ben schwartz
quelle
6
Vielen Dank an Ben - eines der Probleme, die ich bei diesem Ansatz sehen kann: Die Dateisystemressource (Verzeichnis, Dateien) würde einer UID aus dem Docker / LXC-Container (Gast) gehören - eine, die möglicherweise mit einer UID kollidiert auf dem Gastgeber ...
Juwalter
1
Ich denke, Sie sind ziemlich sicher, da es von root ausgeführt wird, aber ich stimme zu, dass es ein Hack ist - bestenfalls geeignet für lokale dev / ephemere Integrationstests. Dies ist definitiv ein Bereich, in dem ich gerne mehr Muster / Denken sehen würde. Sie sollten diese Frage überprüfen / an die Docker-Entwickler-Google-Gruppe
senden
Ben, danke für diese Lösung! Ich würde es aber nicht als Hack bezeichnen, es scheint viel zuverlässiger als Container als Volumen . Sehen Sie Nachteile, wenn Daten ausschließlich aus dem Container verwendet werden? (UID spielt in diesem Fall keine Rolle)
Johndodo
1

Ich verwende nur ein vordefiniertes Verzeichnis auf dem Host, um Daten für PostgreSQL beizubehalten. Auf diese Weise ist es auch möglich, vorhandene PostgreSQL-Installationen einfach in Docker-Container zu migrieren: https://crondev.com/persistent-postgresql-inside-docker/

Alen Komljen
quelle
0

Meine Lösung besteht darin, das neue zu verwenden docker cp, mit dem jetzt Daten aus Containern kopiert werden können, unabhängig davon, ob sie ausgeführt werden oder nicht, und ein Host-Volume an genau demselben Speicherort freigegeben wird, an dem die Datenbankanwendung ihre Datenbankdateien im Container erstellt . Diese Doppellösung funktioniert ohne Nur-Daten-Container direkt aus dem ursprünglichen Datenbankcontainer.

Mein systemd init-Skript übernimmt also die Sicherung der Datenbank in einem Archiv auf dem Host. Ich habe einen Zeitstempel in den Dateinamen eingefügt, um eine Datei nie neu zu schreiben.

Es macht es auf dem ExecStartPre:

ExecStartPre=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStartPre=-/bin/bash -c '/usr/bin/tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStartPre.tar.gz /home/core/sql/mysql --remove-files'

Und das Gleiche gilt auch für ExecStopPost:

ExecStopPost=-/usr/bin/docker cp lanti-debian-mariadb:/var/lib/mysql /home/core/sql
ExecStopPost=-/bin/bash -c 'tar -zcvf /home/core/sql/sqlbackup_$$(date +%%Y-%%m-%%d_%%H-%%M-%%S)_ExecStopPost.tar.gz /home/core/sql/mysql --remove-files'

Außerdem habe ich einen Ordner vom Host als Volume genau an derselben Stelle verfügbar gemacht, an der die Datenbank gespeichert ist:

mariadb:
  build: ./mariadb
  volumes:
    - $HOME/server/mysql/:/var/lib/mysql/:rw

Es funktioniert hervorragend auf meiner VM (ich erstelle einen LEMP-Stack für mich selbst): https://github.com/DJviolin/LEMP

Aber ich weiß nur nicht, ob es sich um eine "kugelsichere" Lösung handelt, wenn Ihr Leben tatsächlich davon abhängt (z. B. Webshop mit Transaktionen in möglichen Millisekunden).

20 Minuten und 20 Sekunden nach diesem offiziellen Docker-Keynote-Video macht der Moderator dasselbe mit der Datenbank:

Erste Schritte mit Docker

"Für die Datenbank haben wir ein Volume, sodass wir sicherstellen können, dass beim Auf- und Absteigen der Datenbank keine Daten verloren gehen, wenn der Datenbankcontainer gestoppt wird."

Lanti
quelle
Was meinst du mit "... benutze ..." ? Und "... Transaktionen in möglichen Millisekunden" ?
Peter Mortensen
0

Verwenden Sie Persistent Volume Claim (PVC) von Kubernetes, einem Tool zur Verwaltung und Planung von Docker-Containern:

Dauerhafte Volumes

Die Verwendung von Kubernetes für diesen Zweck bietet folgende Vorteile:

  • Sie können jeden Speicher wie NFS oder einen anderen Speicher verwenden, und selbst wenn der Knoten ausgefallen ist, muss der Speicher nicht vorhanden sein.
  • Darüber hinaus können die Daten in solchen Volumes so konfiguriert werden, dass sie auch nach der Zerstörung des Containers selbst erhalten bleiben - so dass sie bei Bedarf von einem anderen Container zurückgefordert werden können.
Santanu Dey
quelle