我已经看到了一堆教程,似乎做同样的事情,我试图做,但出于某种原因,我的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循环来保持它,但是怎样才能使它不退出呢?


当前回答

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

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

while true; do
  sleep 100
done

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

其他回答

这并不是你真正应该如何设计Docker容器。

在设计Docker容器时,你应该让它只有一个进程在运行(也就是说,你应该为Nginx准备一个容器,为它正在运行的应用程序准备一个容器);此外,该进程应该在前台运行。

当进程本身退出时,容器将“退出”(在您的示例中,该进程就是您的bash脚本)。


然而,如果你真的需要(或想要)在Docker容器中运行多个服务,可以考虑从“Docker Base Image”开始,它使用runit作为伪init进程(当Nginx和Supervisor运行时,runit将保持在线),当其他进程运行时,runit将保持在前台。

他们有大量的文档,所以你应该能够很容易地实现你想要做的事情。

确保你添加了daemon;或者使用CMD ["nginx", "-g", "daemon off;"根据nginx的官方图片

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

服务管理启动&& nginx

在某些情况下,容器中需要有多个进程,因此强制容器只有一个进程是行不通的,而且会在部署中产生更多问题。

所以你需要了解其中的利弊,并做出相应的决定。

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

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

while true; do
  sleep 100
done

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

动机:

在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.

我刚刚遇到了同样的问题,我发现如果你运行带有-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只是让你在后台运行容器。