Docker升级迁移零风险指南:完整备份与回退策略

📅 2026/8/18 9:13:04
Docker升级迁移零风险指南:完整备份与回退策略
这类 Docker 升级、降级、迁移、备份的操作最怕的不是步骤多而是中途配置丢失、服务中断或者升级后发现新版本不兼容想回退又找不到原来的状态。很多教程只告诉你“怎么升”但没告诉你“升坏了怎么安全地回来”也没说清楚生产环境里那些自定义网络、卷、配置怎么完整打包带走。我处理过不少从测试环境往生产环境搬或者给老旧服务器升级 Docker 的场景。核心就一条在动任何东西之前先把能备份的、能导出的、能记录的状态全部存一份。这不是备份数据是备份“现场”。这样无论是升级失败还是迁移后服务起不来你都能分钟级回退到操作前的状态真正做到标题里说的“零风险”。下面我会按实际运维中的处理顺序拆解整个过程。重点不是命令本身而是每个命令在什么时机用、为什么要用、以及执行后如何验证备份是有效的。1. 操作前最关键的一步完整“现场”备份与状态记录在输入apt upgrade docker-ce或yum update docker之前所有操作都应该是可逆的。你需要备份的不是容器里的业务数据那应该另有定期备份方案而是 Docker 自身的配置和运行状态。1.1 备份 Docker 守护进程配置Docker 服务的主要配置在/etc/docker/daemon.json。这是你自定义镜像仓库、日志驱动、存储驱动、网络设置的地方。先把它拷出来sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.backup.$(date %Y%m%d)如果这个文件不存在说明你用的是默认配置那也要确认一下ls -la /etc/docker/daemon.json 2/dev/null || echo No daemon.json, using default config.1.2 备份容器网络、卷等元数据Docker 的元数据包括网络配置、卷定义、插件信息等默认存放在/var/lib/docker。直接打包这个目录在运行时可能有问题但我们可以备份其关键子目录的结构和配置。更实用的方法是导出所有容器的创建命令和配置。用docker inspect可以获取详细信息但更直观的是用docker commit和docker save吗不那会创建巨大的镜像。对于备份“状态”我推荐先获取所有容器的运行配置快照# 列出所有容器包括已停止的并输出其名称、镜像、创建命令、网络、挂载卷等关键信息 docker ps -a --format table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}} /tmp/container_list_$(date %Y%m%d).txt # 为每个容器生成详细的 inspect 信息存为单独文件便于后续查看 for container in $(docker ps -aq); do docker inspect $container /tmp/container_inspect_${container}_$(date %Y%m%d).json done1.3 记录当前 Docker 版本与系统依赖这是为了降级时能准确找回对应的版本包。记下完整的版本信息docker --version docker-compose --version # 如果用了 cat /etc/os-release uname -r把这些信息保存到一个文件里echo Backup Date: $(date) /tmp/docker_env_backup_$(date %Y%m%d).txt echo Docker Version: $(docker --version) /tmp/docker_env_backup_$(date %Y%m%d).txt echo Docker Compose Version: $(docker-compose --version 2/dev/null || echo Not installed) /tmp/docker_env_backup_$(date %Y%m%d).txt echo Kernel: $(uname -r) /tmp/docker_env_backup_$(date %Y%m%d).txt echo OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d -f2 | tr -d \) /tmp/docker_env_backup_$(date %Y%m%d).txt1.4 可选但重要为关键容器创建临时镜像快照如果你的容器状态非常复杂且没有完整的 Dockerfile 或docker-compose.yml来描述为了绝对安全可以为关键容器创建提交镜像。注意这可能会产生大量磁盘占用仅用于核心业务容器。# 假设你的关键容器名为 app_core docker commit app_core app_core_backup:snapshot_$(date %Y%m%d) # 然后可以将此镜像导出为文件转移至安全位置 docker save app_core_backup:snapshot_$(date %Y%m%d) -o /backup/app_core_snapshot.tar完成以上四步你手头应该有daemon.json的备份文件。所有容器的列表和详细配置 JSON 文件。系统环境与版本记录。可选关键容器的镜像快照文件。现在无论升级还是迁移你都有了回退的“地图”。2. 执行 Docker 引擎的升级或降级操作有了备份心里不慌。现在可以动 Docker 本身了。升级和降级的核心区别在于指定版本号。2.1 升级 Docker 到最新版本对于 Ubuntu/Debian 系统# 1. 更新包索引 sudo apt-get update # 2. 安装允许 apt 通过 HTTPS 使用仓库的包 sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common # 3. 添加 Docker 官方 GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - # 4. 添加 Docker 仓库 sudo add-apt-repository deb [archamd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable # 5. 再次更新包索引 sudo apt-get update # 6. 安装最新版本的 Docker CE sudo apt-get install -y docker-ce docker-ce-cli containerd.io对于 CentOS/RHEL 系统# 1. 卸载旧版本如果存在 sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine # 2. 安装依赖包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 3. 添加 Docker 仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 4. 安装最新版本的 Docker CE sudo yum install -y docker-ce docker-ce-cli containerd.io注意直接安装docker-ce会装最新版。在生产环境中我更建议查看可用版本列表并选择一个已知稳定的次新版本而不是盲目追新。# Ubuntu/Debian 查看可用版本 apt-cache madison docker-ce # CentOS/RHEL 查看可用版本 yum list docker-ce --showduplicates | sort -r然后使用sudo apt-get install docker-ceVERSION_STRING或sudo yum install docker-ce-VERSION_STRING来安装特定版本。2.2 降级 Docker 到特定旧版本降级的需求通常源于新版本不兼容。这时第一步记录的版本信息就派上用场了。首先彻底停止 Docker 服务sudo systemctl stop docker sudo systemctl stop containerd卸载当前 Docker 版本# Ubuntu/Debian sudo apt-get remove --purge docker-ce docker-ce-cli containerd.io # CentOS/RHEL sudo yum remove docker-ce docker-ce-cli containerd.io--purge会删除配置文件但我们有备份所以没关系。或者不用--purge保留/etc/docker目录。安装特定旧版本使用第一步中记录的准确版本字符串。# Ubuntu/Debian sudo apt-get install docker-ceVERSION_STRING docker-ce-cliVERSION_STRING containerd.io # CentOS/RHEL sudo yum install docker-ce-VERSION_STRING docker-ce-cli-VERSION_STRING containerd.io例如sudo apt-get install docker-ce5:20.10.17~3-0~ubuntu-focal恢复守护进程配置sudo cp /etc/docker/daemon.json.backup.20231027 /etc/docker/daemon.json # 使用你的备份日期启动并验证sudo systemctl start docker docker --version2.3 验证升级/降级后的基础功能安装完成后不要急着启动旧容器。先跑一个最简单的测试确保 Docker 引擎本身工作正常# 运行 hello-world 镜像测试拉取镜像和运行容器的能力 sudo docker run --rm hello-world # 检查 Docker 服务状态 sudo systemctl status docker --no-pager -l # 检查守护进程配置是否生效例如查看日志驱动 docker info | grep -i logging\|storage如果hello-world能成功运行并输出欢迎信息说明 Docker 引擎安装和基础网络是通的。3. 容器与数据的迁移两种场景与策略“迁移”可能指同一台机器上 Docker 数据目录的移动也可能指从服务器 A 搬到服务器 B。核心对象就三个镜像、容器、数据卷。3.1 场景一同一服务器内迁移 Docker 数据目录默认 Docker 把所有数据镜像、容器、卷、网络放在/var/lib/docker。如果这个目录所在磁盘空间不足你需要迁移到新位置如/data/docker。操作步骤停止 Docker 服务sudo systemctl stop docker # 确保 containerd 也停止 sudo systemctl stop containerd备份原数据目录双重保险sudo tar -czvf /backup/docker_backup_$(date %Y%m%d).tar.gz -C /var/lib docker同步数据到新位置sudo rsync -avxP /var/lib/docker/ /data/docker/使用rsync比cp更安全支持断点续传和校验。修改 Docker 启动配置指向新路径编辑/etc/docker/daemon.json如果不存在则创建{ data-root: /data/docker }启动 Docker 并验证sudo systemctl start docker docker info | grep Docker Root Dir确认输出是/data/docker。然后运行docker images和docker ps -a查看镜像和容器列表是否完整。确认无误后可删除旧数据可选# 务必确认新目录运行完全正常后再操作 sudo rm -rf /var/lib/docker3.2 场景二从服务器 A 迁移到服务器 B不同主机这是更常见的需求例如从测试环境迁到生产环境或更换云服务器。标准化迁移流程在源服务器A上导出镜像# 导出所有镜像为单个文件如果镜像多且大不推荐难以管理 # docker save $(docker images -q) -o all_images.tar # 更推荐为每个需要迁移的镜像单独导出或使用镜像仓库中转 # 方法1推送到私有或公共镜像仓库 docker tag my_app:latest myregistry.com/my_app:latest docker push myregistry.com/my_app:latest # 方法2导出为文件 docker save my_app:latest -o my_app.tar在源服务器A上备份容器数据卷找到容器使用的所有命名卷和绑定挂载。docker inspect container_name | grep -A 10 -B 5 Mounts对于命名卷Volume其数据在 Docker 管理的数据目录内默认/var/lib/docker/volumes/。你可以备份整个 volumes 目录或使用docker run --rm -v volume_name:/backup_from -v $(pwd):/backup_to alpine tar czf /backup_to/volume_backup.tar.gz -C /backup_from .这类命令打包特定卷。在源服务器A上记录容器运行命令# 对于每个容器获取其创建时的完整命令近似 docker inspect --format{{.Config.Cmd}} container_name # 更全面的方式是使用 docker run 命令的重现工具或直接备份 docker-compose.yml最稳妥的方式如果容器是用docker-compose.yml启动的直接备份这个文件。如果没有考虑根据docker inspect的输出手写一个docker-compose.yml或docker run命令脚本。这是迁移的“蓝图”。在目标服务器B上准备环境安装相同或兼容版本的 Docker参考第一节的版本记录。恢复/etc/docker/daemon.json配置如果有自定义配置。在目标服务器B上导入镜像与数据# 如果用了镜像仓库 docker pull myregistry.com/my_app:latest # 如果用了文件 docker load -i my_app.tar # 恢复数据卷 # 先创建卷 docker volume create app_data # 再将备份文件解压到卷中通过一个临时容器 docker run --rm -v app_data:/restore -v $(pwd):/backup alpine sh -c tar xzf /backup/volume_backup.tar.gz -C /restore在目标服务器B上重新创建并启动容器使用你在第 3 步记录的“蓝图”docker-compose.yml或docker run命令。# 使用 docker-compose docker-compose up -d # 或使用 docker run docker run -d --name my_app -v app_data:/app/data -p 8080:80 my_app:latest验证docker ps查看容器状态。docker logs container_name查看启动日志。访问应用服务进行功能验证。4. 生产环境备份策略与紧急恢复对于生产环境备份应该是自动化的、周期性的。除了前面的一次性手动备份你需要一个持续运行的备份方案。4.1 全量备份与增量备份结合全量备份每周一次备份整个 Docker 数据目录/var/lib/docker或所有镜像、卷的导出文件。适合重大变更前或作为基线。增量备份每天一次备份新增的镜像、变更的卷数据。可以通过对比镜像 ID 列表、卷修改时间来实现。一个简单的全量备份脚本示例 (backup_docker.sh)#!/bin/bash BACKUP_DIR/backup/docker DATE$(date %Y%m%d_%H%M%S) mkdir -p $BACKUP_DIR/$DATE # 1. 备份 daemon.json cp /etc/docker/daemon.json $BACKUP_DIR/$DATE/ 2/dev/null || true # 2. 备份所有镜像列表 docker images --format {{.Repository}}:{{.Tag}} $BACKUP_DIR/$DATE/image_list.txt # 3. 备份所有容器信息包括已停止的 docker ps -a --format {{.Names}} $BACKUP_DIR/$DATE/container_list.txt for container in $(docker ps -aq); do docker inspect $container $BACKUP_DIR/$DATE/container_inspect_$container.json done # 4. 备份所有命名卷仅列表和配置不备份数据本身数据量大需单独处理 docker volume ls -q $BACKUP_DIR/$DATE/volume_list.txt # 5. 备份 docker-compose 文件假设存放在 /opt/app/ 下 find /opt -name docker-compose*.yml -exec cp {} $BACKUP_DIR/$DATE/ \; # 6. 打包备份目录 tar -czf $BACKUP_DIR/docker_backup_$DATE.tar.gz -C $BACKUP_DIR $DATE # 7. 清理7天前的备份 find $BACKUP_DIR -name docker_backup_*.tar.gz -mtime 7 -delete4.2 针对数据卷的备份业务数据通常在卷里。备份卷需要在容器停止时或使用支持热备份的方式进行。对于命名卷my_app_data# 方法使用临时容器挂载卷和备份目录 docker run --rm \ -v my_app_data:/volume_data \ -v /backup:/backup \ alpine \ tar czf /backup/my_app_data_$(date %Y%m%d).tar.gz -C /volume_data .可以将此命令加入 cron 定时任务。4.3 紧急恢复检查清单当升级或迁移后出现严重问题需要回退时按此清单操作立即停止问题服务docker stop faulty_container检查 Docker 引擎状态systemctl status dockerjournalctl -u docker --no-pager -n 50快速回退 Docker 版本如果怀疑版本问题停止 Docker。卸载当前 Docker。使用备份记录中的旧版本号重新安装。恢复daemon.json备份。启动 Docker。恢复容器如果容器本身损坏用备份的镜像 (docker load) 和docker run命令重新创建。如果数据卷损坏用卷备份文件恢复。验证网络与存储恢复后检查容器网络连通性、卷挂载点权限和数据完整性。4.4 常见故障与排查点升级后容器启动失败先看日志docker logs container_id。检查依赖新版本 Docker 的存储驱动、日志驱动是否与旧容器配置冲突检查daemon.json和容器inspect信息。检查权限特别是用户命名空间映射相关配置。迁移后服务不通检查端口映射目标服务器防火墙是否开放了对应端口iptables -L -n或firewall-cmd --list-all。检查卷映射路径目标服务器上挂载的宿主机目录是否存在权限是否正确检查网络模式如果容器使用自定义网络或host网络迁移后网络环境是否一致docker ps无输出或命令卡住Docker 服务状态systemctl status docker。存储驱动问题尤其是从devicemapper迁移到overlay2后可能需要手动迁移数据。查看/var/lib/docker下的目录结构。磁盘空间df -h检查 Docker 数据目录所在磁盘是否已满。整个流程的核心是把 Docker 环境视为一个由“引擎配置、镜像、容器定义、数据卷”组成的整体。任何变动前先为这个整体拍一张“快照”。这张快照能让你在出现任何意外时都有一个清晰的回退路径而不是在故障面前手足无措。对于生产系统将关键步骤脚本化、定期备份制度化才是真正的“零风险”保障。