平时如何重载Nginx

用到最多的应该是下面几条命令:

1
2
3
4
nginx -s reload
systemctl reload nginx
/etc/init.d/nginx reload
kill -HUP `cat /var/run/nginx.pid`

Nginx的重载是以HUP信号为基础进行的, 也就是说, 如果你想在Docker中重启宿主机的Nginx, 需要在容器中向容器外的进程发送信号.

使用场景

记得我在上篇博客中讲到, 一些编排工具的Docker化, 编排工具本身也使用Docker部署. 但是像Nginx这样的出口程序, 放在Docker中没有必要, 不如直接放在宿主机中来的划算, 因此也才有了在容器中重载Nginx这一方案. 因为一般人不会这么用, 所以我也将其放在了奇用部分.

具体操作

1
2
3
4
5
6
7
8
9
$ docker run -ti \
-v /var/run/nginx.pid:/var/run/nginx.pid \
--pid host \
--rm \
--privileged \
alpine \
/bin/sh

> kill -HUP `cat /var/run/nginx.pid`

如何确认Nginx重载成功

Nginx在重载中master进程是不变的, 需要确认其worker的进程是否改变, 这里我直接贴出脚本, 通过ppid查找子进程, 不断进行比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

# parent id
PARPID=`cat /var/run/nginx.pid`
OLD_PIDS=`pgrep -P $PARPID`

kill -HUP `cat /var/run/nginx.pid`

x=10
while [ $x -gt 0 ]
do
sleep 1s
NEW_PIDS=`pgrep -P $PARPID`
[ "$NEW_PIDS" != "$OLD_PIDS" ] && echo "Update success" && exit 0
echo "$x seconds until blast off"
x=$(( $x - 1 ))
done
echo "Failed update" && exit 1

总结

本篇是Docker奇用的最后一篇, 介绍了平时在工作中使用的容器中操作宿主机进程这一情况, 与上一篇中的挂载unix socket不同, 因为Nginx只支持信号的方式, 所以采取--pid host将宿主机与容器统一进程空间, 也请注意, 这也是一项危险的操作, 也请不要滥用.

可能聪明的朋友就会想到, supervisor的socket是否也可挂载进容器中进行处理呢. 我在此不表达意见, 也许总会有一种场景适合.