这一开始本来是一个QQ机器人的问题.
我需要让机器人的Docker容器跟随系统开关机自动启停,在失败时自动重启,就像一个普通的Systemd服务一样.
然后折腾了一个小时,终于解决了.
很简单,先说一下基本思路:
- 写一个监控容器状况的脚本,容器退出后脚本也退出,装作自己是容器的守护进程.
- 在Service里ExecStartPre和ExecStop里控制容器的启停,ExecStart里跑伪装的守护进程.
开始
我们假设这里需要将一个叫contain
的容器作为服务.
伪·守护进程
好,让我们先写一个监控容器状况的脚本,这里暂且叫daemon.sh
.
先来一个死循环,让脚本保持运行:
#!/bin/bash
while sleep 1
done
再判断一下Docker容器是否在运行,这里用docker ps -af "name=<容器名称>"
获得容器的信息,如果返回里会包含Exited
,那就代表容器已经停止运行,用grep判断一下即可:
#!/bin/bash
echo Example Docker contain started.
while sleep 1
do
if docker ps -af "name=contain" | grep Exited; then
fi
done
在容器停止运行时退出,顺便润色两下:
#!/bin/bash
echo Example Docker contain started.
while sleep 1
do
if docker ps -af "name=contain" | grep Exited; then
echo Example Docker contain stopped
exit
fi
done
保存,反手一个chmod +x
,给个权限.
真·系统服务
在/etc/systemd/system
下面创建一个service,我们暂且叫他为contain.service
先开个头:
[Unit]
Description=Example Docker Contain Service
After=Docker.service
Wants=Docker.service
跑俩下:
[Unit]
Description=Example Docker Contain Service
After=Docker.service
Wants=Docker.service
[Service]
User=root
WorkingDirectory=/path/to/fake/daemon
ExecStartPre=/usr/bin/docker start contain
ExecStart=/path/to/fake/daemon/daemon.sh
ExecStop=/usr/bin/docker stop contain
Type=simple
StartLimitInterval=600
收个尾:
[Unit]
Description=Example Docker Contain Service
After=Docker.service
Wants=Docker.service
[Service]
User=root
WorkingDirectory=/path/to/fake/daemon
ExecStartPre=/usr/bin/docker start contain
ExecStart=/path/to/fake/daemon/daemon.sh
ExecStop=/usr/bin/docker stop contain
Type=simple
StartLimitInterval=600
[Install]
WantedBy=multi-user.target
保存,反手一个systemctl daemon-reload
,载入服务.
拍拍手,完事,撤.