我已经看到了一堆教程,似乎做同样的事情,我试图做,但出于某种原因,我的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"]
我可以看到,当我手动运行(即使用-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循环来保持它,但是怎样才能使它不退出呢?
它退出的原因是因为shell脚本首先作为PID 1运行,当它完成时,PID 1消失了,而docker只在PID 1运行时运行。
你可以使用监控器来做所有的事情,如果运行时带有“-n”标志,它会被告知不要守护进程,所以它将保持作为第一个进程:
CMD ["/usr/bin/supervisord", "-n"]
你的supervisor .conf:
[supervisord]
nodaemon=true
[program:startup]
priority=1
command=/root/credentialize_and_run.sh
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=false
startsecs=0
[program:nginx]
priority=10
command=nginx -g "daemon off;"
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.log
autorestart=true
然后你可以有很多其他的进程,你想要和管理将处理重新启动他们,如果需要。
这样你就可以在需要nginx和php5-fpm的情况下使用supervisor ord,而把它们分开没有太大意义。
动机:
在docker容器中运行多个进程并没有什么错。如果你喜欢使用docker作为一个轻量级的VM,那就这样吧。其他人则喜欢将他们的应用程序拆分为微服务。我想:一个容器里的LAMP堆栈?就好了。
答案是:
坚持使用一个好的基础图像,如phusion基础图像。可能还有其他的。请发表评论。
这只是另一个请求监督的请求。因为phusion base image除了提供cron和locale setup之类的东西外,还提供了监督器。当运行这样一个轻量级VM时,你想要设置的东西。它还提供了到容器的ssh连接。
phusion镜像本身将启动并继续运行,如果你发出以下基本的docker运行语句:
moin@stretchDEV:~$ docker run -d phusion/baseimage
521e8a12f6ff844fb142d0e2587ed33cdc82b70aa64cce07ed6c0226d857b367
moin@stretchDEV:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
521e8a12f6ff phusion/baseimage "/sbin/my_init" 12 seconds ago Up 11 seconds
或者非常简单:
如果基本图像不适合你……对于快速CMD,让它保持运行,我认为bash是这样的:
CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"
或者busybox是这样的:
CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"
这很好,因为它将在docker停止时立即退出。
在集装箱被码头工人强行杀死之前,只是单纯的睡眠或猫将需要几秒钟。
更新
作为对Charles Desbiens关于在一个容器中运行多个进程的回应:
This is an opinion. And the docs are pointing in this direction. A quote: "It’s ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application." For sure it obviously much more powerful to devide your complex service into multiple containers. But there are situations where it can be beneficial to go the one container route. Especially for appliances. The GitLab Docker image is my favourite example of a multi process container. It makes deployment of this complex system easy. There is no way for mis-configuration. GitLab retains all control over their appliance. Win-Win.