我已经看过一堆教程看起来像我尝试做的那样,但出于某种原因,我的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循环来保持它,但是什么是阻止它退出的正确方法?
答案 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
上立即退出。只是简单的sleep
或cat
会在容器退出前花费几秒钟。
答案 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)
如何使用监督服务形式?
您的服务监督下的服务
省去了创建supervisord.conf
答案 10 :(得分:0)
在开发过程中,有些情况下还没有服务,但您想模拟它并使容器保持活动状态。
编写一个模拟正在运行的服务的 bash 占位符非常容易:
while true; do
sleep 100
done
随着开发的进展,你可以用更严肃的东西来代替它。