为什么一个容器推荐只运行一个应用

发布于 2024-01-17 12:51:24 字数 3503 浏览 33 评论 0

容器技术为我们的应用部署带来了很大的便捷性,让我们更专注于程序的开发。但有时候由于我们对容器的理解不够深入,误把容器当成虚拟机使用,便会出现以下一些错误的使用情况:

  1. PHP 程序需要使用到 Nginx web 服务,所以将 Nginx 和 PHP-FPM 打包到一个镜像中,其中 Nginx 进程在脚本中以 daemon 的形式启动;
  2. 程序(如 golang 程序)产生的日志需要被 filebeat 程序搜集上报,所以将程序和 filebeat 打包进一个镜像中;

类似的例子还有很多,他们都有一个共同特点,那就是一个容器中运行了超过一个应用。那为什么不推荐一个容器中运行多个应用呢?其实最主要的原因是:容器运行时(docker 等)无法监控到容器内所有应用的运行状态。

0x01 为什么需要监控应用状态

试想这样一个场景,容器内的应用崩溃导致进程退出,但容器对外状态还在运行中,这不但会造成使用者的困惑,而且对进程的监控也不方便。因此,容器作为应用运行的载体,感知应用的运行状态是非常合理且必要的。

并且容器获知应用运行状态也给容器运行是提供了保证容器状态的一种能力,在 docker 中,这个选项是 [--restart](https://docs.docker.com/engine/reference/run/#restart-policies---restart) ( https://docs.docker.com/engine/reference/run/

0x02 如何监控应用状态

我们从一个示例来理解应用状态的监控/感知,首先运行如下命令启动一个容器(镜像的构建方法放在最后):

docker run --name multi-app-container -d yaxin/multi-app-test

然后使用 pstree -ap 定位到容器中的进程树:

http://www.wenjiangs.com/wp-content/uploads/2018/05/42-mqsy5v3jacb.png

然后执行 sudo kill 25962 结束掉 php-fpm 进程,之所以结束 php-fpm 进程是因为该进程并不是容器主进程

http://www.wenjiangs.com/wp-content/uploads/2018/05/58-sqk5o3vmj0g.png

这时候你会发现,容器还是运行状态,但 php-fpm 进程确实已经不存在了,如果此时你再执行 sudo kill 25965 ,然后查看容器状态(需要添加 -a 参数,即 docker ps -a ),已经变为Exited了。

http://www.wenjiangs.com/wp-content/uploads/2018/05/61-ukicgxhpqvh.png

为什么会这样呢?首先运行 docker restart multi-app-container 重启一下退出的容器,然后运行 docker exec -it multi-app-container /bin/sh 进入容器后执行 ps -o pid,ppid,args 查看容器中的进程

http://www.wenjiangs.com/wp-content/uploads/2018/05/70-o1evunaejwq.png

其实这个进程跟上面在主机上用 pstree -ap 看到进程树是相同的,只不过这个是在容器中看到的。观察一下, nginxphp-fpm 都是 init.sh 的子进程,而 init.sh 脚本之所以阻塞,是因为 nginx 是以非后台进程的方式运行,而一旦 nginx 进程结束 init.sh 脚本也就结束,也就说, init.sh 是容器中的主进程(pid 为 1),而 init.sh 阻塞时因为 nginx 阻塞,一旦 nginx 结束,那 init.sh 也会结束,进而被容器运行时(docker)监控到,从而导致容器进程退出。 php-fpm 结束并不会影响主进程的状态,所以它的状态也就不会被容器运行时监控到。

0x03 运行多个应用的方案

总有一些情况我们需要一个容器内运行多个应用的情况,如开发环境下将 nginx 和 php-fpm 打包到同一个镜像,减少复杂度或者将应用使用到的所有软件打包到一个镜像,方便部署(gitlab、nextcloud 等),那这种情况应该如何有效的管理应用呢?答案是第三方进程管理管理软件,如 supervisordpm2 等,这些软件会根据配置规则重启异常进程,从而恢复应用的正常运行,但你需要在容器中先安装这类软件,才能正常使用。

附:镜像构建文件

Dockerfile:

FROM alpine

RUN sed -i 's#dl-cdn.alpinelinux.org#mirrors.aliyun.com#g' /etc/apk/repositories \
    && apk add --no-cache nginx php-fpm \
    && mkdir -p /run/nginx

COPY init.sh /
RUN chmod +x /init.sh

CMD ["/init.sh"]

init.sh

#!/bin/sh

echo "Starting php-fpm..."
php-fpm7 -D

echo "Starting php-fpm..."
nginx -g 'daemon off;'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
25 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文