我试图这样做,但出于某种原因,我的Docker容器退出了 . 基本上,我在Docker容器中设置了一个Web服务器和几个守护进程 . 我通过一个名为 run-all.sh
的bash脚本完成了最后一部分,我在Dockerfile中运行CMD . run-all.sh
看起来像这样:
service supervisor start
service nginx start
我在Dockerfile中启动它,如下所示:
CMD ["sh", "/root/credentialize_and_run.sh"]
我可以看到,当我手动运行时(即使用-i -t / bin / bash访问图像),服务都能正常启动,并且当我运行图像时,一切看起来都正常运行,但它会退出一次它完成了我的流程 . 我希望这些进程无限期地运行,据我所知,容器必须继续运行才能实现 . 然而,当我运行 docker ps -a
时,我看到:
➜ 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
是什么赋予了?为什么要退出?我知道我可以在我的bash脚本末尾添加一个while循环来保持它,但是什么是阻止它退出的正确方法?
7 回答
我遇到了同样的问题,我发现如果你使用
-t
和-d
标志运行容器,它会继续运行 .这是标志的作用(根据
docker run --help
):最重要的是
-t
标志 .-d
只允许您在后台运行容器 .这不是你应该如何设计你的Docker容器 .
在设计Docker容器时,你应该构建它,使得只有一个进程在运行(即你应该有一个容器用于Nginx,一个用于supervisord或它正在运行的应用程序);另外,该进程应该在前台运行 .
当进程本身退出时,容器将“退出”(在您的情况下,该进程是您的bash脚本) .
但是,如果您真的需要(或想要)在Docker容器中运行多个服务,请考虑从"Docker Base Image"开始,它使用
runit
作为伪初始化进程(runit
将在Nginx和Supervisor运行时保持在线状态),这将留在前景,而你的其他进程做他们的事情 .他们拥有大量的文档,因此您应该能够轻松地实现您想要做的事情 .
如果您使用的是Dockerfile,请尝试:
ENTRYPOINT ["tail", "-f", "/dev/null"]
(显然这只是出于开发目的,你不应该运行一个进程,例如.nginx ...)
它退出的原因是因为shell脚本首先作为PID 1运行,当它完成时,PID 1消失,而docker仅在PID 1运行时运行 .
您可以使用主管来执行所有操作,如果使用“-n”标志运行,则告知不要守护进程,因此它将作为第一个进程保留:
还有你的supervisord.conf:
然后,您可以拥有任意数量的其他进程,如果需要,主管将处理它们的重新启动 .
这样你就可以在需要nginx和php5-fpm的情况下使用supervisord,将它们分开是没有多大意义的 .
你可以在没有任何参数的情况下运行普通
cat
,如@Sa所提到'ad to simply keep the container working [actually doing nothing but waiting for user input] (Jenkins' Docker插件做同样的事情)确保将
daemon off;
添加到nginx.conf或根据官方nginx图像运行CMD ["nginx", "-g", "daemon off;"]
然后使用以下命令将supervisor作为服务运行,将nginx作为前台进程运行,以防止容器退出
service supervisor start && nginx
在某些情况下,您需要在容器中有多个进程,因此强制容器只有一个进程将无法工作,并且可能会在部署中产生更多问题 .
因此,您需要了解权衡并做出相应的决定 .
在变量(例如$ NGNIX_PID)和入口点文件末尾捕获ngnix进程的PID
这样,你的容器应该运行直到ngnix存活,当ngnix停止时,容器也会停止