首页 文章

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

提问于
浏览
91

我试图这样做,但出于某种原因,我的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 回答

  • 36

    我遇到了同样的问题,我发现如果你使用 -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 只允许您在后台运行容器 .

  • 67

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

    在设计Docker容器时,你应该构建它,使得只有一个进程在运行(即你应该有一个容器用于Nginx,一个用于supervisord或它正在运行的应用程序);另外,该进程应该在前台运行 .

    当进程本身退出时,容器将“退出”(在您的情况下,该进程是您的bash脚本) .


    但是,如果您真的需要(或想要)在Docker容器中运行多个服务,请考虑从"Docker Base Image"开始,它使用 runit 作为伪初始化进程( runit 将在Nginx和Supervisor运行时保持在线状态),这将留在前景,而你的其他进程做他们的事情 .

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

  • 30

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

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

    (显然这只是出于开发目的,你不应该运行一个进程,例如.nginx ...)

  • 10

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

    您可以使用主管来执行所有操作,如果使用“-n”标志运行,则告知不要守护进程,因此它将作为第一个进程保留:

    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,将它们分开是没有多大意义的 .

  • 5

    你可以在没有任何参数的情况下运行普通 cat ,如@Sa所提到'ad to simply keep the container working [actually doing nothing but waiting for user input] (Jenkins' Docker插件做同样的事情)

  • 59

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

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

    service supervisor start && nginx

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

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

  • 34

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

    wait $NGNIX_PID
    

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

相关问题