使用 Docker 运行程序时,需要注意进程数是否正确,能否正确处理退出信号。本文记录几个我遇到过的案例。
Zabbix进程树错误
容器化 Zabbix 后运行不到1分钟就退出,日志如下。
1:20181218:163231.437 One child process died (PID:1768,exitcode/signal:1). Exiting ...
1:20181218:163233.444 syncing history data...
1:20181218:163233.450 syncing history data done
1:20181218:163233.450 syncing trends data...
1:20181218:163241.877 syncing trends data done
1:20181218:163241.878 Zabbix Server stopped. Zabbix 3.0.24 (revision 87227).
pstree
看到进程树不对:
bash-4.1$ pstree
zabbix_server─┬─cron.sh
├─crond───crond───bash───sleep
├─2*[sh]
└─156*[zabbix_server]
cron.sh
用于发报警,发完就退出,不应该是zabbix_server的子进程
需要引入init
程序,比如dumb-init
:
RUN chmod +x /init.sh
USER zabbix
ENTRYPOINT ["/usr/bin/dumb-init"]
CMD ["/init.sh"]
init.sh
脚本:
#!/bin/bash
[ ! -d /zabbix/alertscripts ] && mkdir -p /zabbix/alertscripts
[ ! -d /zabbix/externalscripts ] && mkdir -p /zabbix/externalscripts
sudo chown -R zabbix:zabbix /zabbix
sudo crond
exec /usr/sbin/zabbix_server -f -c $APP_CONFIG_PATH/ZABBIX_SERVER_CONF
gbalancer进程树错误
gbalancer
的-daemon
选项无效,用 &
使程序进入后台,但是进程树错误:
dumb-init-+-crond
|-nginx-+-gbalancer
| `-4*[nginx]
`-php-fpm7---30*[php-fpm7]
使用 daemonize 解决,alpine
中需要编译:
apk add gcc musl-dev make
./configure
make
正确的进程树:
dumb-init-+-crond
|-gbalancer
|-nginx---4*[nginx]
`-php-fpm7---30*[php-fpm7]
supervisord处理退出信号
以下日志可以看到supervisord
可以正确处理退出信号。
[root@itop php7-nginx]# docker logs php-sup
chown: /home/wwwroot/default/: No such file or directory
/usr/lib/python2.7/site-packages/supervisor/options.py:461: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
'Supervisord is running as root and it is searching '
2018-12-25 10:30:19,447 CRIT Supervisor is running as root. Privileges were not dropped because no user is specified in the config file. If you intend to run as root, you can set user=root in the config file to avoid this message.
2018-12-25 10:30:19,458 INFO RPC interface 'supervisor' initialized
2018-12-25 10:30:19,458 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2018-12-25 10:30:19,458 INFO supervisord started with pid 1
2018-12-25 10:30:20,467 INFO spawned: 'nginx' with pid 29
2018-12-25 10:30:20,490 INFO spawned: 'php-fpm' with pid 30
2018-12-25 10:30:21,796 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2018-12-25 10:30:21,796 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2018-12-25 10:31:58,224 WARN received SIGTERM indicating exit request
2018-12-25 10:31:58,224 INFO waiting for nginx, php-fpm to die
2018-12-25 10:31:58,703 INFO stopped: php-fpm (exit status 0)
2018-12-25 10:31:58,744 INFO stopped: nginx (exit status 0)
使用exec
使用脚本启动程序时应该用 exec
替换 Shell 进程,否则 sh
进程将无法处理 SIGTERM
信号,容器内程序不能优雅的退出(最终会被 kill)。表现为执行 docker stop
时要等待一段时间(受 --shutdown-timeout int Set the default shutdown timeout (default 15)
参数影响)。
未使用 exec
时错误的进程树:
ae5c908cc86d:~# pstree
sh---supervisord-+-nginx---4*[nginx]
`-php-fpm7---30*[php-fpm7]
docker stop
时的日志,可以看到 supervisord
没有收到 SIGTERM
:
[root@itop php7-nginx]# docker stop php-sup
php-sup
[root@itop php7-nginx]# docker logs php-sup
chown: /home/wwwroot/default/: No such file or directory
/usr/lib/python2.7/site-packages/supervisor/options.py:461: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
'Supervisord is running as root and it is searching '
2018-12-25 12:53:11,450 CRIT Supervisor is running as root. Privileges were not dropped because no user is specified in the config file. If you intend to run as root, you can set user=root in the config file to avoid this message.
2018-12-25 12:53:11,462 INFO RPC interface 'supervisor' initialized
2018-12-25 12:53:11,462 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2018-12-25 12:53:11,462 INFO supervisord started with pid 27
2018-12-25 12:53:12,467 INFO spawned: 'nginx' with pid 29
2018-12-25 12:53:12,520 INFO spawned: 'php-fpm' with pid 30
2018-12-25 12:53:13,770 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2018-12-25 12:53:13,771 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
[root@itop php7-nginx]#
supervisord vs dumb-init
都能实现功能,但是 dumb-init
更轻量,supervisord
需要安装 Python
环境,镜像会比较大。
参考资料
1. https://www.artindustrial-it.com/2017/09/20/10-best-practices-for-creating-good-docker-images/
发表回复