为什么docker容器立即退出

我运行一个容器在后台使用

 docker run -d --name hadoop h_Service

它很快就会消失。但如果我在前台运行,它工作得很好。我用

docker logs hadoop

没有错误。什么好主意吗?

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
498302 次浏览

当主进程结束时,docker容器退出。

在这种情况下,它将在start-all.sh脚本结束时退出。我对hadoop的了解还不够多,无法告诉您在这种情况下如何做到这一点,但是您需要在前台运行一些东西,或者使用进程管理器(如runit或supervisor ord)来运行进程。

我认为如果你没有指定-d,你一定是错误的认为它工作;效果应该是一样的。我怀疑你用一个稍微不同的命令启动它或使用-it,这将改变事情。

一个简单的解决方法就是添加如下内容:

< p > <代码>而真实;做睡眠1000;完成 < /代码> < / p >

到剧本的结尾。然而,我不喜欢这样,因为脚本实际上应该监视它启动的进程。

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

这对我来说很管用:

docker run -dit ubuntu

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

docker ps -a

用于再次附加容器

docker attach CONTAINER_NAME

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

我想扩展或者我敢说,改进坎波斯提到的答案

当你奔跑

docker run -dit ubuntu

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

当你通过CTRL+D(最常用的方法)附加并退出容器时,你停止了容器,因为你刚刚杀死了用上面的命令启动容器的主进程。

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

docker exec -it <container ID> /bin/bash

由于映像是linux,因此要检查的一件事是确保容器中使用的任何shell脚本都有unix行结束符。如果它们的末尾有^M,那么它们就是窗口行结束符。修复它们的一种方法是在/usr/local/start-all.sh上使用dos2unix将它们从windows转换为unix。以交互模式运行docker可以帮助解决其他问题。可能是文件名打错了。看到https://en.wikipedia.org/wiki/Newline

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

等待每个指定的进程并返回其终止状态。如果不指定n,则等待所有当前活动的子进程,并且返回状态为0。

我从Sébastien Pujadas的开始脚本为他的麋鹿构建得到了这个想法。

从最初的问题来看,你的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

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

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

&& tail -f /dev/null

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

/usr/local/start-all.sh && tail -f /dev/null

添加

exec "$@"

在我的shell脚本的末尾是我的修复!

有许多可能的方法可以使docker立即退出。对我来说,这是我的Dockerfile的问题。那份文件里有个漏洞。我用了ENTRYPOINT ["dotnet", "M4Movie_Api.dll]而不是ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]。正如你所看到的,我在最后漏掉了一句引文(”)。

为了分析问题,我启动了容器,并快速连接容器,以便看到具体的问题是什么。

C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b




C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b

4ea373efa21b是我的容器id。这让我想到了真正的问题。

enter image description here

在发现问题后,我必须重新构建、恢复、发布我的容器。

为什么docker容器立即退出?

如果你想强制映像挂起(为了调试某些东西或检查文件系统的状态),你可以重写入口点,将其更改为shell:

docker run -it --entrypoint=/bin/bash myimagename

把这个添加到Dockerfile的末尾:

CMD tail -f /dev/null

示例Docker文件:

FROM ubuntu:16.04


# other commands


CMD tail -f /dev/null

Reference .

如果你检查Dockerfile从容器,例如 fballiano / magento2-apache-php < / p >

你会看到在他的文件末尾他添加了以下命令: 而真正的;做睡眠1;做< / p >

现在,我建议你这样做

docker container ls --all | grep 127

然后,您将看到您的docker映像是否有一个错误,如果它以0退出,那么它可能需要这些将永远休眠的命令之一。

我在结尾添加了read shell语句。这将保持容器的主进程——启动shell脚本——运行。

来自副本,我在这里没有看到任何答案,解决了将主要工作负载作为后台作业运行的常见反模式,然后想知道Docker为什么退出。

简单来说,如果你有

my-main-thing &

然后取出&来在前台运行作业,或者添加

wait

在脚本的末尾,使其等待所有后台作业。

如果主工作负载退出,它仍然会退出,所以可以在while true循环中运行这个命令,强制它永远重新启动:

while true; do
my-main-thing &
other things which need to happen while the main workload runs in the background
maybe if you have such things
wait
done

(还要注意如何编写while true。经常会看到一些愚蠢的东西,比如while [ true ]while [ 1 ],它们碰巧是有用的,但它们的意思并不是作者想象的那样。)

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

Docker运行-d -it ubuntu bash

如果您只需要运行一个容器而不退出,那么只需运行即可

docker run -dit --name MY_CONTAINER MY_IMAGE:latest

然后

docker exec -it MY_CONTAINER /bin/bash

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

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

command: bash -c "MY_COMMAND --wait"

正如这里的其他两个答案所述(虽然不是很清楚地指docker-compose,这就是为什么我仍然提到“wait"再一次)。