Ich verliere meine Daten, wenn der Container beendet wird

394

Trotz des interaktiven Tutorials und der FAQ von Docker verliere ich meine Daten, wenn der Container beendet wird.

Ich habe Docker wie hier beschrieben installiert: http://docs.docker.io/en/latest/installation/ubuntulinux ohne Probleme unter Ubuntu 13.04.

Beim Beenden gehen jedoch alle Daten verloren.

iman@test:~$ sudo docker version
Client version: 0.6.4 
Go version (client): go1.1.2 
Git commit (client): 2f74b1c 
Server version: 0.6.4 
Git commit (server): 2f74b1c 
Go version (server): go1.1.2 
Last stable version: 0.6.4 


iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:05:47 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu apt-get install ping
Reading package lists... 
Building dependency tree... 
The following NEW packages will be installed: 
  iputils-ping 
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. 
Need to get 56.1 kB of archives. 
After this operation, 143 kB of additional disk space will be used. 
Get:1 http://archive.ubuntu.com/ubuntu/ precise/main iputils-ping amd64 3:20101006-1ubuntu1 [56.1 kB] 
debconf: delaying package configuration, since apt-utils is not installed 
Fetched 56.1 kB in 0s (195 kB/s) 
Selecting previously unselected package iputils-ping. 
(Reading database ... 7545 files and directories currently installed.) 
Unpacking iputils-ping (from .../iputils-ping_3%3a20101006-1ubuntu1_amd64.deb) ... 
Setting up iputils-ping (3:20101006-1ubuntu1) ... 
iman@test:~$ sudo docker run ubuntu ping
2013/10/25 08:06:11 Unable to locate ping 
iman@test:~$ sudo docker run ubuntu touch /home/test
iman@test:~$ sudo docker run ubuntu ls /home/test
ls: cannot access /home/test: No such file or directory 

Ich habe es auch mit interaktiven Sitzungen mit dem gleichen Ergebnis getestet. Habe ich etwas vergessen

EDIT: WICHTIG FÜR NEUE DOCKER-BENUTZER

Als @ mohammed-Noureldin und andere sagten, eigentlich ist das nicht ein verlass Behälter . Jedes Mal wird nur ein neuer Container erstellt.

Iman
quelle
10
Das kann nicht als " Container-Exiting " bezeichnet werden. Sie erstellen lediglich einen neuen Container. Die Verwendung von Exiting-Wörtern kann sehr verwirrend sein (ich war auch deswegen verwirrt).
Mohammed Noureldin
1
@MohammedNoureldin, du hast recht, das Verlassen ist nicht korrekt, aber genau das haben du, ich und andere gedacht. Es ist also ein besseres fragliches Wort, Ihre Bearbeitung macht Frage zu einer Antwort! Neue Suchende finden hier nicht!
Iman
Zu Beginn von Docker dachte ich, dass ich aufgrund IHRER Frage finde, dass die Adresse einfach FALSCH ist. Der neue Titel wurde überprüft und akzeptiert. Ich verstehe nicht, warum jemand auf einem falschen Titel bestehen sollte. Es ist Ihre Frage und Ihre Entscheidung.
Mohammed Noureldin
3
Ich stimme @MohammedNoureldin zu. Die Kombination aus Titel, Beispiel und akzeptierter Antwort hilft zukünftigen Lesern und insbesondere Anfängern nicht zu verstehen Docker. Ich würde vorschlagen, den Titel und die ursprüngliche Frage beizubehalten, da Anfänger definitiv nach so etwas suchen werden. Aber warum fügst du nicht etwas hinzu, das deine Missverständnisse zum Zeitpunkt des Schreibens des Beitrags beschreibt? Es wird helfen, die Dinge klar zu machen. Das ist unsere Kultur hier bei SO ... nicht wahr? :-)
Tgogos
2
Ich hatte dieses Problem ... jedes Mal, wenn Sie beenden, müssen Sie Ihren Container starten, nicht ausführen ... ein Image ausführen, um einen neuen Container zu erstellen. Dies hilft Docker beim Starten von <Container-ID> Docker-
Attach

Antworten:

399

Sie müssen sich verpflichten , die Änderungen an dem Container zu machen und führen Sie es dann. Versuche dies:

sudo docker pull ubuntu

sudo docker run ubuntu apt-get install -y ping

Rufen Sie dann die Container-ID mit diesem Befehl ab:

sudo docker ps -l

Änderungen am Container festschreiben:

sudo docker commit <container_id> iman/ping 

Führen Sie dann den Container aus:

sudo docker run iman/ping ping www.google.com

Das sollte funktionieren.

Unferth
quelle
9
Daher sollte ich nach jedem Lauf Commit verwenden , um Daten zu erhalten.
Iman
5
Commit sollte nur verwendet werden, wenn Sie Änderungen am Container vornehmen (z. B. beim Installieren neuer Tools oder Daten), damit diese Änderungen gespeichert werden. Wenn Sie das nächste Mal einen neuen Container von diesem Image aus ausführen, beginnt er am Punkt des letzten Speicherns oder festschreiben, Ihre Daten erhalten.
Unferth
7
@Unferth was ist, wenn ich weiterhin Änderungen vornehmen möchte? Bisher werden mehr Bilder mit erstellt <none>. Wie füge ich das Commit weiterhin an ein vorhandenes Image an?
Marconi
62
Das inkrementelle Festschreiben von Änderungen ist nicht "der Docker-Weg". Verwenden Sie eine DOCKERFILE.
user2105103
23
Wie würden Sie sich aus dem Container heraus verpflichten? Stellen Sie sich das folgende Szenario vor: 1) Ich führe den Container folgendermaßen aus: docker run -i -t myimage / bin / bash 2) Ich nehme einige Änderungen vor 3) Ich kann nicht aus dem Container heraus festschreiben. Wenn ich also den Container verlasse, habe ich Ich werde alle meine Daten verlieren, ohne die Möglichkeit zu haben, meine vorherigen Änderungen zu übernehmen
qgicup
374

Wenn Sie docker runeinen Container starten, wird tatsächlich ein neuer Container basierend auf dem von Ihnen angegebenen Image erstellt.

Beachten Sie neben den anderen nützlichen Antworten hier, dass Sie einen vorhandenen Container nach dem Beenden neu starten können und Ihre Änderungen noch vorhanden sind.

docker start f357e2faab77 # restart it in the background
docker attach f357e2faab77 # reattach the terminal & stdin
ZeissS
quelle
88
docker pszeigt an, dass nur Docker-Container ausgeführt werden. docker ps -azeigt Ihnen auch diejenigen, die beendet wurden - und die Sie weiterlaufen können. Ein Commit ist nur nach jedem Lauf erforderlich, wenn Sie dort einen Snapshot für die zukünftige Verwendung erstellen möchten. Andernfalls bleibt der Container selbst erhalten, damit Sie ihn weiterhin verwenden können.
user1278519
2
Frage bitte, wenn ich also einen jenkinsServer-Docker herunterlade und ihn auf meinem CI-Host ausführe und einige meiner Jobs ausführt, schreibt der Jenkins-Server einige Protokolle auf die Festplatte. Wenn nun mein Server (der mein Docker gehostet hat) neu gestartet wird und ich meinen Jenkins-Docker erneut starte, würde dies bedeuten, dass ich alle Protokolldateien verloren habe? Wenn dem so ist, wie kann ich jenkinsDocker beispielsweise verwenden, um meine Jenkins-Installation auf CI zu vereinfachen?
Jas
2
@Jas Wenn Sie sich an denselben Container halten und keine neuen erstellen, gibt es keine Probleme. Docker verfügt heutzutage über Neustartrichtlinien, sodass Sie es so konfigurieren können, dass beim Neustart des Computers derselbe Container neu gestartet wird. Ich würde Ihnen auch raten, Ihre Jenkins nach Hause in ein Volume zu legen, um von außen darauf zugreifen zu können (Backups usw.).
ZeissS
7
Hier ist eine praktische Möglichkeit, Dateien nach dem Beenden aus dem Container zu kopieren:docker cp $(docker ps -alq):/path/to/file .
Josh Habdas
3
Sie können einen Container auch anhand seines Namens starten und anhängen. (zB docker run -it --name my_debian debianund danach docker start my_debian && docker attach my_debian)
Johnny Willer
128

Es gibt folgende Möglichkeiten, Containerdaten beizubehalten:

  1. Docker-Volumes

  2. Docker-Commit

    a) Erstellen Sie einen Container aus dem Ubuntu-Image und führen Sie ein Bash-Terminal aus.

       $ docker run -i -t ubuntu:14.04 /bin/bash
    

    b) Installieren Sie die Locke im Terminal

       # apt-get update
       # apt-get install curl
    

    c) Verlassen Sie das Containerterminal

       # exit
    

    d) Notieren Sie sich Ihre Container-ID, indem Sie den folgenden Befehl ausführen:

       $ docker ps -a
    

    e) Speichern Sie den Container als neues Bild

       $ docker commit <container_id> new_image_name:tag_name(optional)
    

    f) Vergewissern Sie sich, dass Sie Ihr neues Bild mit installierter Locke sehen können.

       $ docker images           
    
       $ docker run -it new_image_name:tag_name bash
          # which curl
            /usr/bin/curl
    
kalyani chaudhari
quelle
Ist es notwendig, exitvorher docker commit? Vielen Dank.
Abhishek Anand
2
@AbhishekAnand ja, denn mit dem docker runBefehl führen Sie bash im Container aus und bleiben dort aufgrund der Optionen -iund -t(interaktiv mit TTY). Docker wird jedoch auf Ihrem Computer außerhalb des Containers ausgeführt. Nachdem Sie die erforderlichen Änderungen am Container von innen vorgenommen haben, müssen Sie die Shell exitdes Containers (oder Strg + D) verwenden, um zur Shell Ihres Systems zurückzukehren . Beachten Sie auch das #und $in der Antwort, die die verschiedenen Shells angeben, in die die Befehle geschrieben werden.
Erik
Kurze Frage: Wenn ich nicht festschreibe, habe ich die Daten verloren. Es ist klar. Aber wenn ich die Nginx-Konfiguration ändere, warum bleibt sie dann aktualisiert? (keine Notwendigkeit zu verpflichten) @Erik
grep
@grep Wenn Sie eine klare und reproduzierbare MWE haben, stellen Sie bitte eine neue Frage, falls es noch keine zu diesem speziellen Anwendungsfall gibt.
Erik
3. docker stopgefolgt von docker start.
Glockenspiel
59

Zusätzlich zur Antwort von Unferth wird empfohlen, eine Docker-Datei zu erstellen .

Erstellen Sie in einem leeren Verzeichnis eine Datei mit dem Namen "Dockerfile" mit dem folgenden Inhalt.

FROM ubuntu
RUN apt-get install ping
ENTRYPOINT ["ping"]

Erstellen Sie ein Bild mit der Docker-Datei . Verwenden wir ein Tag, damit wir uns nicht die hexadezimale Bildnummer merken müssen.

$ docker build -t iman/ping .

Und dann das Bild läuft in einem Behälter.

$ docker run iman/ping stackoverflow.com
salathe
quelle
1
Nie mehr als einmal manuell machen zu müssen, ist genau das, worum es bei Docker geht. Erstellen Sie eine Docker-Datei, schreiben Sie das resultierende Bild fest und laden Sie es hoch. Ziehen Sie das Bild nach vorne.
Brandon Bertelsen
11

Ich habe eine viel einfachere Antwort auf Ihre Frage. Führen Sie die folgenden zwei Befehle aus

sudo docker run -t -d ubuntu --name mycontainername /bin/bash
sudo docker ps -a

Der obige Befehl ps -a gibt eine Liste aller Container zurück. Nehmen Sie den Namen des Containers, der auf den Bildnamen verweist - 'ubuntu'. Docker generiert automatisch Namen für die Container, z. B. 'lightlyxuyzx'wenn Sie die Option --name nicht verwenden.

Die Optionen -t und -d sind wichtig. Der erstellte Container wird getrennt und kann wie unten angegeben mit der Option -t erneut verbunden werden.

Mit der Option --name können Sie Ihren Container in meinem Fall 'mycontainername' benennen.

sudo docker exec -ti mycontainername bash

Mit diesem Befehl können Sie sich mit der Bash-Shell beim Container anmelden. Ab diesem Zeitpunkt werden alle Änderungen, die Sie am Container vornehmen, automatisch vom Docker gespeichert. Zum Beispiel - apt-get install curlinnerhalb des Containers Sie können den Container ohne Probleme verlassen. Docker speichert die Änderungen automatisch.

Bei der nächsten Verwendung müssen Sie diese beiden Befehle nur jedes Mal ausführen, wenn Sie mit diesem Container arbeiten möchten.

Dieser Befehl unten startet den gestoppten Container:

sudo docker start mycontainername

sudo docker exec -ti mycontainername bash

Ein weiteres Beispiel mit Ports und einem gemeinsam genutzten Speicherplatz:

docker run -t -d --name mycontainername -p 5000:5000 -v ~/PROJECTS/SPACE:/PROJECTSPACE 7efe2989e877 /bin/bash

In meinem Fall: 7efe2989e877 - ist die Image-ID eines vorherigen Containers, den ich mit erhalten habe

Docker ps -a

Magnus Melwin
quelle
4
Mit Docker 18.09.2 unter Ubuntu 18.04 funktioniert es nicht so wie es ist. Es funktioniert, wenn ich die --nameOption und vor den docker run --name mycontainername -t -d ubuntu /bin/bash
Bildnamen setze
9

Möglicherweise möchten Sie Docker-Volumes anzeigen, wenn Sie die Daten in Ihrem Container beibehalten möchten. Besuchen Sie https://docs.docker.com/engine/tutorials/dockervolumes/ . Die Docker-Dokumentation ist ein sehr guter Anfang

Kudzanayi Mutamba
quelle
3

Mein Vorschlag ist, Docker mit Docker Compose zu verwalten. Ist eine einfache Möglichkeit, alle Docker-Container für Ihr Projekt zu verwalten. Sie können die Versionen zuordnen und verschiedene Container verknüpfen, um zusammenzuarbeiten.

Die Dokumente sind sehr einfach zu verstehen, besser als die Dokumente von Docker.

Docker-Compose Docs

Beste

Cam T.
quelle
3

Es gibt wirklich gute Antworten auf die gestellte Frage. Möglicherweise ist keine weitere Antwort erforderlich, dennoch möchte ich meine persönliche Meinung zu diesem Thema in möglichst einfachen Worten abgeben.

Hier sind einige Punkte zu Containern und Bildern, die uns zu einer Schlussfolgerung verhelfen:

  • Ein Docker-Image kann sein :
    1. erstellt aus einem bestimmten Container
    2. gelöscht
    3. verwendet, um eine beliebige Anzahl von Containern zu erstellen
  • Ein Docker-Container kann sein :
    1. aus einem Bild erstellt
    2. gestartet
    3. gestoppt
    4. neu gestartet
    5. gelöscht
    6. verwendet, um eine beliebige Anzahl von Bildern zu erstellen
  • Ein Docker-Ausführungsbefehl führt Folgendes aus :
    1. Lädt ein Bild herunter oder verwendet ein zwischengespeichertes Bild
    2. Erstellt daraus einen neuen Container
    3. Startet den Container
  • Wenn eine Docker-Datei zum Erstellen eines Bildes verwendet wird :
    1. Es ist bereits bekannt, dass das Image schließlich zum Ausführen eines Docker-Containers verwendet wird.
    2. Nach der Ausgabe des Docker-Build-Befehls erstellt Docker hinter den Kulissen einen laufenden Container mit einem Basisdateisystem und führt die Schritte in der Docker-Datei aus, um diesen Container gemäß den Anforderungen der Entwickler zu konfigurieren.
    3. Nachdem der Container mit den Spezifikationen der Docker-Datei konfiguriert wurde, wird er als Image festgeschrieben.
    4. Das Bild macht sich bereit zum Rock & Roll!

Fazit :

Wie wir sehen können, ist ein Docker-Container unabhängig von einem Docker-Image.

Ein Container kann neu gestartet werden, sofern die eindeutige ID dieses Containers [ docker ps --allzum Abrufen der ID] verwendet wird .

Alle Vorgänge wie das Erstellen eines neuen Verzeichnisses, das Erstellen von Dateien, das Installieren von Tools usw. können während der Ausführung im Container ausgeführt werden. Sobald der Container gestoppt ist, werden alle Änderungen beibehalten. Das Stoppen und Neustarten von Containern ist wie ein Neustart eines Computersystems.

Ein bereits erstellter Container ist immer für einen Neustart verfügbar. Wenn wir jedoch einen docker runBefehl ausgeben , wird ein neuer Container aus einem Image erstellt und ähnelt daher einem neuen Computersystem. Die im alten Container vorgenommenen Änderungen sind - wie wir jetzt verstehen können - in diesem neuen Container nicht verfügbar.

Ein letzter Hinweis :

Ich denke, es ist jetzt offensichtlich, warum die Daten verloren zu sein scheinen, aber sie sind immer da. Aber in einem anderen [alten] Container. Beachten Sie also den Unterschied in docker start& docker runcommand und lassen Sie sich nie verwirren.

kiran dahibhate
quelle
1

Das ähnliche Problem (und Dockerfile allein konnte es auf keinen Fall beheben) brachte mich auf diese Seite.

Stufe 0: In der Hoffnung, dass Dockerfile das Problem beheben kann: Bis --dns und --dns-search in der Dockerfile-Unterstützung angezeigt werden, gibt es keine Möglichkeit, intranetbasierte Ressourcen in zu integrieren.

Stufe 1: Nachdem Sie ein Image mit Dockerfile erstellt haben (übrigens ist es ein schwerwiegender Fehler , dass sich Dockerfile im aktuellen Ordner befindet), müssen Sie ein Image haben, um das Intranet-basierte bereitzustellen , indem Sie das Docker-Run-Skript ausführen. Beispiel: docker run -d \ --dns=${DNSLOCAL} \ --dns=${DNSGLOBAL} \ --dns-search=intranet \ -t pack/bsp \ --name packbsp-cont \ bash -c " \ wget -r --no-parent http://intranet/intranet-content.tar.gz \ tar -xvf intranet-content.tar.gz \ sudo -u ${USERNAME} bash --norc"

Stufe 2: Anwenden eines Docker-Ausführungsskripts im Dämonmodus , der lokale DNS-Datensätze bereitstellt, damit lokale Inhalte heruntergeladen und bereitgestellt werden können.

Wichtiger Punkt: Das Ausführungsskript sollte mit etwas enden /usr/bin/sudo -u ${USERNAME} bash --norc, das den Container auch nach Abschluss der Installationsskripte am Laufen hält.

Nein , es ist nicht möglich, den Container für die gesamte Automatisierung im interaktiven Modus auszuführen, da er innerhalb der internen Eingabeaufforderung verbleibt, bis STRG-p STRG-q gedrückt wird.

Nein , wenn die interaktive Bash am Ende des Installationsskripts nicht ausgeführt wird, wird der Container sofort nach Abschluss der Skriptausführung beendet, wodurch alle Installationsergebnisse verloren gehen.

Stufe 3: Der Container wird noch im Hintergrund ausgeführt, es ist jedoch unklar, ob der Container den Installationsvorgang beendet hat oder nicht. Verwenden Sie den folgenden Block, um festzustellen, ob while ! docker container top ${CONTNAME} | grep "00[[:space:]]\{12\}bash \--norc" - do echo "." sleep 5 done die Ausführung abgeschlossen ist: Das Skript wird erst nach Abschluss der Installation fortgesetzt. und dies ist der richtige Zeitpunkt, um Folgendes aufzurufen: Festschreiben , wobei die aktuelle Container-ID sowie der Name des Zielabbilds angegeben werden (möglicherweise identisch mit der Build / Run- Prozedur, jedoch mit dem Tag für lokale Installationszwecke versehen. Beispiel : docker commit containerID pack/bsp:toolchained. Siehe diesen Link unter wie man die richtige containerID bekommt

Stufe 4: Der Container wurde mit den lokalen Installationen aktualisiert und in ein neu zugewiesenes Image übertragen (das mit dem Zweck-Tag hinzugefügt wurde). Es ist jetzt sicher, den Containerlauf zu stoppen. Beispiel:docker stop packbsp-cont

Stufe 5: Starten Sie den Container mit lokalen Installationen jederzeit mit dem zuvor gespeicherten Image. Beispiel:docker run -d -t pack/bsp:toolchained

Oleg Kokorin
quelle
1

eine brillante Antwort hier Wie man einen Docker fortsetzt, der vom Benutzer kgs verlassen wird

docker start $(docker ps -a -q --filter "status=exited")
(or in this case just docker start $(docker ps -ql) 'cos you don't want to start all of them)

docker exec -it <container-id> /bin/bash

Diese zweite Zeile ist entscheidend. Exec wird also anstelle von run verwendet und nicht für ein Image, sondern für eine Container-ID. Und Sie tun es, nachdem der Container gestartet wurde.

Barlop
quelle
0

Keine der Antworten spricht den Punkt dieser Designauswahl an. Ich denke, Docker funktioniert auf diese Weise, um diese beiden Fehler zu vermeiden:

  • Wiederholter Neustart
  • Teilfehler
Minh Nghĩa
quelle