471 Stimmen

Warum beendet der Docker-Container sofort?

Ich führe einen Container im Hintergrund aus mit

 docker run -d --name hadoop h_Service

es beendet sich schnell. Aber wenn ich es im Vordergrund ausführe, funktioniert es einwandfrei. Ich habe die Logs überprüft mit

docker logs hadoop

Es gab keinen Fehler. Irgendwelche Ideen?

DOCKERFILE

 FROM java_ubuntu_new
 RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
 RUN dpkg -i cdh4-repository_1.0_all.deb
 RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
 RUN  apt-get update
 RUN apt-get install -y hadoop-0.20-conf-pseudo
 RUN dpkg -L hadoop-0.20-conf-pseudo
 USER hdfs
 RUN hdfs namenode -format
 USER root
 RUN apt-get install -y sudo
 ADD . /usr/local/
 RUN chmod 777 /usr/local/start-all.sh
 CMD ["/usr/local/start-all.sh"]

start-all.sh

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start
 /etc/init.d/hadoop-hdfs-datanode start
 /etc/init.d/hadoop-hdfs-secondarynamenode start
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start
 /bin/bash

35voto

Wenn Sie nur einen Container laufen lassen müssen, ohne zu beenden, führen Sie einfach aus

docker run -dit --name MY_CONTAINER MY_IMAGE:latest

und dann

docker exec -it MY_CONTAINER /bin/bash

und Sie werden in der bash Shell des Containers sein und es sollte nicht beenden.

Das Folgende funktionierte nur mit roslaunch in einer ROS-Simulation, dieser "--wait" ist kein Standardparameter für docker-compose!

Achtung: Dies ist schwer zu lesen und es scheint nur um einen selbstgeschriebenen Parameter zu gehen. Einfach überspringen.

Oder wenn der Exit während docker-compose auftritt, verwenden Sie

command: bash -c "MY_COMMAND --wait"

wie bereits von zwei anderen Antworten hier erwähnt (obwohl sie nicht so deutlich auf docker-compose verweisen, deshalb erwähne ich den "wait"-Trick noch einmal).

In der ROS-Simulation wäre es zum Beispiel:

command: bash -c "roslaunch gazebo_ros empty_world.launch --wait"

Die Verwendung von --wait war der Kern, um ein sogenanntes ROS-Netzwerk in docker-compose zum Laufen zu bringen, siehe Beispielcode unter ROS in docker-compose leads to "bash: line 0: cd: MYPROJECT: No such file or directory". Mehr zu roslaunch finden Sie unter Docker on WSL2: Dockerfile: how to test whether ROS gazebo can connect to already working X server (using its X11 display on Windows)?.

Daher muss dieser --wait ein Argument für einen Befehl wie roslaunch gazebo_ros empty_world.launch gewesen sein. Aber wenn man das verlinkte Tutorial überprüft Tutorial: Using roslaunch to start Gazebo, world files and URDF models, steht kein solcher Parameter im Code, nur:

roslaunch gazebo_ros empty_world.launch paused:=true use_sim_time:=false gui:=true throttled:=false recording:=false debug:=true verbose:=true gui_required:=true

Deswegen vermute ich, dass es eine selbstgeschriebene Erweiterung der gegebenen Parameter des Projekts gewesen sein muss.

Ich habe später dieses --wait wieder in anderen Einstellungen ausprobiert, und es hat nicht funktioniert. Im ROS-Startskript, wo es funktioniert hat, hat es wahrscheinlich nur den Workaround einer anderen Antwort in dieser Q/A (&& tail ...) überschrieben.

30voto

Kert Kukk Punkte 686

Fügen Sie dies am Ende der Dockerfile hinzu:

CMD tail -f /dev/null

Beispiel Dockerfile:

FROM ubuntu:16.04

# andere Befehle

CMD tail -f /dev/null

Referenz

23voto

Brian Olsen Punkte 905

Ein guter Ansatz wäre es, Ihre Prozesse und Dienste im Hintergrund zu starten und am Ende Ihres Skripts den Befehl wait [n ...] zu verwenden. In Bash zwingt der Befehl wait den aktuellen Prozess dazu:

Auf die Beendigung jedes angegebenen Prozesses zu warten und seinen Beendigungsstatus zurückzugeben. Wenn n nicht angegeben wird, werden alle derzeit aktiven Kindprozesse abgewartet und der Rückgabestatus ist Null.

Ich habe diese Idee von Sébastien Pujadas' Startskript für sein ELK-Build.

In Anlehnung an die Originalfrage würde Ihr start-all.sh etwa wie folgt aussehen...

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start &
 /etc/init.d/hadoop-hdfs-datanode start &
 /etc/init.d/hadoop-hdfs-secondarynamenode start &
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
 wait

20voto

Vivek Punkte 541

Sie müssen es mit dem -d Flag ausführen, um es als Daemon im Hintergrund laufen zu lassen.

docker run -d -it ubuntu bash

6voto

Leon Punkte 2856

Meine Praxis besteht darin, im Dockerfile eine Shell zu starten, die nicht sofort beendet wird CMD [ "sh", "-c", "service ssh start; bash"], dann docker run -dit image_name ausführen. Auf diese Weise ist der (ssh) Dienst und der Container aktiv.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X