So bearbeiten Sie Dateien im gestoppten / nicht gestarteten Docker-Container

90

Beim Versuch, Fehler zu beheben und Probleme mit meiner Anwendung zu debuggen, die auf mehrere Container aufgeteilt ist, bearbeite ich häufig Dateien in Containern:

  • entweder bin ich total faul und installiere nano und bearbeite direkt im container oder

  • Ich docke die Datei aus dem Container, bearbeite sie, kopiere sie zurück und starte den Container neu

Dies sind Zwischenschritte, bevor neue Inhalte für die Containererstellung erstellt werden. Dies dauert viel länger als die oben genannten Schritte (was natürlich nur Zwischenschritte sind).

Jetzt breche ich häufig das Startprogramm des Containers, das in den fehlerhaften Fällen entweder ein Knotenskript oder ein Python-Webserver-Skript ist. Beide schlagen normalerweise aufgrund von Syntaxfehlern fehl.

Gibt es eine Möglichkeit, diese Container zu speichern? Da sie nicht starten, kann ich sie nicht andocken, und daher sind sie für mich verloren. Ich gehe dann die Route rm / rmi / build / run, nachdem ich die fehlerhafte Datei in der Build-Eingabe korrigiert habe.

Wie kann ich entweder Dateien in einem gestoppten Container bearbeiten oder sie kopieren oder eine Shell in einem gestoppten Container starten - alles, was mir erlaubt, diesen Container zu reparieren?

(Es scheint ein bisschen so, als würde man an einem Remotecomputer arbeiten und die Netzwerkkonfiguration unterbrechen. Auf diese Weise wird die Verbindung "für immer" unterbrochen, und man muss einen Fallback verwenden, falls vorhanden.)

Wie bearbeite ich Docker-Container-Dateien vom Host aus? sieht relevant aus, ist aber veraltet.

Andreas Reiff
quelle
Dies könnte auch eine Problemumgehung sein. Stackoverflow.com/a/32353134/586754 - in der Hoffnung auf eine noch bessere Lösung.
Andreas Reiff
1
Vielleicht sollten Sie ein Volume bereitstellen, damit Sie Dateien auf Ihrem Host anstatt im Container bearbeiten können. Sobald Sie mit Ihrem Code zufrieden sind, können Sie docker cpdie Dateien im Container
freigeben
Ja, das wäre allerdings etwas spät, wenn ich die Dinge nicht von Anfang an so eingerichtet hätte. Das funktioniert nicht für die Wiederherstellung, denke ich.
Andreas Reiff
Viele Leser möchten nur Dateien anzeigen , anstatt sie zu bearbeiten. In diesen Fällen können Sie den docker commitBefehl verwenden, um ein neues Bild zu brechen. name=$(docker commit); docker run -it $name /bin/shwird tun was du willst.
Att Righ
so scheint es, dass die Dateisysteme von gestoppten Containern am Ende relativ permanent sind?
Webwoman

Antworten:

126

Ich hatte ein Problem mit einem Container, der aufgrund einer fehlerhaften Konfigurationsänderung nicht gestartet werden konnte. Ich konnte die Datei aus dem gestoppten Container kopieren und bearbeiten. etwas wie:

docker cp docker_web_1:/etc/apache2/sites-enabled/apache2.conf .

(korrigiere die Datei)

docker cp apache.conf docker_web_1:/etc/apache2/sites-enabled/apache2.conf
Tomurie
quelle
22
Dies sollte die akzeptierte Antwort sein. Aus irgendeinem Grund dachte ich nicht, dass CP an gestoppten Containern arbeitet. Nett!
Proximo
Perfekt. Ich habe eine Datei aus dem Container kopiert (ich kannte ihren Pfad) und sie dann bearbeitet und dann an denselben Speicherort zurück in den Container kopiert. Hat für mich gearbeitet! Vielen Dank!
Nawaz
Gibt es eine Möglichkeit, eine Datei zu entfernen?
Kodlan
1
@kodlan Nur wenn es nur in dem angezeigt wird, von dem UpperDirSie erhalten, müssen docker container inspectSie experimentieren, um zu sehen, wie das Overlay-System Dateien in der zugrunde liegenden Struktur darstellt, die in der oberen Ebene gelöscht wurden.
Tim Baverstock
58

Beantwortung meiner eigenen Frage .. Ich hoffe immer noch auf eine bessere Antwort von einer sachkundigeren Person !!

Es gibt 2 Möglichkeiten.

1) Bearbeiten des Dateisystems auf dem Host direkt . Dies ist etwas gefährlich und kann den Container vollständig beschädigen, möglicherweise andere Daten, je nachdem, was schief geht.

2) Ändern Sie das Startskript in etwas, das niemals fehlschlägt, z. B. das Starten einer Bash, das Durchführen der Korrekturen / Änderungen und das erneute Ändern des Startprogramms auf das gewünschte (z. B. Knoten oder was auch immer zuvor).

Mehr Details:

1) Verwenden

docker ps

um die laufenden Container zu finden oder

docker ps -a

um alle Container (einschließlich angehaltener) zu finden und

docker inspect (containername)

Suchen Sie nach der "Id", einem der ersten Werte.

Dies ist der Teil, der Implementierungsdetails enthält und sich möglicherweise ändert. Beachten Sie, dass Sie Ihren Container auf diese Weise verlieren können.

Gehe zu

/var/lib/docker/aufs/diff/9bc343a9..(long container id)/

und dort finden Sie alle Dateien, die in Richtung des Bildes geändert wurden, auf dem der Container basiert. Sie können Dateien überschreiben, Dateien hinzufügen oder bearbeiten.

Auch dies würde ich nicht empfehlen.

2) Wie unter https://stackoverflow.com/a/32353134/586754 beschrieben , finden Sie die Konfiguration json config.json unter einem Pfad wie

/var/lib/docker/containers/9bc343a99..(long container id)/config.json

Dort können Sie die Argumente von zB "nodejs app.js" in "/ bin / bash" ändern. Starten Sie nun den Docker-Dienst neu und starten Sie den Container (Sie sollten sehen, dass er jetzt korrekt gestartet wird). Du solltest benutzen

docker start -i (containername)

um sicherzustellen, dass es nicht sofort beendet wird. Sie können jetzt mit dem Container arbeiten und / oder später mit anhängen

docker exec -ti (containername) /bin/bash

Docker cp ist auch sehr nützlich zum Kopieren von Dateien, die außerhalb des Containers bearbeitet wurden.

Außerdem sollte man nur dann auf diese Maßnahmen zurückgreifen, wenn der Container ohnehin mehr oder weniger "verloren" ist, so dass jede Änderung eine Verbesserung wäre.

Andreas Reiff
quelle
Ich hoffe immer noch auf eine bessere Antwort - also zögern Sie nicht, eine zu geben, ich werde auch das "ansered" -Tag verschieben.
Andreas Reiff
Ich habe den zweiten Weg benutzt und musste den Docker-Dienst neu starten, um das Überschreiben von config.jsonDateien jedes Mal zu erzwingen, wenn ich sie bearbeitete
Vitaly Isaev
2
Ich habe config.v2.json und jedes Mal, wenn ich den Zombie-Container starte, wird mein Path / EntryPoint-Update zurückgesetzt und stirbt erneut. Die Verwendung von "docker cp" zum Aktualisieren des Skripts "entrypoint.sh" zum Ausführen von "bash" hat das Problem behoben.
Curtis Yallop
@CurtisYallop Ich erlebe das Gleiche. Wie haben Sie es gelöst?
Brett McLain
1
@BrettMcLain Ich habe Docker CP verwendet, anstatt es auf dem Host zu bearbeiten. So: Suchen Sie den Speicherort des Einstiegspunktskripts: "Docker inspect container_name | grep Entry". Skript abrufen: "docker cp container_name: /entrypoint.sh ./". (Bearbeiten) Setzen Sie das Skript wieder in den Container: "docker cp entrypoint.sh container_name: /entrypoint.sh". Sie können den Einstiegspunkt dazu bringen, Bash auszuführen oder eine Schlafschleife auszuführen, z. B. "while :; do sleep 10; done". Die erste Skriptzeile muss "#! / Bin / bash" sein.
Curtis Yallop
8

Sie können das Container-Dateisystem direkt bearbeiten, aber ich weiß nicht, ob es eine gute Idee ist. Zuerst müssen Sie den Pfad des Verzeichnisses finden, das als Laufzeitstamm für den Container verwendet wird. Ausführen docker container inspect id/name. Suchen Sie nach dem SchlüsselUpperDir in der JSON-Ausgabe .

Das ist dein Verzeichnis.

Tejas Sarade
quelle
Das Verzeichnis wurde gefunden, aber es enthielt nicht alle Dateien.
Aioobe
Es ist OverlayFS, daher müssen sich Ihre Dateien in einem dieser Verzeichnisse befinden.
Tejas Sarade
0

Wenn Sie versuchen, einen gestoppten Container neu zu starten und den Container aufgrund einer Fehlkonfiguration ändern müssen, der Container jedoch nicht gestartet wird, können Sie die folgenden Schritte mit dem Befehl "docker cp" ausführen (ähnlich dem vorherigen Vorschlag). Mit diesem Verfahren können Sie Dateien entfernen und andere erforderliche Änderungen vornehmen. Mit etwas Glück können Sie viele der folgenden Schritte überspringen.

  1. Verwenden Sie Docker Inspect, um den Einstiegspunkt zu finden (in einigen Versionen Pfad genannt).
  2. Erstellen Sie einen Klon des Docker-Laufs using
  3. Geben Sie den Klon mit docker exec -ti bash ein (if * nix container)
  4. Suchen Sie den Speicherort der Einstiegspunktdatei, indem Sie den zu suchenden Klon durchsuchen
  5. Kopieren Sie das alte Einstiegspunktskript mit Docker cp: ./
  6. Ändern oder erstellen Sie beispielsweise ein neues Einstiegspunktskript

    #!/bin/bash tail -f /etc/hosts

  7. Stellen Sie sicher, dass das Skript über Ausführungsrechte verfügt
  8. Ersetzen Sie den alten Einstiegspunkt mit Docker cp ./:
  9. Starten Sie den alten Container mit start
  10. Wiederholen Sie die Schritte 6 bis 9 bis zum Start
  11. Behebung von Problemen im Container
  12. Stellen Sie den Einstiegspunkt bei Bedarf wieder her und wiederholen Sie die Schritte 6 bis 9 nach Bedarf
  13. Entfernen Sie bei Bedarf den Klon
user6830669
quelle