本文目录导读:

在Shell脚本中恢复容器数据卷,通常涉及以下几个方面,以下是几种常见场景及对应的Shell脚本方法:
从备份文件恢复到数据卷
#!/bin/bash
# 配置变量
BACKUP_DIR="/path/to/backups"
BACKUP_FILE="volume_backup_2024.tar.gz"
VOLUME_NAME="myapp_data"
CONTAINER_NAME="myapp_container"
# 恢复函数
restore_volume() {
echo "开始恢复数据卷: $VOLUME_NAME"
# 检查备份文件是否存在
if [ ! -f "$BACKUP_DIR/$BACKUP_FILE" ]; then
echo "错误: 备份文件不存在: $BACKUP_DIR/$BACKUP_FILE"
exit 1
}
# 停止正在运行的容器
echo "停止容器: $CONTAINER_NAME"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
# 创建临时容器并恢复数据
echo "恢复数据到卷..."
docker run --rm \
-v "$VOLUME_NAME:/volume" \
-v "$BACKUP_DIR:/backup" \
alpine \
sh -c "rm -rf /volume/* /volume/..?* /volume/.[!.]* && tar xzf /backup/$BACKUP_FILE -C /volume"
# 重新启动容器
echo "启动容器: $CONTAINER_NAME"
docker start "$CONTAINER_NAME"
echo "恢复完成!"
}
# 执行恢复
restore_volume
从另一个卷恢复(卷间复制)
#!/bin/bash
# 卷间恢复
restore_from_another_volume() {
SOURCE_VOLUME="source_volume_backup"
TARGET_VOLUME="target_data_volume"
# 使用临时容器复制数据
docker run --rm \
-v "$SOURCE_VOLUME:/from" \
-v "$TARGET_VOLUME:/to" \
alpine \
sh -c "cp -a /from/. /to/"
echo "已从 $SOURCE_VOLUME 恢复到 $TARGET_VOLUME"
}
恢复指定目录到数据卷
#!/bin/bash
# 从主机目录恢复到卷
restore_from_host_directory() {
LOCAL_PATH="/host/data/backup"
VOLUME_NAME="app_config"
# 恢复
docker run --rm \
-v "$VOLUME_NAME:/volume" \
-v "$LOCAL_PATH:/backup" \
alpine \
sh -c "cp -a /backup/. /volume/"
echo "已从 $LOCAL_PATH 恢复到 $VOLUME_NAME"
}
增量恢复(rsync方式)
#!/bin/bash
# 增量恢复
incremental_restore() {
SNAPSHOT_DIR="/snapshots/app_data_20240101"
VOLUME_NAME="app_data_production"
# 创建临时容器进行rsync恢复
docker run --rm \
-v "$VOLUME_NAME:/target" \
-v "$SNAPSHOT_DIR:/source:ro" \
alpine \
sh -c "
apk add --no-cache rsync
rsync -av --delete /source/ /target/
"
echo "增量恢复完成"
}
恢复并验证完整性
#!/bin/bash
# 恢复并验证
restore_with_validation() {
BACKUP_FILE="database_backup.sql.gz"
VOLUME_NAME="mysql_data"
CONTAINER_NAME="mysql_prod"
# 暂停应用
echo "暂停应用服务..."
docker stop "$CONTAINER_NAME"
# 恢复数据
echo "正在恢复数据库..."
docker run --rm \
-v "$VOLUME_NAME:/var/lib/mysql" \
-v "$(pwd)/backups:/backup" \
alpine \
sh -c "
rm -rf /var/lib/mysql/*
gunzip -c /backup/$BACKUP_FILE > /tmp/restore.sql
"
# 启动容器并验证
docker start "$CONTAINER_NAME"
sleep 5
# 验证恢复是否成功
if docker exec "$CONTAINER_NAME" mysql -u root -e "SHOW DATABASES;" > /dev/null 2>&1; then
echo "数据库恢复验证成功"
else
echo "警告: 数据库恢复可能需要手动验证"
fi
}
完整的恢复脚本示例
#!/bin/bash
set -euo pipefail
# 配置
BACKUP_ROOT="/backups/docker_volumes"
LOG_FILE="/var/log/volume_restore.log"
TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 错误处理
error_exit() {
log "错误: $1"
exit 1
}
# 检查依赖
check_prerequisites() {
command -v docker >/dev/null 2>&1 || error_exit "Docker未安装"
command -v tar >/dev/null 2>&1 || error_exit "tar未安装"
}
# 列出可用备份
list_backups() {
log "可用的备份文件:"
ls -lh "$BACKUP_ROOT/"*.tar.gz 2>/dev/null || echo "没有找到备份文件"
}
# 恢复数据卷
restore_volume() {
local volume_name="$1"
local backup_file="$2"
# 检查卷是否存在
if ! docker volume inspect "$volume_name" >/dev/null 2>&1; then
log "创建新卷: $volume_name"
docker volume create "$volume_name"
fi
# 停止使用该卷的容器
log "查找并停止使用卷 $volume_name 的容器..."
docker ps -q --filter "volume=$volume_name" | while read container; do
log "停止容器: $container"
docker stop "$container" 2>/dev/null || true
done
# 执行恢复
log "开始恢复卷 $volume_name 从 $backup_file..."
docker run --rm \
-v "$volume_name:/volume" \
-v "$BACKUP_ROOT:/backup" \
alpine \
sh -c "
rm -rf /volume/* /volume/..?* /volume/.[!.]* 2>/dev/null
tar xzf /backup/$backup_file -C /volume
chmod -R 755 /volume
" || error_exit "恢复失败"
log "卷 $volume_name 恢复完成"
}
# 主函数
main() {
check_prerequisites
# 显示备份列表
list_backups
# 如果提供了参数,则执行恢复
if [ $# -ge 2 ]; then
local volume_name="$1"
local backup_file="$2"
if [ ! -f "$BACKUP_ROOT/$backup_file" ]; then
error_exit "备份文件不存在: $BACKUP_ROOT/$backup_file"
fi
restore_volume "$volume_name" "$backup_file"
else
log "用法: $0 <卷名> <备份文件名>"
log "示例: $0 myapp_data backup_20240101.tar.gz"
fi
}
# 执行
main "$@"
使用示例
# 1. 从备份文件恢复 ./restore_volume.sh myapp_data latest_backup.tar.gz # 2. 从指定备份恢复 ./restore_volume.sh prod_data snapshot_20240101.tar.gz # 3. 使用简单命令恢复 docker run --rm -v my_volume:/volume -v /backups:/backup alpine sh -c "tar xzf /backup/backup.tar.gz -C /volume"
重要注意事项
- 备份文件位置:备份文件应在主机系统上,通过卷挂载到临时容器
- 权限问题:注意文件权限,可能需要使用
--chmod或chown调整 - 运行容器:确保恢复期间没有其他容器访问该卷
- 事务完整性:对于数据库等有事务要求的应用,确保恢复前数据库已停止
- 版本兼容性:确保备份时的数据格式与当前应用版本兼容
建议在非生产环境先测试恢复流程,确保脚本正常工作。