Watchtower是轻量级Docker容器自动更新工具,适合个人服务器、开发测试及家庭实验室场景;生产环境应使用Kubernetes滚动更新。其核心依赖挂载/var/run/docker.sock实现与Docker守护进程通信,配置错误或权限不足将导致失效;支持--interval轮询或--schedule cron调度(二者互斥),私有仓库需显式挂载config.json及CA证书;--cleanup清理无引用镜像,--include-restartable可监控重启策略容器;但不校验新容器健康状态,复杂场景需额外脚本增强。

Watchtower 不是生产环境的容器更新方案,它适合个人服务器、开发测试或家庭实验室场景;真要上生产,该用 Kubernetes 的滚动更新策略。
Watchtower 启动时必须挂载 /var/run/docker.sock
这是 Watchtower 和 Docker 守护进程通信的唯一通道,漏掉就完全无法工作。常见错误是只写了 -v /var/run/docker.sock 而没写宿主机路径映射目标,正确写法必须是:
docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower
如果你用的是 rootless Docker(比如非 root 用户启的 dockerd-rootless),套接字路径不是这个,得换成 $XDG_RUNTIME_DIR/docker.sock,否则会报错 Cannot connect to the Docker daemon。
另外注意权限:如果宿主机的 /var/run/docker.sock 属于 docker 组但容器内运行用户不是该组成员,可能触发连接拒绝——这时加 --user root 最快验证是否为权限问题。
--interval 和 --schedule 别混用
Watchtower 默认每 5 分钟检查一次(即 --interval 300),但很多人误以为 --schedule "0 0 * * *"(每天零点)和 --interval 86400 效果一样。其实不等价:
-
--interval是固定周期轮询,不管网络是否就绪、Registry 是否响应,到点就发请求 -
--schedule是 cron 式触发,依赖本地系统时间,且首次启动后可能延迟到下一个匹配时间点才执行第一次检查
更关键的是:两个参数同时存在时,--schedule 会覆盖 --interval。所以想“每天凌晨 2 点检查”,只写 --schedule "0 0 2 * * *"(注意 6 字段 cron,秒在最前);想“每 10 分钟查一次”,就只用 --interval 600,别加 schedule。
顺带一提:--interval 10 这种高频轮询对私有 Registry 压力大,也容易被限流,家用环境建议不低于 300 秒。
私有仓库认证不能只靠 docker login
很多用户执行了 docker login harbor.example.com 就以为 Watchtower 能自动读取凭据,结果日志里反复出现 unauthorized: authentication required。这是因为:
- Watchtower 容器默认不继承宿主机的
~/.docker/config.json - 必须显式挂载:添加
-v $HOME/.docker/config.json:/config.json:ro - 路径必须是
/config.json,不能是其他名字,Watchtower 硬编码读这个路径
如果宿主机是多用户环境,或者你用的是 rootless Docker,$HOME 可能指向错误用户目录——此时应改用绝对路径,比如 /root/.docker/config.json(root 用户)或 /home/youruser/.docker/config.json(普通用户),并确认该文件权限为 600。
还有一种情况:私有 Registry 启用了 TLS 自签名证书。Watchtower 默认校验证书,会报 x509: certificate signed by unknown authority。解决方法是把 CA 证书挂进容器并设环境变量:-v /path/to/ca.crt:/etc/ssl/certs/ca.crt:ro -e WATCHTOWER_INSECURE_REGISTRY=harbor.example.com,注意后者值是域名,不是 URL。
--cleanup 和 --include-restartable 要按需组合
--cleanup 的作用是删除旧镜像层,但它不会删掉当前正在运行容器所依赖的旧镜像——除非那个镜像已完全没被任何容器引用。所以即使开了 cleanup,磁盘空间也不一定立刻释放。
--include-restartable 是个容易被忽略的开关:它让 Watchtower 主动监控那些设置了 restart: unless-stopped 或 always 的容器,即使它们当前处于 stopped 状态。不加这个,Watchtower 默认只管 running 容器。
典型误用场景:你有个定时任务容器,每天跑完自动 exit,靠 restart 策略第二天再启。如果没加 --include-restartable,Watchtower 根本不会去比对它的镜像版本,也就永远不会更新。
另外,--cleanup 配合 --remove-volumes(注意不是 --prune-volumes)才会真正清理无主 volume。但后者有风险:一旦误删,数据不可逆。生产级部署中,volume 清理必须人工确认,别交给 Watchtower 自动干。
Watchtower 的核心逻辑很简单:拉新镜像 → 停旧容器 → 启新容器。但它不会校验新容器是否健康、端口是否通、依赖服务是否就绪。如果你的应用启动慢、依赖数据库初始化,或者需要迁移脚本,Watchtower 的“原子更新”反而会引发故障。这种场景下,得靠前置 healthcheck + post-update hook(目前 Watchtower 不原生支持 hook,得自己包一层 shell 脚本做 wrapper)。


















