Zapic's Blog
将Docker容器作为普通的Systemd服务管理
2020-04-08
教程
查看标签

这一开始本来是一个QQ机器人的问题.
我需要让机器人的Docker容器跟随系统开关机自动启停,在失败时自动重启,就像一个普通的Systemd服务一样.

然后折腾了一个小时,终于解决了.

很简单,先说一下基本思路:

  1. 写一个监控容器状况的脚本,容器退出后脚本也退出,装作自己是容器的守护进程.
  2. 在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,载入服务.

拍拍手,完事,撤.