家里 NAS 上跑了不少 Docker 服务,比如 CPA 网关、青龙、DDNS、Home Assistant 等。这些服务的镜像会不定期发布新版本,每次需要手动去拉取、重建,久了就很烦。

前段时间折腾 CPA 网关自动更新,逐步从青龙脚本 → Portainer API → SSH 操作,最后收敛到了一个通用方案:一个脚本 + 一个配置文件,跑在群晖任务计划程序上,定时检查所有服务的 GitHub release,自动拉取镜像并按需重建容器。

方案架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────────┐
│ 群晖 DSM Task Scheduler │
│ 每天 6:00 / 18:00 各跑一次 │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ docker-auto-update.sh │ │
│ │ │ │
│ │ 读取 services.json 配置 │ │
│ │ ↓ │ │
│ │ 对每个服务: │ │
│ │ 1. 查询 GitHub latest release │ │
│ │ 2. 比对本地版本记录 │ │
│ │ 3. 若有新版本 → docker pull │ │
│ │ 4. 按模式决定是否 compose up -d │ │
│ │ 5. 企业微信推送通知 │ │
│ └──────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘

两种模式

模式 动作 适用场景
pull_only 只拉取镜像到本地 容器独立运行,不在 Compose 管理下,或者想手动择机重建
pull_and_rebuild 拉取镜像 + docker compose up -d 重建 Compose 管理的服务,全自动更新

配置文件格式

脚本通过一个 JSON 文件管理所有服务,新增服务只需加一条记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"services": [
{
"name": "CPA 网关",
"github_repo": "router-for-me/CLIProxyAPI",
"docker_image": "eceasy/cli-proxy-api",
"mode": "pull_and_rebuild",
"compose_dir": "/volume1/docker/cpa",
"compose_file": "compose.yaml",
"container_name": "cli-proxy-api",
"notify": true
}
]
}

各字段说明:

字段 说明
name 服务显示名称,用于日志和通知
github_repo GitHub 仓库 owner/repo,用于查询最新 release tag
docker_image Docker 镜像名,不含 tag
mode pull_onlypull_and_rebuild
compose_dir (仅 rebuild 模式) Compose 项目目录
compose_file (仅 rebuild 模式) Compose 文件名,默认 compose.yaml
container_name 容器名,用于从运行态反查当前版本(可选)
notify 是否推送企业微信通知

文件结构

1
2
3
4
5
6
7
8
/volume1/docker/scripts/compose/
├── update.sh # 通用更新脚本
├── services.json # 服务配置文件(可随时增删)
├── .wecom-config # 企业微信通知凭据(权限 600)
├── state/ # 各服务的版本记录
│ ├── CPA_网关.version
│ └── ...
└── update.log # 运行日志

群晖任务计划程序配置

DSM 控制面板 → 任务计划程序:

1
2
3
4
任务名称: Docker 自动更新
用户: root
运行命令: bash /volume1/docker/scripts/compose/update.sh
定时: 每天 06:00 / 18:00

通知效果

有更新时,企业微信会收到类似这样的推送:

1
2
3
4
5
✅ **Docker 镜像更新**
>CPA 网关: v7.2.71 → v7.2.74
>模式: 拉取 + 重建
>compose: /volume1/docker/cpa/compose.yaml
>⏱ 2026-07-14 18:00:23

失败时推送警告:

1
2
3
⚠️ **CPA 网关 拉取失败**
>eceasy/cli-proxy-api:v7.2.74 镜像拉取失败
>⏱ 2026-07-14 18:00:23

无更新时脚本静默退出,不产生通知。

脚本核心逻辑

1
2
3
4
5
6
7
8
9
10
for 每个服务 in services.json:
1. curl GitHub API → 获取最新 release tag
2. 读取本地 .version 文件 → 获取当前版本
3. 版本比较
- 相同 → 跳过
- 新版本 → docker pull
4. 根据 mode 决定是否 docker compose up -d
5. 写入新版本到 .version 文件
6. 清理旧镜像
7. 推送企业微信通知

关键设计:

  • 互斥锁:防止定时任务重叠执行
  • 版本状态文件:每次检查后记录版本,避免重复拉取同一个版本
  • compose.yaml 备份:更新前自动 .bak,失败时回滚
  • 幂等安全:无新版本时静默退出,不影响正在运行的服务

使用场景扩展

目前配置了 CPA 网关的自动更新,后续想加新服务只需在 services.json 追加一条记录。例如添加青龙的自动更新:

1
2
3
4
5
6
7
8
{
"name": "青龙面板",
"github_repo": "whyour/qinglong",
"docker_image": "whyour/qinglong",
"mode": "pull_only",
"container_name": "qinglong-web-1",
"notify": true
}

青龙使用 pull_only 模式——镜像拉取后择机手动重建,避免自动重启打断正在跑的任务。


📝 本文由 AI 助手群晖仕辅助生成