本文目录导读:

- 核心思路
- 方案一:恢复 Docker 数据卷 (Volume)
- 方案二:恢复挂载目录 (Bind Mount) 或 数据库数据
- 方案三:高级 - 使用 Docker Compose 恢复
- 关键注意事项 & 最佳实践
- 如何让脚本定时自动运行 (Cron)
要用脚本自动恢复Docker数据,关键是要先明确数据的存储方式(通常是数据卷或挂载目录)以及你使用的备份方案(比如压缩文件、数据库导出文件等)。
这里提供一个通用的、基于数据卷备份 (tar包) 的自动恢复脚本模板,并针对不同场景(如数据库、文件系统)给出具体示例。
核心思路
- 停止容器:防止在恢复过程中有数据写入,导致数据不一致。
- 删除旧容器:可选,有时需要先删除重建。
- 清空目标数据卷/目录:确保恢复的数据纯净。
- 解压备份文件:将备份包恢复到指定位置。
- 重启容器:使用新数据启动。
恢复 Docker 数据卷 (Volume)
这是最推荐的方式,数据都存储在 Docker 管理的卷中。
前提:你有一个通过 docker run --volumes-from 或 docker volume 创建的备份包(backup.tar.gz)。
恢复脚本:restore_volume.sh
#!/bin/bash
# --- 配置区域 ---
BACKUP_FILE="/path/to/your/backup.tar.gz" # 备份文件路径
TARGET_CONTAINER_NAME="my_app_container" # 目标容器名称 (需停止)
TARGET_VOLUME_NAME="my_app_data_volume" # 要恢复到的数据卷名称
# --- 脚本开始 ---
echo "开始恢复 Docker 数据卷: $TARGET_VOLUME_NAME ..."
# 1. 检查备份文件是否存在
if [ ! -f "$BACKUP_FILE" ]; then
echo "错误:备份文件 $BACKUP_FILE 不存在!"
exit 1
fi
# 2. 停止正在运行的容器 (如果正在运行)
RUNNING=$(docker ps -q --filter name="$TARGET_CONTAINER_NAME")
if [ -n "$RUNNING" ]; then
echo "正在停止容器 $TARGET_CONTAINER_NAME ..."
docker stop "$TARGET_CONTAINER_NAME"
fi
# 3. (可选) 如果容器存在,先删除它,方便后面重建卷
EXISTING=$(docker ps -a -q --filter name="$TARGET_CONTAINER_NAME")
if [ -n "$EXISTING" ]; then
echo "正在删除旧容器 $TARGET_CONTAINER_NAME ..."
docker rm "$TARGET_CONTAINER_NAME"
fi
# 4. 清空目标数据卷 (重要!)
# 使用一个临时容器来清空卷内容,避免直接操作卷目录权限问题
echo "正在清空数据卷: $TARGET_VOLUME_NAME ..."
docker run --rm -v "$TARGET_VOLUME_NAME":/data alpine sh -c "rm -rf /data/* /data/.* 2>/dev/null; echo 'Volume cleared'"
# 5. 恢复数据:将备份包解压到该卷
echo "正在解压备份文件到数据卷 ..."
# 创建一个临时容器,挂载卷,并解压备份
docker run --rm \
-v "$TARGET_VOLUME_NAME":/data \
-v "$(dirname "$BACKUP_FILE")":/backup_src \
alpine \
tar -xzf "/backup_src/$(basename "$BACKUP_FILE")" -C /data
echo "数据恢复完成!"
# 6. 重新创建并启动容器 (你需要修改这里的 docker run 命令以匹配你的实际情况)
echo "正在重新创建并启动容器 $TARGET_CONTAINER_NAME ..."
# 注意:这里需要替换成你原本的 docker run 指令
# 以下是一个示例:
docker run -d \
--name "$TARGET_CONTAINER_NAME" \
-v "$TARGET_VOLUME_NAME":/path/in/container \
your_image:tag
echo "容器 $TARGET_CONTAINER_NAME 已启动。"
echo "恢复流程结束。"
恢复挂载目录 (Bind Mount) 或 数据库数据
如果你的数据是直接挂载宿主机的目录(/data/mysql),脚本会更简单直接。
恢复脚本:restore_bindmount.sh (以 MySQL 为例)
#!/bin/bash
# --- 配置区域 ---
BACKUP_FILE="/backups/mysql_backup.sql.gz" # 数据库导出文件
DATA_DIR="/data/mysql" # 宿主机上的挂载目录
CONTAINER_NAME="mysql_container"
# --- 脚本开始 ---
# 1. 停止容器
docker stop "$CONTAINER_NAME"
# 2. (可选) 备份当前数据,以防万一
echo "备份当前数据到 /data/mysql_backup_$(date +%Y%m%d_%H%M%S) ..."
cp -r "$DATA_DIR" "${DATA_DIR}_backup_$(date +%Y%m%d_%H%M%S)" 2>/dev/null || echo "备份完成"
# 3. 清空旧数据 (谨慎操作!)
echo "正在清空 $DATA_DIR ..."
rm -rf "$DATA_DIR"/*
mkdir -p "$DATA_DIR"
# 4. 恢复数据 (如果是 mysql dump 文件)
echo "正在恢复 MySQL 数据库 ..."
gunzip < "$BACKUP_FILE" | docker exec -i "$CONTAINER_NAME" mysql -u root -p'yourpassword' your_database
# 或者,如果你备份的是整个数据目录 (/var/lib/mysql 的 tar包)
# tar -xzf "$BACKUP_FILE" -C "$DATA_DIR"
# 5. 重启容器
docker start "$CONTAINER_NAME"
echo "MySQL 数据恢复完成。"
高级 - 使用 Docker Compose 恢复
如果你的环境用 docker-compose 管理,推荐在脚本中调用 docker-compose 命令。
文件结构:
project/
├── docker-compose.yml
├── backups/
│ └── data_backup_20231001.tar.gz
└── scripts/
└── restore.sh
恢复脚本:scripts/restore.sh
#!/bin/bash BACKUP_FILE="../backups/data_backup_20231001.tar.gz" COMPOSE_PROJECT_DIR=".." VOLUME_NAME="project_db_data" # docker-compose 里定义的 volume cd "$COMPOSE_PROJECT_DIR" || exit # 1. 停止并移除所有容器 (保留卷) docker-compose down # 2. 清空卷并恢复数据 docker run --rm -v "$VOLUME_NAME":/data alpine sh -c "rm -rf /data/*" docker run --rm -v "$VOLUME_NAME":/data -v "$(pwd)/backups":/bak alpine tar -xzf "/bak/$(basename "$BACKUP_FILE")" -C /data # 3. 重启服务 docker-compose up -d echo "Docker Compose 环境已恢复。"
关键注意事项 & 最佳实践
| 项目 | 说明 |
|---|---|
| 权限问题 | 恢复时务必使用 alpine 或 busybox 镜像,通过容器内部操作,避免因宿主机用户权限 (如 UID/GID 不匹配) 导致容器内进程无法读写数据。 |
| 数据库恢复 | 不要直接替换数据库的数据目录文件 (如 /var/lib/mysql),除非你能保证版本完全一致且已停止服务,推荐使用数据库本身的导入工具 (如 mysql、pg_restore、mongorestore)。 |
| 数据一致性 | 恢复前必须停止正在写入的容器,否则恢复后数据可能损坏。 |
| 自动化的前置条件 | 脚本如果要全自动运行,需要提前定义好:备份文件名、目标卷名、容器名、数据库密码等,建议使用环境变量或配置文件来传入。 |
| 测试 | 建议先在一个隔离的测试环境中运行几次脚本,确保路径和命令都正确。 |
| 错误处理 | 脚本中可以增加 set -e(遇到错误退出)防止灾难性错误被忽略。 |
如何让脚本定时自动运行 (Cron)
将上述脚本保存为 /usr/local/bin/docker_restore.sh 并赋予执行权限 (chmod +x),然后通过 crontab 调用。
# 查看当前用户的 crontab crontab -e # 添加一行 (例如每天凌晨3点自动恢复) # 注意:自动恢复通常用于“从灾备节点同步”或“回滚到特定版本”,请谨慎设置 0 3 * * * /usr/local/bin/docker_restore.sh >> /var/log/docker_restore.log 2>&1
最核心的命令就是 docker run --rm -v 你的卷名:/data -v 你的备份目录:/backup alpine tar -xzf /backup/备份文件.tar.gz -C /data,将这条命令包装在停止容器、清理数据、重启容器的逻辑中,就能实现自动恢复。