Docker 版本迭代速度比较快,新版本往往带来性能优化和安全修复,但生产环境直接升级存在不小风险:容器引擎与内核版本不匹配、存储驱动变更、API 版本兼容性问题,都可能导致升级后容器全部异常。一旦升级失败,如何快速回滚到旧版本是运维人员必须掌握的技能。本文将系统地讲解 Docker 升级前的准备、标准的升级操作以及多种回滚方案,帮助你在升级出问题时把业务影响降到最低。

升级前必须做好的准备工作
回滚能不能顺利执行,很大程度上取决于升级前的准备是否充分。任何一个环节的疏漏,都可能在回滚时变成无法挽回的坑。建议在升级前建立一份检查清单,逐项确认后再执行操作。
第一项是备份所有容器的运行配置。容器本身是无状态的,但启动参数、网络配置、挂载卷信息必须完整保留。可以使用 docker ps -a 导出容器清单,也可以借助 docker-compose 文件或者自建脚本把每个容器的 docker inspect 输出保存下来:
#!/bin/bash
# 备份所有容器的完整配置信息
mkdir -p /backup/docker_$(date +%Y%m%d)
cd /backup/docker_$(date +%Y%m%d)
docker ps -a --format "{{.Names}}" > container_list.txt
while read name; do
docker inspect "$name" > "inspect_${name}.json"
done < container_list.txt
# 导出关键镜像
docker images --format "{{.Repository}}:{{.Tag}}" > image_list.txt
while read img; do
docker save -o "$(echo $img | tr '/:' '__').tar" "$img"
done < image_list.txt第二项是记录当前版本信息。执行 docker version 和 docker info 把客户端、服务端版本以及存储驱动类型记录存档。如果当前使用的是 overlay2 存储驱动,回滚到老版本时也要确认旧版本支持该驱动,避免降级后镜像层无法识别。
第三项是保留旧版本的安装包。这一点非常关键,很多工程师在升级后直接清除了本机的 rpm 或 deb 缓存,等需要回滚时才发现旧版本包已经无处可寻。建议提前用 yumdownloader 或 apt-get download 把当前版本的 docker-ce、docker-ce-cli、containerd.io 三个包下载到本地目录留存。
标准的 Docker 升级操作流程
在准备充分的前提下,升级操作本身并不复杂,核心原则是:先停服务、再换包、后验证。不要在容器运行状态下直接替换二进制,这容易造成状态不一致。
以 CentOS 为例,使用 yum 升级的标准流程如下:
# 1. 停止并备份当前运行的容器 docker ps -q | xargs docker stop systemctl stop docker docker.socket # 2. 下载旧版本包留存(用于回滚) yumdownloader --resolve docker-ce-24.0.9 docker-ce-cli-24.0.9 containerd.io # 3. 升级到目标版本 yum install -y docker-ce-26.1.4 docker-ce-cli-26.1.4 containerd.io # 4. 启动并验证 systemctl start docker docker version docker info | grep -i "storage driver"
Ubuntu 环境下使用 apt 的操作类似,但要注意锁定版本的写法略有差异:apt-get install docker-ce=26.1.4-1~ubuntu.22.04~jammy。升级完成后,先检查 docker info 中的存储驱动和 cgroup 版本是否与升级前一致,再逐个启动容器观察日志,确认业务正常后再放开流量。
还有一个容易被忽略的细节:containerd 的版本必须与 docker-ce 匹配。Docker 本身只是容器管理的上层工具,实际创建容器的是 containerd 和 runc。如果升级时只升级了 docker-ce 而 containerd 保持旧版,可能出现容器启动报错 failed to create shim task 之类的异常。
升级失败后的回滚方案详解
回滚是本文的核心。Docker 采用 rpm 或 deb 包管理体系,天然支持版本降级,思路就是把升级时安装的包整体替换回旧版本。
在 CentOS 上执行 yum 降级是最直接的方案:
# 停止服务 systemctl stop docker docker.socket # 使用 yum downgrade 回到旧版本 yum downgrade -y docker-ce-24.0.9 docker-ce-cli-24.0.9 # containerd 一并回退,保持版本匹配 yum downgrade -y containerd.io # 重启并验证 systemctl start docker docker version docker ps -a
如果 yum downgrade 报依赖冲突,可以改用 yum install 加完整版本号的方式强制指定版本,必要时加上 --setopt=obsoletes=0 参数,避免新版包被判定为淘汰旧版而拒绝降级。Ubuntu 环境则使用 apt-get install docker-ce=旧版本号 并配合 apt-mark hold docker-ce 锁定版本,防止后续自动升级再次覆盖。
包降级完成后,还需要处理数据目录的兼容问题。Docker 的数据存放在 /var/lib/docker,如果新版本已经对镜像层元数据做过格式升级,回滚到旧版本后可能出现镜像加载失败。这时不必慌张,只要升级前的 docker save 导出文件还在,就可以通过 docker load 重新导入镜像,再结合备份的 inspect 信息重建容器。这也是为什么准备工作如此重要的原因。
编写一键回滚脚本与最佳实践
在多次执行升级操作的团队里,建议把回滚流程固化成脚本,减少人工操作失误。一个实用的回滚脚本至少要包含:停止服务、包降级、版本校验、镜像重新导入、容器重建五个步骤:
#!/bin/bash
set -e
OLD_VER="24.0.9"
BACKUP_DIR="/backup/docker_20240101"
echo "[1/5] 停止 Docker 服务"
systemctl stop docker docker.socket || true
echo "[2/5] 降级 Docker 包"
yum downgrade -y docker-ce-${OLD_VER} docker-ce-cli-${OLD_VER} containerd.io
echo "[3/5] 重启并校验版本"
systemctl start docker
CUR=$(docker version --format '{{.Server.Version}}')
if [ "$CUR" != "$OLD_VER" ]; then
echo "版本校验失败: $CUR"; exit 1
fi
echo "[4/5] 导入备份镜像"
for f in ${BACKUP_DIR}/*.tar; do
docker load -i "$f"
done
echo "[5/5] 回滚完成,请手动检查容器状态"
docker images最后总结几条实践建议。第一,升级尽量安排在业务低峰期,并预留至少一倍的回滚时间窗口;第二,采用灰度策略,先升级一台非核心节点观察 24 小时再推广到全集群;第三,使用 Kubernetes 的团队还要注意 kubelet 对容器运行时版本的最低要求,回滚版本不能低于它;第四,每次升级后在文档中记录版本变更内容和验证结论,形成团队知识沉淀。升级不是目的,稳定运行才是,把回滚方案准备扎实,才有底气去拥抱新版本。
Docker版本升级Docker回滚docker-ce降级修改时间:2026-09-15 03:46:32