告别Gotify——WatchTower 推送Docker更新消息到微信

Watchtower


Watchtower 是一个轻量级的开源工具,专为自动化更新 Docker 容器而设计。它通过监控运行中的容器,自动检测其基础镜像是否有新版本发布,并完成拉取新镜像、重启容器等操作,帮助用户保持容器始终处于最新状态,无需手动干预。

官方网站:https://containrrr.dev/watchtower/introduction/

通过一个简单的docker-compose.yaml即可部署:

services:
  watchtower:
    image: containrrr/watchtower  # 使用官方镜像
    container_name: watchtower    # 指定容器名称
    restart: unless-stopped       # 自动重启策略(除非手动停止)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # 挂载 Docker 套接字以控制容器
    environment:
      - TZ=Asia/Shanghai                     # 设置时区(可选)
      - SCHEDULE=0 0 4 * * 2,3,5             # Cron 表达式:每周二、三、五 4:00 AM
      - WATCHTOWER_CLEANUP=true              # 更新后自动清理旧镜像
      - WATCHTOWER_DEBUG=false               # 关闭调试日志
    command: --interval 300  # 冗余保障:如果调度失败,300秒后重试(可选)

但是以上compose只能静默更新,无法第一时间了解容器更新情况。为此,Watchtower 可以在容器更新时发送通知, 支持 6 类主要通知渠道,包括电子邮件(SMTP)、Slack、Microsoft Teams、Gotify、Discord 及基于 Shoutrrr 的通用通知(可扩展至 Telegram、Mattermost 等平台),用户可通过环境变量配置单渠道或多渠道组合,实时接收容器更新状态,并支持仅监控不更新的安全模式。


Gotify

Gotify 是一个开源的自托管消息推送服务,专注于为开发者及企业提供轻量级、可定制的实时消息推送解决方案。Gotify 的具体部署我就不展开介绍了,这不是本文的重点,感兴趣的同学可以参照官方网站( https://gotify.net/docs/install )部署使用。

以下是为 Watchtower 添加 Gotify 消息通知的修改后 Docker Compose 文件,包含自定义消息模板:

services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - TZ=Asia/Shanghai
      - SCHEDULE=0 0 4 * * 2,3,5            # 每周二、三、五 4:00 AM
      - WATCHTOWER_CLEANUP=true             # 清理旧镜像
      - WATCHTOWER_NOTIFICATIONS=gotify     # 启用 Gotify 通知
      - WATCHTOWER_NOTIFICATION_GOTIFY_URL=http://your_gotify_host  # Gotify 服务器地址
      - WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN=your_gotify_token       # Gotify 应用 Token
      - WATCHTOWER_NOTIFICATION_TEMPLATE=📊 **容器更新报告**\n---\n🔍 扫描总数:{{len .Scanned}}\n✔️ 成功更新:{{len .Updated}}\n⚠️ 跳过更新:{{len .Skipped}}\n❌ 更新失败:{{len .Failed}}\n{{- if .Updated }}\n✳️ **已更新容器:**\n{{- range .Updated }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 旧版本 ID:{{.CurrentImageID.ShortID}}\n  - 新版本 ID:{{.LatestImageID.ShortID}}\n{{- end }}{{- end }}{{- if .Fresh }}\n🆕 **新部署容器:**\n{{- range .Fresh }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 状态:{{.State}}\n{{- end }}{{- end }}{{- if .Skipped }}\n⚠️ **跳过更新的容器:**\n{{- range .Skipped }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 状态:{{.State}}\n  - 原因:{{.Error}}\n{{- end }}{{- end }}{{- if .Failed }}\n🛑 **更新失败的容器:**\n{{- range .Failed }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 状态:{{.State}}\n  - 错误信息:{{.Error}}\n{{- end }}{{- end }}  # 自定义消息模板
    command: --interval 300

至此其实已经能满足绝大部分用户接收容器更新消息的需求了,我也使用了Gotify一段时间,但在使用过程中,还是遇到了不少的痛点问题gotify通知渠道无法解决的:

  • 仅限 Android 原生支持:无官方 iOS 客户端,苹果用户需依赖网页端或第三方工具(如浏览器常驻标签),无法实现后台推送,容易错过实时通知。

  • 无移动端推送优化:Gotify 的移动端通知受限于国内Android后台消息机制,必须保持APP常驻后台保活才能及时接收到消息。

为此,我将目光转向了一款国民级应用——微信


微信

与 Gotify 相比,采用微信作为消息通知渠道在用户体验和功能集成方面具有以下显著优势:

1. 用户覆盖与终端兼容性

  • 全平台支持:微信覆盖 iOS、Android、PC 及网页端,用户无需额外安装小众客户端,即可在常用设备上接收通知,避免了 Gotify 的 iOS 原生客户端缺失问题。

  • 高触达率:微信日活用户超 10 亿,用户习惯高频打开,消息推送更易被及时查看,而 Gotify 依赖用户主动关注或网页端访问,存在 消息遗漏风险。

2. 消息交互与功能扩展

  • 富媒体支持:微信支持图文、语音、视频、小程序卡片等多样化消息格式,可嵌入动态数据(如容器更新日志的折叠内容),而 Gotify 仅支持基础文本,信息呈现 层级单一。

  • 无缝跳转操作:通过微信消息可直接跳转小程序或 H5 页面,用户可快速执行操作(如查看容器详情、回滚更新),而 Gotify 需依赖外部工具处理,流程割裂。

3. 社交传播与生态整合

  • 社交属性赋能:微信消息可通过群聊、朋友圈分享扩大触达范围,适合团队协作场景(如运维团队同步更新状态),而 Gotify 仅为单向推送,缺乏 社交传播能力3。

  • 生态闭环:微信集成支付、卡券、企业微信等功能,可结合小程序实现 “通知-操作-交易”闭环(如发送容器故障通知后引导用户付费升级服务),Gotify 需额外开发集成。

4. 用户习惯与运维便捷性

  • 零学习成本:用户对微信界面及操作高度熟悉,无需适应新工具,而 Gotify 需管理 Token、服务器地址等参数, 学习门槛较高1。

  • 企业级管理:微信支持分级权限(如公众号、企业微信的分角色通知),适合大型团队分权管理,而 Gotify 需通过创建多个应用变通实现, 管理复杂度高。

决定了使用微信作为消息接收渠道,但是WatchTower原生并不支持微信推送,那就看看有哪些开源项目可供使用了。

  1. WxPusher(基于微信公众号)
    1. 接口类型:通过微信公众号模板消息接口实现,需服务号或测试号。
    2. 核心功能:
      • 支持 HTML、Markdown 格式消息,可嵌入复制按钮等交互元素。
      • 提供 Java/Python SDK 及 REST API。
    3. 限制:
      • 账号要求:需微信服务号(需企业资质)或测试号(个人可用但功能有限)。
      • 频率限制:单个用户每天最多接收 2000 条,单条消息最多发送 2000 个用户。
      • 模板限制:需预先配置消息模板,且模板内容需符合微信审核规范。
      • 内容长度:正文不超过 40,000 字符,摘要不超过 20 字符。
  2. Wecom酱(基于企业微信)
    1. 接口类型:通过企业微信应用消息接口推送至个人微信。
    2. 核心功能:
      • 支持文本、图片等消息类型,无需用户安装企业微信客户端。
      • 提供多语言 SDK(PHP/Python 等),支持自建服务。
    3. 限制:
      • 企业注册:需注册企业微信并创建应用,个人用户需虚构企业信息。
      • IP 白名单:2022 年后创建的应用需配置服务器 IP 为可信 IP,云函数需固定公网 IP。
      • 消息类型:文本消息无格式支持,复杂内容需自行拼接字符串。
      • 频率限制:未明确公开上限,但高频调用需自行缓存 access_token。
  3. MP-PUSH(自托管服务)
    1. 接口类型:类似 Server 酱的自托管方案,基于 NestJS 实现。
    2. 核心功能:
      • 支持频道订阅模式,用户通过微信绑定频道接收消息。
      • 提供 Docker 镜像快速部署,API 极简(仅需 POST 请求)。
    3. 限制:
      • 依赖服务号:需微信服务号或测试号,且配置消息模板。
      • 部署门槛:需自有服务器或云主机,且域名备案(国内服务器)。
      • 功能局限:仅支持文本推送,缺乏富媒体交互。
  4. Server酱(开源生态)
    1. 接口类型:混合方案,支持企业微信、微信公众号等多通道。
    2. 核心功能:
      • 开源版(Wecom酱)可自建,商业版(Turbo)提供免费额度。
      • 支持异步任务队列和消息模板。
    3. 限制:
      • 开源版限制:需自行处理消息排队和错误重试,无官方维护。
      • 商业版限制:免费额度有限(如每天 5 条),付费版需订阅。
      • 依赖第三方:集成 LeanCloud 等云服务,增加运维复杂度。
  5. 微信原生 SDK(如 PHP/C# SDK)
    1. 接口类型:微信官方 API 的封装库(如公众号、小程序接口)。
    2. 核心功能:
      • 全面覆盖微信生态 API(如用户管理、消息推送、支付等)。
      • 支持多平台(.NET、PHP 等),如 SKIT.FlurlHttpClient.Wechat。
    3. 限制:
      • 开发复杂度:需处理 OAuth 授权、消息加解密等底层逻辑。
      • 账号权限:高级功能(如模板消息)需服务号且通过微信认证。
      • 维护成本:需持续跟进微信 API 变更,如 RSA 签名模式调整。

方案

适用场景

优势

主要限制

WxPusher

个人开发者、轻量通知

无需服务器,API 简单

依赖服务号,消息模板审核严格

Wecom酱

企业内通知、自建服务

免客户端安装,开源灵活

企业微信注册门槛,IP 白名单要求

MP-PUSH

自托管、频道订阅模式

Docker 部署便捷,代码开源

功能单一,依赖服务号

Server酱生态

混合通知、多通道整合

开源与商业版结合,扩展性强

自建版运维复杂,商业版付费

原生 SDK

深度集成微信生态功能

功能全面,官方兼容性高

开发门槛高,需处理底层细节

可以看到很多方案都要通过开通服务号或测试号,这里插入简要补充一下这两个的区别

  1. 微信服务号
    1. 资质要求
      • 主体类型:仅限企业、政府、媒体、组织机构等,个人无法申请。
      • 认证费用:需缴纳每年 300 元 的微信认证费(首次认证失败不退款)。
      • 材料要求:提供营业执照、法人身份证明、企业银行账户信息等。
    2. 核心功能
      • 消息推送:每月可发送 4 条 模板消息至用户,支持图文、视频等富媒体格式。
      • 支付能力:集成微信支付功能,支持线上交易、红包发放(需额外开通商户平台)。
      • 高级接口:开放用户管理(获取用户手机号、地理位置)、客服系统、智能菜单等接口。
      • OAuth 授权:支持网页授权登录,用户无需关注即可获取基本信息。
      • 数据统计:提供用户增长、消息分析、菜单点击量等运营数据。
    3. 适用场景
      • 企业营销:推送促销活动、会员服务通知。
      • 客户服务:通过客服接口实现自动化回复或人工接入。
      • 商业闭环:结合微信支付实现电商交易(如小程序商城)。
  2. 微信测试号
    1. 资质要求
      • 主体类型:个人开发者可直接申请,无需企业资质或认证费用。
      • 申请方式:通过 微信公众平台测试号系统 扫码登录获取。
    2. 功能限制
      • 消息推送:可发送模板消息,但无频率限制(仅限测试环境,不可用于生产)。
      • 接口权限:支持基础接口(如自定义菜单、消息接收/回复),但无支付功能。
      • 用户管理:测试号用户需手动添加(最多 100 人),无法获取真实用户数据。
      • 有效期:测试号长期有效,但接口配置需通过 Token 验证(需服务器支持)。
    3. 开发优势
      • 快速验证:适合个人开发者调试消息交互、OAuth 登录等核心功能10。
      • 内网穿透:通过 ngrok 或 cpolar 工具将本地服务映射至公网,解决微信 80/443 端口限制问题8。
      • 低成本试错:无需支付认证费用,规避企业资质门槛。

服务号的话个人用户就别想了,而测试号除了灵活性不够,还需要自己造轮子写代码,本着能偷懒就偷懒的原则,这样一番对比下来,就只有WecomChan(https://github.com/easychen/wecomchan)适合我这种懒人的要求了。通过企业微信作为接入,拥有更高的自由度。

你可能会问,企业微信本身就开放了发送应用消息接口https://developer.work.weixin.qq.com/document/path/90236),为什么不直接用WatchTower调用呢?

行,也不行。官方文档中规定:

获取access_token是调用企业微信API接口的第一步,相当于创建了一个登录凭证,其它的业务API接口,都需要依赖于access_token来鉴权调用者身份。

因此开发者,在使用业务接口前,要明确access_token的颁发来源,使用正确的access_token。

企业微信所有 API 接口调用均先需获取 access_token,而access_token不是永久有效的(一般是2个小时有效期),且短时间内不能频繁去获取,这就意味直接用WatchTower调用,无法定期自动更新access_token。这就又需要一个第三方工具来自动获取access_token并缓存下来。

WecomChan就是来帮我们干这个活的。

这里摘取一段WecomChan的介绍:

优点:

  1. 一次配置,持续使用

  2. 配置好以后,只需要微信就能收消息,不再需要安装企业微信客户端

PS:消息接口无需认证即可使用,个人用微信就可以注册

前置条件:

  1. 域名:拥有一个域名(备案或没备案都行)

  2. IP:拥有一个公网IP

现在你看到我的这个个人网站(https://blog.weiqingyuan.com)下方的备案号就说明,以上两个前置条件我都具备了,接下来就可以根据WecomChan的操作一步一步进行了,为方便不具备科学条件上网的读者阅读,也为了自己做个存档,我就把文字教程搬运过来:

具体操作

第一步,注册企业

用电脑打开企业微信官网,注册一个企业

第二步,创建应用

注册成功后,点「管理企业」进入管理界面,选择「应用管理」 → 「自建」 → 「创建应用」

应用名称填入「Server酱」,应用logo到这里下载,可见范围选择公司名。

创建完成后进入应用详情页,可以得到应用ID( agentid )①,应用Secret( secret )②。

注意:secret推送到手机端时,只能在企业微信客户端中查看。

第三步,添加可信IP

2022年6月20日之后创建的应用,需要额外配置可信IP。

在「应用详情页」的最下方,开发者接口分类中,找到「企业可信IP」,点击「配置」,并填入服务器IP即可。

注意,如果你使用云函数等公用IP的云服务,可能需要在(云函数或其他服务的)设置界面中打开「固定公网IP」来获得一个独立的IP。否则有可能报「第三方服务IP」错误。

第四步,获取企业ID

进入「我的企业」页面,拉到最下边,可以看到企业ID③,复制并填到上方。

推送UID直接填 @all ,推送给公司全员。

第五步,推送消息到微信

进入「我的企业」 → 「微信插件」,拉到下边扫描二维码,关注以后即可收到推送的消息。

PS:如果出现接口请求正常,企业微信接受消息正常,个人微信无法收到消息的情况:

  1. 进入「我的企业」 → 「微信插件」,拉到最下方,勾选 “允许成员在微信插件中接收和回复聊天消息”

  2. 在企业微信客户端 「我」 → 「设置」 → 「新消息通知」中关闭 “仅在企业微信中接受消息” 限制条件。

接下来就能使用以下docker-compose.yaml来部署WecomChan了:

services:
  go-wecomchan:
    image: sola97/wecomchan:latest
    container_name: go-wecomchan
    restart: always
    environment:
      - SENDKEY=your_sendkey  # 用于验证的发送密钥,请替换为实际的发送密钥,后续调用时会用到
      - WECOM_CID=your_CorpID  # 请替换为实际的企业微信的CorpID
      - WECOM_SECRET=your_Secret  # 请替换为实际的企业微信应用的Secret
      - WECOM_AID=your_AgentID  # 请替换为实际的企业微信应用的AgentID
      - WECOM_TOUID=your_UserID  # 接收消息的用户ID,多个用户用竖线分隔,例如 user1|user2,全员推送的话填 @all
      - REDIS_STAT=ON  # 启用Redis状态存储
      - REDIS_ADDR=redis:6379  # Redis服务的地址和端口
      - REDIS_PASSWORD=your_redis_password  # Redis的连接密码,请替换为实际的密码
    ports:
      - 8080:8080  # 将容器的8080端口映射到主机的8080端口
    networks:
      - go-wecomchan
    depends_on:
      - redis  # 确保在go-wecomchan服务启动前,redis服务已启动

  redis:
    image: docker.io/bitnami/redis:6.2
    container_name: go-wecomchan-redis
    restart: always
    environment:
      - REDIS_PASSWORD=your_redis_password  # Redis的连接密码,请确保与上面go-wecomchan服务中的一致
      - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL  # 禁用高风险的Redis命令,增强安全性
    networks:
      - go-wecomchan
    volumes:
      - redis_data:/bitnami/redis/data  # 持久化Redis数据

volumes:
  redis_data:
    driver: local  # 使用本地卷驱动

networks:
  go-wecomchan:
    driver: bridge  # 使用桥接网络

注意此处我没用用官方的镜像 docker.io/aozakiaoko/go-wecomchan,因为WatchTower原生支持的通知渠道只有电子邮件(SMTP)、Slack、Microsoft Teams、Gotify、Discord 及基于 Shoutrrr 的通用通知(可扩展至 Telegram、Mattermost 等平台),除了不包括微信、企业微信,也同样不包括WecomChan,但通用消息渠道Shoutrrr支持 POST调用。

WecomChan官方的 Docker 版调用方式中,文本消息的调用方式是GET:

# 推送文本消息
curl --location --request GET 'http://localhost:8080/wecomchan?sendkey={你的sendkey}&msg={你的文本消息}&msg_type=text'

# 推送图片消息
curl --location --request POST 'http://localhost:8080/wecomchan?sendkey={你的sendkey}&msg_type=image' \
--form 'media=@"test.jpg"'

而WatchTower的Shoutrrr如果使用GET则无法将消息通知模板WATCHTOWER_NOTIFICATION_TEMPLATE 拼接到GET URL中。

在翻阅issue时,有一位大神sola97修改了一个支持POST的Docker镜像,也就是上面compose里面的sola97/wecomchan。

部署好WecomChan后,记得在企业微信你创建的应用里添加你的域名和公网IP,否则调用会报错:

WecomChan和企业微信至此已经配置完成。用以下命令在服务器本机测试一下:

curl -H 'Content-Type: application/json' -d '{"sendkey":"your_sendkey","msg":"文本消息 POST 测试","msg_type":"text"}' 'http://127.0.0.1:8080/wecomchan'

接下来需要重新部署WatchTower,添加WecomChan的调用通道。Gotify虽然有各种缺点,但 作为备用通道也是很好的,因此同时保留。以下是docker-compose.yaml

services:
  watchtower:
    image: containrrr/watchtower:latest
    container_name: watchtower
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # 必须挂载,用于访问 Docker API
    # command: --run-once
    environment:
      TZ: Asia/Shanghai
      WATCHTOWER_CLEANUP: "true"   # 更新后自动清理旧镜像
      WATCHTOWER_SCHEDULE: "0 0 4 * * 1,4"  # Cron 表达式:每周一(1)、周四(4) 4:00 AM 执行
      WATCHTOWER_NOTIFICATION_REPORT: "true"  # 生成详细的更新报告
      WATCHTOWER_NOTIFICATIONS: "gotify shoutrrr"   # 同时启用 Gotify 和 Shoutrrr 通知渠道
      WATCHTOWER_NOTIFICATION_GOTIFY_URL: "http://your_gotify_host" # Gotify 服务器地址
      WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN: "your_gotify_token"  # Gotify 应用 Token
      WATCHTOWER_NOTIFICATION_URL: > # Shoutrrr 通用通知配置 (generic+ 作为前缀添加到目标 URL,以便将其用于通用服务)
        generic+http://your_wecomchan_host/wecomchan?requestmethod=POST&contenttype=application/json
      WATCHTOWER_NOTIFICATION_TEMPLATE: |  # 自定义通知模板 (兼容 JSON 格式,另外企业微信支持markdown语法)
        {{- if .Report -}}
        {
          "sendkey": "your_sendkey",
          "msg": "{{- with .Report -}}📊 **容器更新报告**\n---\n🔍 扫描总数:{{len .Scanned}}\n✔️ 成功更新:{{len .Updated}}\n⚠️ 跳过更新:{{len .Skipped}}\n❌ 更新失败:{{len .Failed}}\n{{- if .Updated }}\n✳️ **已更新容器:**\n{{- range .Updated }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 旧版本 ID:{{.CurrentImageID.ShortID}}\n  - 新版本 ID:{{.LatestImageID.ShortID}}\n{{- end }}{{- end }}{{- if .Fresh }}\n🆕 **新部署容器:**\n{{- range .Fresh }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 状态:{{.State}}\n{{- end }}{{- end }}{{- if .Skipped }}\n⚠️ **跳过更新的容器:**\n{{- range .Skipped }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 状态:{{.State}}\n  - 原因:{{.Error}}\n{{- end }}{{- end }}{{- if .Failed }}\n🛑 **更新失败的容器:**\n{{- range .Failed }}- 容器名称:{{.Name}}\n  - 镜像:{{.ImageName}}\n  - 状态:{{.State}}\n  - 错误信息:{{.Error}}\n{{- end }}{{- end }}{{- end -}}",
          "msg_type": "text"
        }
        {{- else -}}
        {
          "sendkey": "your_sendkey",
          "msg": "{{range .Entries}}{{.Message}}\n{{end}}",
          "msg_type": "text"
        }
        {{- end -}}

关键配置说明

  1. WATCHTOWER_NOTIFICATION_URL

    • 使用 Shoutrrr 的 generic 协议适配第三方服务,示例中为 WecomChan 的 Webhook

    • requestmethod=POST 指定 HTTP 方法,contenttype=application/json 定义请求格式

  2. 模板设计要点

    • 通过 Go 模板语法动态生成 JSON 消息体,需确保 JSON 格式正确(如引号转义)

    • {{len .Scanned}} 等变量来自 Watchtower 的更新报告对象

  3. 需替换的占位符

    • your_gotify_host:Gotify 服务器地址(如 http://192.168.1.100:8081

    • your_gotify_token:Gotify 应用的推送 Token

    • your_wecomchan_host:WecomChan 服务地址(如 http://wecom.example.com

    • your_sendkey:消息接收服务的鉴权密钥

至此全部部署并配置完成,此时你应该可以在微信中看到消息推送了。


最后总结一下消息从WatchTower推送到个人微信的完整流程。

数据流图

graph TD %% 数据源与生成 A[WatchTower<br>(容器更新检测)] -->|更新事件数据<br>(Scanned/Updated等状态)| B[更新报告生成模块] B -->|结构化报告<br>(JSON/模板变量)| C[通知消息构建模块] %% 消息传输与中转 C -->|Shoutrrr协议<br>(POST请求+JSON消息体)| D[WecomChan服务<br>(HTTP接口)] D -->|解析参数<br>(sendkey、msg、msg_type)| E[企业微信API调用模块] %% 权限验证与数据处理 E -->|请求获取<br>access_token| F[企业微信认证服务器] F -->|返回有效令牌<br>(有效期2小时)| E E -->|携带access_token<br>构造消息请求| G[企业微信消息服务器] %% 数据终端呈现 G -->|推送至<br>个人微信| H[用户微信客户端<br>(服务通知/群聊)] H -->|解析富媒体内容<br>(文本/Markdown)| I[用户界面展示] %% 辅助组件 subgraph 缓存层 J[Redis<br>(存储access_token)] --> E end subgraph 配置层 K[WatchTower配置<br>(docker-compose.yaml)] --> C L[WecomChan配置<br>(企业ID/Secret等)] --> D end

时序图

sequenceDiagram participant WatchTower participant WecomChan participant Redis participant 企业微信API participant 微信客户端 Note over WatchTower: 定时扫描或事件触发容器更新检测 WatchTower->>WatchTower: 生成更新报告(Scanned/Updated等数据) WatchTower->>WatchTower: 渲染通知模板为JSON消息体 WatchTower->>WecomChan: POST请求(带sendkey、JSON消息) Note over WecomChan: 检查Redis中是否有有效access_token WecomChan->>Redis: 查询access_token及过期时间 alt access_token无效或过期 WecomChan->>企业微信API: POST /gettoken(CorpID+Secret) 企业微信API-->>WecomChan: 返回access_token(有效期7200秒) WecomChan->>Redis: 存储access_token及过期时间 else access_token有效 Redis-->>WecomChan: 返回有效access_token end WecomChan->>企业微信API: POST /message/send(access_token+消息内容) 企业微信API-->>WecomChan: 返回消息发送成功状态 企业微信API->>微信客户端: 推送消息至个人微信 微信客户端-->>用户: 显示更新通知(服务通知/群聊)

总结

优点分析

1. 高兼容性与用户触达率
  • 全平台覆盖:依托微信生态,支持 iOS、Android、PC 及网页端,解决了 Gotify 缺乏官方 iOS 客户端的痛点,用户无需额外安装小众应用即可接收通知。

  • 高触达效率:微信日活超 10 亿,用户打开频率高,消息通过「服务通知」或群聊推送,显著降低遗漏风险,相比 Gotify 的被动查看模式更可靠。

2. 低开发门槛与便捷性
  • 免代码集成:通过 WecomChan 中转,无需直接调用企业微信复杂 API(如处理access_token缓存、消息加解密),降低开发难度。

  • 配置轻量化:只需在 WatchTower 的docker-compose中添加 Shoutrrr 通用通知配置,结合 WecomChan 的图形化管理界面(如企业微信后台),运维成本低于自建 SDK 方案。

3. 功能扩展性与灵活性
  • 富媒体支持:微信消息可包含 emoji、Markdown 格式(如加粗、列表)、链接等,相比 Gotify 的纯文本通知,信息呈现更清晰(如示例中的更新报告带状态图标)。

  • 多渠道备份:可同时保留 Gotify 作为备用通知渠道(如WATCHTOWER_NOTIFICATIONS="gotify shoutrrr"),避免单一渠道故障导致通知中断。

4. 企业级管理能力
  • 权限分级:通过企业微信可实现分角色通知(如仅推送给运维团队),支持TOUID指定具体用户或@all全员推送,适合团队协作场景。

  • 合规性适配:企业微信接口符合国内网络安全规范,无需科学上网即可使用,适合对合规性有要求的企业环境。

缺点分析

1. 部署与配置复杂度较高
  • 基础设施依赖:需具备公网 IP 和域名(国内服务器需备案),对个人开发者或无服务器资源的用户不友好(对比 Gotify 可完全本地化部署)。

  • 企业微信注册门槛:需创建企业微信账号(个人用户需虚构企业信息),且 2022 年后创建的应用需配置可信 IP,增加网络配置成本(如云函数需固定公网 IP)。

2. 消息频率与格式限制
  • 潜在频率限制:企业微信未明确公开消息发送频率上限,但频繁调用可能触发风控(如短期内大量推送),需自行实现access_token缓存和请求频率控制。

  • 格式局限性:WecomChan 仅支持文本消息(msg_type="text"),无法直接发送图片、小程序卡片等高级格式(需通过企业微信原生 API 单独开发)。

3. 运维与依赖风险
  • 第三方服务依赖:依赖 WecomChan 开源项目(非官方维护),若项目停止更新可能影响兼容性(如企业微信 API 变更时需自行适配)。

  • Redis 依赖:WecomChan 需部署 Redis 服务存储access_token和消息状态,增加组件复杂度(对比 Gotify 单容器部署更轻量)。

4. 敏感信息管理挑战
  • 密钥安全:需在 WatchTower 和 WecomChan 中配置企业微信Secretsendkey等敏感信息,若环境变量泄露可能导致恶意消息推送或企业微信接口被滥用。

  • 数据合规性:企业微信消息内容受微信审核约束,需避免敏感词或违规内容,增加内容管理成本。

免责声明:以上方案为个人原创摸索,共享出来仅供参考和交流讨论,作者不承担采用本方案造成的任何损失的后果,请根据自身项目实际情况与资源配置搭建符合自己需求的推送渠道。


告别Gotify——WatchTower 推送Docker更新消息到微信
http://localhost:8090//archives/gao-bie-you-xiang-gotify----watchtower-tui-song-dockergeng-xin-xiao-xi-dao-wei-xin
作者
WeiQ_Orz
发布于
2025年05月25日
许可协议