2009 字
10 分钟
如何在Linux自动更新Docker容器
2026-11-15

上一篇 《如何在Linux部署Docker&Compose》 讲了怎么把容器跑起来。容器跑起来之后还有个长期问题:镜像更新了怎么及时跟上?安全补丁靠手动一个个 pull 很容易拖几个月。这篇讲怎么让容器自动更新,主线是 Watchtower(全自动),外加一套 Compose 脚本半自动方案,并把风险和回滚讲清楚——自动更新省事,但用错了也会半夜把服务更挂。

先想清楚:哪些容器适合自动更新#

自动更新的前提是镜像用 latest 或大版本标签(如 nginx:1),发布方出了新版就自动替换。这对无状态、发布稳定的服务很合适,但不是所有容器都适合:

类型建议原因
无状态小服务(博客、面板、工具站)自动更新挂了影响小,新版一般向后兼容
反向代理、网关自动更新或只通知影响面大,建议至少开通知
数据库(PostgreSQL、MySQL、Redis)不要全自动大版本升级涉及数据格式,必须人工确认
有状态/核心生产服务只通知,手动更新先看 changelog 再决定

还有一条铁律:重要服务把镜像版本固定住(如 postgres:16.4),自动更新只碰那些明确用浮动标签的容器。下面 Watchtower 的「只更新带标签的容器」就是为这个准备的。

方案对比#

方案自动化程度适合场景
手动 docker compose pull && up -d无偶尔维护、服务少
脚本 + 定时任务半自动Compose 项目、想自己掌控节奏
Watchtower全自动容器较多、想一劳永逸
Diun只通知不更新核心服务,先知道再手动更

主线:Watchtower 全自动更新#

Watchtower 会定时检查你正在运行的容器有没有新镜像,有就拉取新镜像、用原来的参数重建容器,整个过程不用人管。

用 Docker Compose 部署(推荐)#

和上一篇的习惯保持一致,用 Compose 管理:

services:
watchtower:
image: nickfedor/watchtower:latest
container_name: watchtower
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 10800 --cleanup

启动:

Terminal window
docker compose up -d
WARNING

镜像别用错:原版 containrrr/watchtower 已经停止维护并归档,它内置的 Docker 客户端 API 版本只有 1.25,而 Docker 29 的守护进程最低要求 1.40 以上。用原版镜像装出来的 Watchtower 会在日志里反复报错 client version 1.25 is too old. Minimum supported API version is 1.40,容器看着在跑,实际上永远不会更新任何东西。现在应当使用持续维护的分支 nickfedor/watchtower,配置、标签、参数与原版完全兼容,本篇所有示例都以它为准。如果你已经装了原版,换掉镜像重新 up -d 即可,原有配置不用改。

两个关键参数:

  • --interval 10800:每 10800 秒(3 小时)检查一次。太频繁没意义还费流量,3 小时是个舒服的节奏。
  • --cleanup:更新成功后删掉旧镜像,不然旧镜像会一层层堆满磁盘。
WARNING

Watchtower 需要挂载 /var/run/docker.sock,等于给它开了 Docker 的完整控制权。只在自己的机器上用,镜像只从官方仓库拉,别在不可信环境里部署。

只更新指定容器(更安全的做法)#

默认 Watchtower 会盯上所有容器。更稳妥的做法是加 --label-enable,只更新那些你亲自打了标签的容器:

command: --interval 10800 --cleanup --label-enable

然后在想自动更新的服务上加标签(Compose 写法):

services:
nginx:
image: nginx:latest
labels:
- com.centurylinklabs.watchtower.enable=true

没打标签的容器(比如数据库)Watchtower 看都不看,先看通知再手动处理,两边都不耽误。

先只监控,不动手#

第一次用不放心,可以先跑一阵子「只监控」模式:发现新镜像只写日志、不更新。

command: --interval 10800 --monitor-only

观察几天日志,确认它盯的容器没问题,再把 --monitor-only 去掉转正。

更新通知#

更新是自动的,但你应该知道它更了什么。Watchtower 支持通过 shoutrrr 发通知(Telegram、邮件、企业微信等都行),以 Telegram 为例:

environment:
- TZ=Asia/Shanghai
- WATCHTOWER_NOTIFICATIONS=shoutrrr
- WATCHTOWER_NOTIFICATION_URL=telegram://<机器人Token>@telegram?chats=<你的ChatID>

之后每次更新都会收到一条消息:哪个容器、从哪个版本更到了哪个版本,一目了然。

更新前后钩子#

个别容器更新前需要先做点事(比如备份、优雅停机),可以在目标容器上加生命周期标签:

labels:
- com.centurylinklabs.watchtower.lifecycle.pre-update=/scripts/backup.sh
- com.centurylinklabs.watchtower.lifecycle.post-update=/scripts/check.sh

脚本要放在容器内部,路径是容器里的路径。pre-update 返回非 0 会中止这次更新,正好用来做「备份失败就不许更新」的保险。

半自动方案:Compose 脚本 + 定时任务#

如果你的服务全是 Compose 项目,又想保留「更新前我说了算」的感觉,可以用脚本定时拉取重建,自己掌控名单:

/opt/scripts/docker-update.sh
#!/bin/bash
cd /opt/myapp || exit 1
docker compose pull
docker compose up -d
docker image prune -f
Terminal window
chmod +x /opt/scripts/docker-update.sh

挂到 crontab,每天凌晨 4 点执行并留日志:

0 4 * * * /opt/scripts/docker-update.sh >> /var/log/docker-update.log 2>&1

这个方案的好处是更新范围就是脚本里写的项目,坏处是每个项目要单独维护一份脚本,项目多了不如 Watchtower 省心。

WARNING

脚本里的 docker image prune -f 只删没有容器在用的悬空镜像,相对安全;但千万不要写成 docker system prune -a,那会把停着的容器、没在跑的镜像一起清掉,上一篇已经强调过这个坑。

版本固定与回滚#

自动更新偶尔会翻车:新版改了配置格式、或者本身带 bug。提前做好两件事,翻车了 5 分钟就能退回去:

1. Compose 文件进 Git。 每次改配置都提交,出事能查到上次的配置长什么样。

2. 知道旧镜像还在不在。 开了 --cleanup 旧镜像会被删掉,回滚要重新拉旧版本,所以关键服务的镜像标签别只写 latest,写到小版本:myapp:2.3.1。回滚时改回上一个版本号重新拉取即可:

Terminal window
# 把 compose 里的镜像改回旧版本后
docker compose pull
docker compose up -d

如果没开 --cleanup,旧镜像还躺在本机,可以直接给它重新打上标签再用:

Terminal window
docker images # 找到旧镜像的 IMAGE ID
docker tag <旧IMAGE_ID> myapp:rollback

常见问题排查#

日志反复报 client version 1.25 is too old。 这是装了原版 containrrr/watchtower 的典型症状:它的客户端 API 太旧,被新版 Docker 直接拒绝,一个容器都更新不了。把镜像换成维护分支 nickfedor/watchtower 重新部署即可,配置不用动。

Watchtower 没动静。 先看它的日志,它会明确写每个容器检查的结果和跳过原因:

Terminal window
docker logs -f watchtower

提示权限不足。 基本都是 /var/run/docker.sock 没挂对,或者宿主机 Docker 的 socket 路径不同,检查 Compose 的 volumes。

更新后容器起不来。 先看新容器日志确认是新版的问题,再按上面的回滚步骤退回旧版本,别在故障现场改配置硬撑:

Terminal window
docker logs <容器名>

磁盘越来越满。 多半是没开 --cleanup,旧镜像在堆积。手动清一次悬空镜像即可:

Terminal window
docker image prune -f

停用自动更新#

想停掉很简单,停掉 Watchtower 就行,其他容器不受影响:

Terminal window
docker compose stop watchtower
docker compose rm watchtower

小结#

  • 无状态小服务交给 Watchtower 全自动,3 小时检查一次、开 --cleanup、开通知;
  • 放不下心的先用 --label-enable 只更新打了标签的容器,或者 --monitor-only 先观察几天;
  • 数据库和核心服务固定版本、只通知不自动更;
  • Compose 文件进 Git、关键服务版本写到小版本,翻车能立刻回滚。

自动更新的定位是「把重复劳动交给工具」,不是「把判断也交出去」。名单分好类、通知开起来、回滚留好路,它就是个很省心的帮手。

如何在Linux自动更新Docker容器
https://blog.anexns.com/posts/linux-docker-auto-update/
作者
Anexns
发布于
2026-11-15
许可协议
CC BY-NC-SA 4.0