Shell脚本如何恢复容器数据卷

wen 实用脚本 1

本文目录导读:

Shell脚本如何恢复容器数据卷

  1. 从备份文件恢复到数据卷
  2. 从另一个卷恢复(卷间复制)
  3. 恢复指定目录到数据卷
  4. 增量恢复(rsync方式)
  5. 恢复并验证完整性
  6. 完整的恢复脚本示例
  7. 使用示例
  8. 重要注意事项

在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"

重要注意事项

  1. 备份文件位置:备份文件应在主机系统上,通过卷挂载到临时容器
  2. 权限问题:注意文件权限,可能需要使用 --chmodchown 调整
  3. 运行容器:确保恢复期间没有其他容器访问该卷
  4. 事务完整性:对于数据库等有事务要求的应用,确保恢复前数据库已停止
  5. 版本兼容性:确保备份时的数据格式与当前应用版本兼容

建议在非生产环境先测试恢复流程,确保脚本正常工作。

抱歉,评论功能暂时关闭!