2014-09-10 7 views
71

Ich habe eine Reihe von Tutorials gesehen, die scheinbar dasselbe tun, was ich versuche, aber aus irgendeinem Grund werden meine Docker-Container beendet. Im Grunde stelle ich einen Web-Server und ein paar Dämonen in einem Docker-Container auf. Ich mache die letzten Teile davon durch ein Bash-Skript namens run-all.sh, dass ich durch CMD in meiner Dockerfile laufen. run-all.sh sieht wie folgt aus:Wie behalte Docker Container nach dem Starten von Diensten?

service supervisor start 
service nginx start 

Und ich es in meiner Dockerfile beginnen wie folgt:

CMD ["sh", "/root/credentialize_and_run.sh"] 

Ich kann sehen, dass die alle Dienste richtig starten, wenn ich die Dinge manuell ausführen (dh immer auf das Bild mit -i -t/bin/bash), und alles sieht so aus, als würde es korrekt ausgeführt, wenn ich das Bild ausführe, aber es wird beendet, sobald es meine Prozesse gestartet hat. Ich möchte, dass die Prozesse unbegrenzt laufen, und soweit ich weiß, muss der Container weiterlaufen, damit dies geschieht. Dennoch, wenn ich docker ps -a laufen, ich sehe:

➜ docker_test docker ps -a 
CONTAINER ID  IMAGE       COMMAND    CREATED    STATUS      PORTS    NAMES 
c7706edc4189  some_name/some_repo:blah "sh /root/run-all.sh 8 minutes ago  Exited (0) 8 minutes ago      grave_jones 

Was soll das? Warum ist es spannend? Ich weiß, ich könnte einfach eine While-Schleife am Ende meines Bash-Skripts einfügen, um weiterzumachen, aber was ist der richtige Weg, um zu verhindern, dass es beendet wird?

+1

setzen Sie die Ports der Services nach außen frei (-p-Option für Docker Run)? (Natürlich wird dies nicht verhindern, dass sie aussteigen) – ribamar

Antwort

27

Das ist nicht wirklich, wie Sie Ihre Docker-Container entwerfen sollten.

Beim Entwerfen eines Docker-Containers sollten Sie es so erstellen, dass nur ein Prozess ausgeführt wird (d. H. Sie sollten einen Container für Nginx und einen für Supervisord oder die App, die es ausführt); Außerdem sollte dieser Prozess im Vordergrund laufen.

Der Container wird "verlassen", wenn der Prozess selbst beendet wird (in Ihrem Fall ist dies Ihr Bash-Skript).


Wenn Sie jedoch wirklich Notwendigkeit (oder wollen) mehrere Service in Ihrem Docker Behälter laufen, sollten Sie von "Docker Base Image" beginnen, die runit als Pseudo-init-Prozess verwendet (runit wird online bleiben, während Nginx und Supervisor-Lauf), die im Vordergrund bleiben, während Ihre anderen Prozesse ihre Sache machen.

Sie haben umfangreiche Dokumente, so dass Sie in der Lage sein sollten zu erreichen, was Sie versuchen, relativ einfach zu tun.

+0

Kannst du erklären, warum ich nur einen Dienst laufen lassen sollte? Ich könnte Nginx zum Vorgesetzten hinzufügen, wenn nötig, aber nicht sicher, warum dies notwendig sein sollte. – Eli

+2

@Eli Die kurze Antwort ist, dass Docker so funktioniert. Docker führt nur einen Prozess (und seine untergeordneten Elemente) pro Container aus. Es wird empfohlen, dass dieser Prozess ein tatsächlicher Anwendungsprozess ist (damit Docker weiß, wenn es beendet wird), aber Sie können tatsächlich den Supervisor als diesen Prozess verwenden. Beachten Sie, dass Sie den Supervisor so konfigurieren müssen, dass er im Vordergrund läuft (d. H. Nicht daemonisiert), was über die Option "--nodaemon" geschieht. –

+0

Ich kann keine Dokumentation finden, die dazu ermutigt wird, nur einen Dienst irgendwo auszuführen, und es scheint seltsam. Was ist, wenn Sie zuerst die Anmeldeinformationen herunterladen oder einige Start-Skripts ausführen möchten, die zur Laufzeit ausgeführt werden müssen? Können Sie einen Link zu Ihrem Anspruch bereitstellen? – Eli

9

Vergewissern Sie sich, dass Sie daemon off; fügen Sie es mit CMD ["nginx", "-g", "daemon off;"] nach dem offiziellen nginx Bild

Dann wird die nginx.conf oder laufen verwenden folgende sowohl Supervisor als Service und nginx als Vordergrundprozess auszuführen, der den Behälter verhindern von

service supervisor start && nginx

in einigen Fällen Verlassen müssen Sie mehr als einen Prozess in Ihrem Behälter haben, so dass der Behälter zwingt genau ein Verfahren zu haben, wird nicht funktionieren und mehr Probleme bei der Bereitstellung erstellen können.

Sie müssen also die Kompromisse verstehen und Ihre Entscheidung entsprechend treffen.

33

Der Grund dafür ist, dass das Shell-Skript zuerst als PID 1 ausgeführt wird, und wenn das abgeschlossen ist, ist PID 1 nicht mehr vorhanden und Docker wird nur ausgeführt, während PID 1 ist.

Sie können Supervisor verwenden, um alles zu tun, wenn mit der „-n“ Flagge laufen wird ihm gesagt, nicht daemonize, so wird es als erster Prozess bleiben:

CMD ["/usr/bin/supervisord", "-n"] 

Und Ihre supervisord.conf:

Dann können Sie so viele andere Prozesse haben, wie Sie möchten, und der Supervisor wird den Neustart bei Bedarf übernehmen.

Auf diese Weise könnten Sie supervisord in Fällen verwenden, in denen Sie nginx und php5-fpm benötigen und es macht nicht viel Sinn, sie auseinander zu halten.

0

Ich habe das gleiche problem.You diesen Befehl versuchen: Docker Protokolle [Container]

Es wird Ihnen zeigen, warum der Behälter meinem Fall stop.In es zeigt: Permission verweigert

42

Ich hatte gerade das gleiche Problem und ich fand heraus, dass, wenn Sie Ihren Container mit dem -t und -d Flag laufen, es läuft weiter.

docker run -td <image> 

Hier ist, was die Fahnen tun (nach docker run --help):

-d, --detach=false   Run container in background and print container ID 
-t, --tty=false   Allocate a pseudo-TTY 

Der wichtigste der -t Flagge ist. -d lässt Sie den Container einfach im Hintergrund ausführen.

+1

Ich kann das nicht reproduzieren. Würden Sie bitte ein Beispiel geben? Gibt es etwas Spezifisches (z. B. CMD) über Dockerfile, das wir brauchen, damit dies funktioniert? –

+1

Das hat nicht für mich funktioniert. Ich habe den Befehl 'docker logs ' verwendet, um sicherzustellen, dass es sich um einen Fehler handelt, der dazu führt, dass mein Docker-Container beendet wird. Der Ausgangsstatus ist "0" und die letzte Ausgabe ist die Bestätigung, dass mein 'lighttpd' Server läuft:' [ok] Webserver starten: lighttpd. ' – ob1

+0

Ich habe seit einiger Zeit nicht mehr mit Docker gearbeitet. Es ist also möglich, dass sich die Kommandozeilenschnittstelle geändert hat und dieser Befehl nicht mehr funktioniert. –

24

nur verwenden tail -F -n0 /etc/hosts oder etwas

es Ihrem Container läuft so lange halten, wie Sie es nicht

+0

zusätzlich zu meiner Antwort: aber verstehen Sie, dass Docker-Compose (nicht daemonized) verwendet wird, um Ihnen den Workflow Ihres Containers zu zeigen, so dass es nützlich sein könnte, die Protokolldateien Ihrer gestarteten Dienste zu beenden. Prost –

+1

Es ist ein Hack, aber es funktioniert –

17

stoppen Wenn Sie eine Dockerfile verwenden, versuchen:

ENTRYPOINT ["tail", "-f", "/dev/null"]

(Offensichtlich ist dies nur für Dev-Zwecke, Sie sollten einen Container nicht am Leben erhalten, es sei denn, es läuft ein Prozess z. B. nginx ...)

1

Capture the PID des ngnix Prozess in einer Variablen (zB $ NGNIX_PID) und am Ende der Einstiegspunkt Datei do

wait $NGNIX_PID 

Auf diese Weise sollte Ihr Container laufen, bis ngnix am Leben ist, wenn ngnix stoppt, der Container stoppt ebenfalls

Verwandte Themen