为什么docker容器会立即退出

Gib*_*bbs 202 docker

我在后台运行一个容器

 docker run -d --name hadoop h_Service
Run Code Online (Sandbox Code Playgroud)

它快速退出.但如果我在前台运行,它运行正常.我使用了检查日志

docker logs hadoop
Run Code Online (Sandbox Code Playgroud)

没有错误.有任何想法吗?

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"]
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

cam*_*ser 189

这对我有用:

docker run -dit ubuntu
Run Code Online (Sandbox Code Playgroud)

之后,我检查了运行的进程:

docker ps -a
Run Code Online (Sandbox Code Playgroud)

用于再次连接容器

docker attach CONTAINER_NAME
Run Code Online (Sandbox Code Playgroud)

提示:要在不停止容器类型的情况下退出: ^P^Q

  • @Tommy,来自https://docs.docker.com/engine/reference/commandline/run/-d,--detach分离模式:在后台运行命令,-i, - interactive即使没有连接也保持STDIN打开,-t, - try分配一个伪TTY` -dit`只是简写 (11认同)
  • @ am17torres对,抱歉让我澄清我困惑的问题; d是分离的,我是互动的,所以d和i的组合让我很困惑.我认为d是将其作为背景(非交互式)过程启动. (2认同)
  • @Tommy当这些选项合并时,容器将**在后台进入交互模式**. (2认同)
  • @Tommy,@ am17torres`-di`是最低要求,如果我正确理解,`-t`选项与'-d`一起使用时是多余的 (2认同)
  • 实际上,如果你没有启用`-t`就重新连接,你将无法看到你的提示......但是因为每次我都没注意到,我通常会"执行"一个新的bash.我在从mac分离时遇到了问题,但也许我做错了.. (2认同)
  • 我想我不知道“后台交互模式”这个短语是什么意思,或者它令人困惑。 (2认同)
  • 如果主进程将立即退出,这将无济于事 (2认同)

Adr*_*uat 108

docker容器在其主进程完成时退出.

在这种情况下,它将在start-all.sh脚本结束时退出.在这种情况下,我不太了解hadoop告诉你如何做到这一点,但是你需要在前台运行一些东西,或者使用runit或supervisord等进程管理器来运行进程.

如果你没有说明-d,我认为你必须弄错它的工作; 它应该具有完全相同的效果.我怀疑你用一个稍微不同的命令启动它或使用-it它会改变一些事情.

一个简单的解决方案可能是添加如下内容:

while true; do sleep 1000; done

到脚本的末尾.我不喜欢这样,因为脚本应该真正监视它启动的进程.

(我应该说我从https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh那里偷了代码)


Kri*_*pta 54

我想延伸或者敢说,改善camposer提到的答案

当你跑步

docker run -dit ubuntu
Run Code Online (Sandbox Code Playgroud)

您基本上是以交互模式在后台运行容器.

当您通过CTRL + D(最常见的方式)连接和退出容器时,您停止容器,因为您刚刚使用上述命令杀死了启动容器的主进程.

利用已经运行的容器,我只需要分叉另一个bash进程并通过运行获取伪TTY:

docker exec -it <container ID> /bin/bash
Run Code Online (Sandbox Code Playgroud)


que*_*o42 32

如果您需要让容器运行而不退出,只需运行

docker run -dit --name MY_CONTAINER MY_IMAGE:latest
Run Code Online (Sandbox Code Playgroud)

进而

docker exec -it MY_CONTAINER /bin/bash
Run Code Online (Sandbox Code Playgroud)

你将处于bash容器的外壳中,并且它不应该退出。

以下仅适用于 ROS 模拟中的 roslaunch,此“--wait”不是 docker-compose 的默认参数!

Mind:这个很难读,而且好像只是关于一个自写的参数。跳过它。

或者如果退出发生在 期间docker-compose,请使用

command: bash -c "MY_COMMAND --wait"
Run Code Online (Sandbox Code Playgroud)

正如这里的其他两个答案已经指出的那样(尽管没有明确指代 docker-compose,这就是为什么我仍然再次提到“等待”技巧)。

在 ROS 模拟中,例如:

command: bash -c "roslaunch gazebo_ros empty_world.launch --wait"
Run Code Online (Sandbox Code Playgroud)

使用--wait是在 docker-compose 上获得所谓的 ROS 网络工作的核心,请参阅docker-compose 中的 ROS 中的示例代码导致“bash: line 0: cd: MYPROJECT: No such file or directory”。更多信息roslaunch请参阅WSL2 上的 Docker:Dockerfile:如何测试 ROS Gazebo 是否可以连接到已经工作的 X 服务器(在 Windows 上使用其 X11 显示)?

因此,这--wait一定是像 之类的命令的参数roslaunch gazebo_ros empty_world.launch。但是当检查链接教程教程:使用roslaunch启动Gazebo,世界文件和URDF模型时,代码中没有这样的参数,只是:

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
Run Code Online (Sandbox Code Playgroud)

这就是为什么我猜测它一定是项目给定参数的自写扩展。

后来我--wait在其他设置中再次尝试此操作,但没有成功。在 ROS 启动脚本中,它的工作原理可能只是掩盖了本问答( && tail ...) 中另一个答案的解决方法。


小智 25

每当我想要一个容器在完成我添加的脚本执行后熬夜

&& tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)

在命令结束时.所以它应该是:

/usr/local/start-all.sh && tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)

  • 这个可以解决,但是我想知道这个命令是否会导致内存泄漏或其他问题?与运行 `while true; 相比如何?睡觉1;完成;`? (3认同)

Bri*_*sen 18

一个很好的方法是启动在后台运行它们的进程和服务,并使用wait [n ...]脚本末尾的命令.在bash中,wait命令强制当前进程:

等待每个指定的进程并返回其终止状态.如果未给出n,则等待所有当前活动的子进程,并且返回状态为零.

我从SébastienPujadas 的麋鹿构建起始脚本中得到了这个想法.

从最初的问题来看,你的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 &
 wait
Run Code Online (Sandbox Code Playgroud)


Ker*_*ukk 16

将此添加到 Dockerfile 的末尾:

CMD tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)

示例 Docker 文件:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null
Run Code Online (Sandbox Code Playgroud)

参考


Leo*_*eon 6

我的做法是在 Dockerfile 中启动一个不会立即退出的 shell CMD [ "sh", "-c", "service ssh start; bash"],然后运行docker run -dit image_name。这样(ssh)服务和容器就可以运行了。


Viv*_*vek 6

您需要使用 -d 标志运行它以使其在后台作为守护程序运行。

docker run -d -it ubuntu bash


RJF*_*ner 5

为什么Docker容器会立即退出?

如果要强制映像徘徊(以便调试某些内容或检查文件系统的状态),则可以覆盖入口点以将其更改为shell:

docker run -it --entrypoint=/bin/bash myimagename
Run Code Online (Sandbox Code Playgroud)