如何在启动服务后保持Docker容器运行?

时间:2014-09-10 21:18:40

标签: docker

我已经看过一堆教程看起来像我尝试做的那样,但出于某种原因,我的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循环来保持它,但是什么是阻止它退出的正确方法?

11 个答案:

答案 0 :(得分:92)

如果您使用的是Dockerfile,请尝试:

ENTRYPOINT ["tail", "-f", "/dev/null"]

(显然这只是出于开发目的,你不应该让容器保持活着,除非它正在运行一个进程,例如.nginx ......)

答案 1 :(得分:68)

我遇到了同样的问题,我发现如果您使用-t-d标志运行容器,它会继续运行。

docker run -td <image>

以下是标志的作用(根据docker run --help):

-d, --detach=false         Run container in background and print container ID
-t, --tty=false            Allocate a pseudo-TTY

最重要的是-t标志。 -d只允许您在后台运行容器。

答案 2 :(得分:41)

这不是你应该如何设计你的Docker容器。

在设计Docker容器时,您应该构建它,以便只运行一个进程(即,您应该有一个容器用于Nginx,一个用于supervisord或app它正在运行);另外,该过程应该在前台运行。

容器将&#34;退出&#34;当进程本身退出时(在您的情况下,该进程是您的bash脚本)。


但是,如果确实需要(或想要)在Docker容器中运行多个服务,请考虑从"Docker Base Image"开始,它使用runit作为伪init进程(runit将在Nginx和Supervisor运行时保持在线状态),当您的其他进程执行其操作时,它将保持在前台。

他们拥有大量的文档,因此您应该能够轻松地实现您想要做的事情。

答案 3 :(得分:38)

它退出的原因是因为shell脚本首先作为PID 1运行,当它完成时,PID 1消失,而docker仅在PID 1运行时运行。

如果使用&#34; -n&#34;运行,您可以使用主管执行所有操作。标记它被告知不要守护进程,所以它将作为第一个进程保留:

CMD ["/usr/bin/supervisord", "-n"]

你的supervisord.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的情况下使用supervisord,将它们分开是没有意义的。

答案 4 :(得分:33)

你可以运行普通的cat,不需要像bro @ Sa'ad所提到的任何参数来简单地保持容器工作[实际上什么都不做,只是等待用户输入](Jenkins的Docker插件做同样的事情)< / p>

答案 5 :(得分:11)

请确保将daemon off;添加到nginx.conf或根据官方nginx图像使用CMD ["nginx", "-g", "daemon off;"]运行

然后使用以下命令将supervisor作为服务运行,将nginx作为前台进程运行,以防止容器退出

service supervisor start && nginx

在某些情况下,您需要在容器中安装多个进程,因此强制容器只有一个进程将无法正常工作,并且可能会在部署中产生更多问题。

因此,您需要了解权衡并做出相应的决定。

答案 6 :(得分:5)

在变量中捕获ngnix进程的PID(例如$ NGNIX_PID)并在入口点文件的末尾执行

wait $NGNIX_PID 

这样,你的容器应该运行直到ngnix存活,当ngnix停止时,容器也会停止

答案 7 :(得分:1)

动机:

nothing wrong in running multiple processes inside of a docker container。如果有人喜欢将docker用作轻量级虚拟机-那就这样吧。其他人则喜欢将其应用程序拆分为微服务。我认为:在一个容器中堆叠一个LAMP?太好了

答案:

粘贴具有良好的基本图片(如phusion base image)。可能还有其他。请发表评论。

这只是主管的另一个恳求。因为除了其他一些诸如cron和locale设置之类的东西之外,phusion基本映像还提供了管理程序。运行如此轻量级的VM时,您喜欢进行设置。值得的是,它还提供了到容器的ssh连接。

如果您发出以下基本docker run语句,则phusion映像本身只会启动并继续运行:

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 stop立即退出。只是简单的sleepcat会在容器退出前花费几秒钟。

答案 8 :(得分:1)

除了在您的 docker 文件中包含类似 : ENTRYPOINT ["tail", "-f", "/dev/null"] 的内容外,您还应该使用 -td 选项运行 docker 容器。当容器在远程 m/c 上运行时,这特别有用。把它想象成你已经通过 ssh 连接到一个具有图像的远程 m/c 并启动了容器。在这种情况下,当您退出 ssh 会话时,容器将被终止,除非它以 -td 选项启动。运行图像的示例命令是:docker run -td <any other additional options> <image name>

这适用于 docker 版本 20.10.2

答案 9 :(得分:0)

如何使用监督服务形式?

您的服务监督下的服务

  

Once supervise is successfully running, it will not exit unless it is killed or specifically asked to exit.

省去了创建supervisord.conf

的麻烦

答案 10 :(得分:0)

在开发过程中,有些情况下还没有服务,但您想模拟它并使容器保持活动状态。

编写一个模拟正在运行的服务的 bash 占位符非常容易:

while true; do
  sleep 100
done

随着开发的进展,你可以用更严肃的东西来代替它。