容器升级不断档:换镜像不丢数据的方法

镜像出了新版本,怎么升级不断档又不丢数据?小够讲清容器升级的标准流程:pull、重建、数据卷不动,升级前必须备份,Watchtower 自动更新的利弊和回滚方法一次说清。

我是小够,只推够用的 VPS。

容器跑起来不是一劳永逸:Nginx 出安全更新、WordPress 发新版,你都得升级。Docker 的升级逻辑和传统"apt upgrade"不一样,记住一句话:容器不升级,只重建;数据不动,动的是镜像。

标准流程(compose)

cd ~/apps/wordpress
docker compose pull wordpress   # 拉新镜像,只拉 wordpress 这个服务
docker compose up -d            # 重建容器
docker image prune              # 清掉旧镜像,省磁盘

up -d 检测到镜像变了,会自动重建容器。数据在数据卷里,重建不影响——前提是当初数据卷配对了(看本月数据卷那篇)。pull 后面跟服务名,只升级这一个,不动数据库,避免"顺手把数据库也升了"这种惊吓。想一次全升就 docker compose pull 不加服务名。

标准流程(docker run 的容器)

没用 compose 的,手动三步:

docker pull nginx:alpine
docker stop web && docker rm web
docker run -d --name web -p 8080:80 -v ./html:/usr/share/nginx/html nginx:alpine

run 的参数要和当初一模一样——这就是为什么小够推荐 compose:参数都在文件里,不用凭记忆。手动 run 的升级最容易出错,错一个参数服务行为就变了。实在要用 run,把当初的命令存成 shell 脚本放项目目录,升级时照着跑。

升级前必须备份

铁律:升级前先备份数据卷。备份命令数据卷那篇讲过,这里不再重复。别觉得"我就升个小版本"——小够见过小版本升级把数据库搞挂的,备份是唯一的后悔药。

数据库升级要特别小心:MySQL 8.0 升 8.1 这种小版本一般没事,但跨大版本(比如 5.7 到 8.0)一定要先看官方升级说明,有些需要手动执行升级步骤,有些数据目录格式变了回不去。数据库的升级策略是:先备份,再看文档,最后动手,顺序别反。应用容器随便升,数据库容器升级前把文档读完。

怎么知道有新版本

  • 镜像仓库的 tags 页面(比如 Docker Hub 上的 wordpress 页)会列出所有版本,定期去看一眼,养成习惯。
  • 用 Diun 或 Watchtower 这类工具检测更新,有新版发通知(不是自动升级,是通知)。
  • 关注上游项目的 release note:WordPress、Nginx 的大版本更新一般提前几个月就有消息,不会搞突然袭击。

Watchtower:自动更新的利弊

Watchtower 能自动检测并更新容器:

services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --interval 86400 --cleanup

--interval 86400 每天检查一次,--cleanup 删掉旧镜像。听起来很美,但小够不建议生产环境自动升级:半夜自动升挂了,你都不知道;数据库这种有状态服务更不能自动升,数据格式一变哭都来不及。

折中方案:Watchtower 只开通知模式,有新版告诉你,升不升你手动决定:

command: --interval 86400 --monitor-only

检测自动化、决策手动化,这是小够的底线。通知可以接邮件或 webhook,配一次就行。

回滚

升级后发现不对劲?有 tag 就好办:

# compose 文件里把 image 改回旧 tag,比如 wordpress:6-php8.1-apache
docker compose up -d

所以打镜像/用镜像都尽量带具体版本号,别全用 latest——回滚的时候你会感谢自己。数据库回滚更麻烦:新版本可能已经改了数据文件格式,旧版本打不开了。这就是为什么数据库升级前备份是铁律中的铁律:应用回滚靠 tag,数据库回滚靠备份。

升级不断档?

个人博客这种,升级重建也就停几秒到几十秒,可以接受。真要零停机,得上蓝绿部署/滚动更新,那是多机器、负载均衡的玩法,个人 VPS 没必要。够用就好,别为理论上的完美付出不成比例的成本。真要是不能停的服务,升级前发个维护公告,比折腾零停机实在得多。