Wie kann ich eine Docker-Container-Initialisierung debuggen?

93

Ich hatte ein Problem mit einem Container, obwohl er perfekt aufgebaut ist, startet er nicht richtig. Die Ursache ist eine Problemumgehung, die ich der Docker-Datei hinzugefügt habe (für ein selbstkonfiguriertes / etc / hosts-Routing).

RUN mkdir -p -- /lib-override /etc-override && cp /lib/libnss_files.so.2 /lib-override
ADD hosts.template /etc-override/hosts
RUN perl -pi -e 's:/etc/hosts:/etc-override/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override

Offensichtlich ist da ein Fehler, aber ich frage mich, wie ich mehr Informationen darüber bekommen kann, was Docker während des Betriebs macht. Das funktioniert zum Beispiel:

$ docker run image ls
usr bin ...

Das tut es aber nicht:

$ docker run image ls -l
$

Die Protokolle enthalten nichts und ich kann auch keine interaktive Shell aufrufen. Ich kann strace benutzen, um zu sehen, was passiert, aber ich hatte gehofft, dass es einen besseren Weg gibt.

Kann ich den Docker so einstellen, dass er ausführlicher ist?

EDIT : Dank Andrew D. weiß ich jetzt, was mit dem obigen Code falsch ist (ich habe ihn verlassen, damit seine Antwort verstanden werden kann). Jetzt ist die Frage noch, wie ich so etwas debuggen oder ein paar Einblicke in die Gründe bekommen kann, warum ls -l versagt hat, warum ls nicht.

EDIT : Die -D = true könnte mehr Ausgabe geben, aber nicht in meinem Fall ...

estani
quelle
Bitte bemühen Sie sich, eine der Antworten als "akzeptiert" zu markieren, danke!
Brian Topping

Antworten:

95

Der Docker- eventsBefehl kann hilfreich sein, und der Docker-Protokollbefehl kann Protokolle auch dann abrufen, wenn das Image nicht gestartet werden konnte.

Beginnen Sie zuerst docker eventsim Hintergrund, um zu sehen, was los ist.

docker events&

Führen Sie dann Ihren fehlgeschlagenen docker run ...Befehl aus. Dann sollte auf dem Bildschirm etwa Folgendes angezeigt werden:

2015-12-22T15:13:05.503402713+02:00 xxxxxxxacd8ca86df9eac5fd5466884c0b42a06293ccff0b5101b5987f5da07d: (from xxx/xxx:latest) die

Anschließend können Sie die Start-Hex-ID aus der vorherigen Nachricht oder der Ausgabe des Ausführungsbefehls abrufen. Dann können Sie es mit dem Befehl logs verwenden:

docker logs <copy the instance id from docker events messages on screen>

Sie sollten nun eine Ausgabe des fehlgeschlagenen Abbildstarts sehen.

Wie @alexkb in einem Kommentar vorgeschlagen hat: docker events&Kann problematisch sein, wenn Ihr Container ständig von so etwas wie dem AWS ECS-Service aus neu gestartet wird. In diesem Szenario ist es möglicherweise einfacher, die Container-Hex-ID aus den Anmeldungen abzurufen /var/log/ecs/ecs-agent.log.<DATE>. Dann benutze Docker logs <hex id>.

Peter Lamberg
quelle
Sehr hilfreich! Neu in Docker und versuchte, Portainer zum Laufen zu bringen. Behebt es mit diesen Debugging-Schritten. Gefunden jemand auf Medium.com mit dem gleichen Problem: medium.com/@jameson_37151/…
Jameson
Ich bekomme "Container nicht gefunden" !?
Demented Hedgehog
Seltsam. Um sicherzugehen, @dementedhedgehog, haben Sie versucht, die Hex-ID aus der Protokollmeldung zu kopieren, die mit " (from xxx/xxx:latest) die" endet .
Peter Lamberg
1
Vielen Dank für diese Antwort, es ist ein Lebensretter. Das Einzige, was Sie hinzufügen müssen, ist, dass docker events&dies problematisch sein kann, wenn Ihr Container ständig von so etwas wie dem AWS ECS-Service neu gestartet wird. In diesem Szenario ist es möglicherweise einfacher, die Container-Hex-ID aus den Anmeldungen zu entfernen /var/log/ecs/ecs-agent.log.<DATE>. Verwenden Sie dann, docker logs <hex id>wie in dieser Antwort vorgeschlagen, um festzustellen, warum die Dinge nicht gestartet werden.
Alexkb
1
@alexkb Danke! Ich habe Ihren Vorschlag am Ende der Antwort hinzugefügt, damit andere ihn leichter finden.
Peter Lamberg
18

Das Beste, was ich bisher herausgefunden habe, ist:

#stop the current demon and start it in debug modus
sudo service docker stop
dockerd -D # --debug

Starten Sie den Client einfach von einer neuen Shell aus. Die falsche Vorstellung war, dass der Client überhaupt irgendetwas tut ... nun, er kommuniziert nur mit dem Dämon, also möchten Sie nicht den Client debuggen, sondern den Dämon selbst (normalerweise).

estani
quelle
13

In meinem Fall war das -aFlag (an STDOUT / STDERR anhängen) ausreichend:

user@machine:~$ docker start -a server_name
Error: The directory named as part of the path /log/log_path/app.log does not exist.
For help, use /usr/bin/supervisord -h

Es wurde der Startfehler angezeigt (in unserem Fall ein fehlender Protokollpfad von supervisord). Ich gehe davon aus, dass die meisten Container-Startfehler auch hier auftreten würden.

Claytond
quelle
3

Ich kann Ihre Frage zur Vervollständigung der Docker-Ausgabe nicht beantworten, aber ich kann Ihnen sagen, dass das direkte Ersetzen einer Zeichenfolge in einer .so-Datei etwas verrückt ist: Der Zeichenfolge ist nur so viel Speicherplatz zugewiesen, und Wenn Sie die Datei-Offsets anderer Einträge ändern, wird die Elf-Datei beschädigt. Versuchen Sie, objdump oder readelf für Ihre .so-Datei auszuführen, nachdem Sie den Perl-Befehl ( vor der Änderung von LD_LIBRARY_PATH ) außerhalb eines Containers ausgeführt haben. Dollar zu Donuts sind jetzt beschädigt.

Der Grund, warum es in diesem leider notwendigen Hack funktioniert, ist, dass "tmp" und "etc" dieselbe String-Länge haben, sodass sich keine Offsets ändern. Betrachten Sie das Verzeichnis / dkr oder ähnliches, wenn Sie / tmp nicht verwenden möchten.

Wenn Sie diesen Ansatz MÜSSEN und Ihre gewünschten Pfade unveränderlich sind, erstellen Sie die Bibliothek neu und ändern Sie den Standardpfad für / etc / hosts in der Quelle. Oder besser, wenn den Aufbau Ihrer modifizierten libnss_files.soes um etwas umbenennen wie libnss_altfiles.sound ändern nsswitch.confzu verwenden , hosts: altfileswenn Ihr Docker Container beginnen (es sei denn , Docker binden als auch montiert nsswitch.conf, dann können Sie es nicht ändern). Auf diese Weise können Sie die Datei libnss_altfiles.so parallel zu Ihren normalen Bibliotheken im Basissystem verwenden. Wenn Docker die Datei nsswitch.conf bindet, belassen Sie eine Kopie der neu erstellten Datei libnss_files.so in Ihrem Verzeichnis / lib-override, damit sie von LD_LIBRARY_PATH geladen werden kann.

Als Heads-up ignorieren suid / sgid-Binärdateien LD_LIBRARY_PATH und LD_PRELOAD, so dass einige Dinge kaputt gehen (lesen Sie: Verwenden Sie wieder die Standarddatei / etc / hosts), wenn Sie diese Variablen verwenden.

Andrew Domaszek
quelle
Vielen Dank für den tollen Einblick ... Ich war zu schnell und sehe jetzt, was passiert. Ich weiß immer noch nicht, warum die Statistik einen Host (ls -l) auflösen muss, während die einfache Dateiliste (ls) nicht ...
estani
0

Manchmal können Sie nützliche Fehlermeldungen finden, indem Sie in den Knoten sshing, auf dem der Docker-Daemon ausgeführt wird, und dann Folgendes ausführen:

$ tail -f /var/log/containers/* /var/log/docker.log 2>&1

Unter 'Docker Community Edition' unter Mac OS können Sie eine Verbindung zum Docker VM herstellen, indem Sie folgende Schritte ausführen:

$  screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
user674669
quelle