收起左侧

解决docker的unless-stopped容器自启动失败问题

0
回复
29
查看
[ 复制链接 ]

0

主题

0

回帖

0

牛值

江湖小虾

1. 问题描述

docker容器重启策略restart设置了unless-stopped,并且在没有执行手动停止容器情况下,进行系统更新或重启,那么这些容器不会自启动。always的容器会正常自启动。

2. 临时解决方案

论坛中有用户分享了一个该问题的临时解决方案

简单来说,就是对 docker.service 文件进行修改,注释掉服务关闭时执行的强制关闭所有容器指令

问题:每次升级版本后都得重新来一遍,因为更新后docker.service都会被覆盖回默认状态

3. 基于drop-in机制的解决方案

通过学习临时解决方案可以发现,飞牛对 docker.service 文件进行了修改,导致重启策略为 unless-stopped 的容器不能自启动。那么我们也可以对服务配置文件进行修改,Unit 文件有一个 drop-in 覆盖机制允许在不修改主配置文件的情况下添加或覆盖特定设置

3.1 解决思路

在docker服务停止前,记录当前运行中且重启策略为unless-stopped的容器id号。对应执行ExecStopPre行。

在docker服务开始后,根据记录文件,启动记录的每一个需要重启的容器。对应执行ExecStartPost行。

为什么不直接对ExecStop行进行覆盖呢?飞牛系统这么设计docker服务配置文件,一定有他的道理。苦一苦用户,加点其他配置好了。

3.2 具体操作

  1. 开启ssh服务,并通过ssh登录设备,参考博客
  2. 编辑docker服务,生成覆盖配置
sudo systemctl edit docker.service
  1. 粘贴相关指令代码。仅需复制粘贴从 [Service] 开始的三行。上下相关的注释部分也贴在了下面,便于定位指令粘贴位置。
### Editing /etc/systemd/system/docker.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file

[Service]
ExecStartPost=/bin/sh -c 'sleep 5; LIST=/opt/unless-stopped-list.txt; [ -s "$LIST" ] && grep -v "^#" "$LIST" | while IFS= read -r cid; do [ -n "$cid" ] && docker start "$cid" 2>/dev/null; done; rm -f "$LIST"'
ExecStopPre=/bin/sh -c 'docker ps -q | (running_count=$(wc -l); if [ "$running_count" -gt 0 ]; then echo "# Unless-stopped Container List" > /opt/unless-stopped-list.txt; for container_id in $(docker ps -q); do restart_policy=$(docker inspect -f "{{.HostConfig.RestartPolicy.Name}}" "$container_id" 2>/dev/null); case "$restart_policy" in "unless-stopped") echo "$container_id" >> /opt/unless-stopped-list.txt;; esac; done; fi; sleep 5)'

### Lines below this comment will be discarded

### /etc/systemd/system/docker.service
# [Unit]

ExecStopPre行指令解释:选定/opt/unless-stopped-list.txt文件保存相关的容器id,首先检查当前正在运行且重启策略为unless-stopped的容器,若存在这样的容器,在文件第一行写入注释“Unless-stopped Container List”,其后每一行为一个容器id,最后休眠5秒。

ExecStartPost行指令解释:首先休眠5秒(刚执行了ExecStart,等待docker服务起来),然后检查文件是否存在,若存在,读取除注释外的每一行,启动相应id的容器,最后在容器启动完成后删除文件。

  1. 保存退出后检查覆盖配置,应该只有3行内容
cat /etc/systemd/system/docker.service.d/override.conf
  1. 重新加载服务配置文件
sudo systemctl daemon-reload
  1. 重启docker服务
sudo systemctl restart docker
  1. 检查容器是否如期启动
docker ps

4. 最后

在利用了drop-in机制的配置下,即使更新了飞牛系统,也不会影响我们对 docker.service 的修改(应该是这样的,我的设备是arm架构,更新不了系统,欢迎x86的设备更新验证反馈)。

存在的问题:在docker服务关闭而系统未关闭的情况下,存储容器id号的文件可能有泄露信息风险。

恳请大家批评指正!积极讨论,共同进步。

收藏
送赞
分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则