在Docker里使用s6-svscan做进程守护

为什么要用s6

容器的哲学就是“容器里最好只有一个模块”,也就是常说的容器即进程(one process per container)。但是现在这个哲学有所动摇,很多人认为容器即服务(one thing per container),毕竟总有些特殊场景我们需要在一个docker里安装多个模块。容器虽然可以在docker run的时候可以指定--restart=always,但是这个并不能对pid不为1的进程起到看门狗的作用,如果pid不为1的进程crash了,那么就不会重启而出现故障了。于是需要一个真正的看门狗来重启这个服务。可用于docker的看门狗品种有很多,详情可见 https://www.iamle.com/archives/tag/runit 这篇文章。我在那篇文章里选择了s6。虽然听说有赞在生产环境里已经用了runit,但是我搞了一天都没有搞明白runit怎么用,而且关于runit的资料都是2017年之前的,就放弃了…

首先先在/opt/service里准备两个服务,分别是app1app2,在各自的文件家里分别创建run和finish两个文件,结构如下:

1
2
3
4
5
6
7
8
9
10
[root@func-lcshop-Harbor opt]# tree service/
service/
├── app1
│   ├── finish
│   └── run
└── app2
├── finish
└── run

2 directories, 4 files

这个run文件就是进程的启动文件,app1/run内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
[root@func-lcshop-Harbor app1]# cat run 
#!/bin/bash
echo "Started APP1 service..."

for i in {1..3}
do
echo "这里是第一个程序!"
sleep 1
done

echo "Oh no!我嗝屁了..." >&2 #3秒就死掉
exit 1

app2/run的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
echo "Started app2 service..."

for i in {1..3000} #这里懒,就直接写了3000秒
do
echo "这是第二个程序!" #这里做了区分
date
sleep 1
done

echo "Oh no!我嗝屁了..." >&2
exit 1

我上面主要是为了模拟程序挂掉的场景,实际run脚本应该是长时间运行的。

而finish的作用主要是执行程序退出后的操作,也就是run结束后的操作。这里要注意!因为s6会自动重启run脚本,如果在finish里也写了启动run脚本,那么就会有两个run脚本运行!

app1/finish内容如下:

1
2
3
#!/bin/bash
echo "app1 挂掉啦!..."
echo "app1 restart ok!"

然后我们准备一个dockerfile,如下:

1
2
3
4
FROM ubuntu
ADD https://github.com/just-containers/s6-overlay/releases/download/v1.21.8.0/s6-overlay-amd64.tar.gz /tmp/ #这个网站可能链接比较慢,所以推荐先下载然后COPY到容器里
RUN tar xzf /tmp/s6-overlay-amd64.tar.gz -C / #解压缩到根目录下
CMD ["/bin/s6-svscan","/opt/service"] #/opt/service就是app1和app2的路径

执行docker build -t="s6:0.1" .创建镜像,再使用docker run -it --name s6demo -v /opt/service:/opt/service s6:0.1启动这个s6demo的容器,在容器启动时就会发现s6会扫描/opt/service文件夹,执行对应的run脚本,当run脚本意外退出时,s6会自动重启,如图:
抱光妹

参考资料

https://github.com/just-containers/s6-overlay#the-docker-way
https://sourcediver.org/blog/2014/11/17/using-runit-in-a-docker-container/
https://segmentfault.com/a/1190000006644578
https://it.ismy.fun/2018/03/09/runit-example/

感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------