之前两篇文章的整合脚本

#命名为 backup_container_all.sh
#运行前:
chmod +x backup_container_all.sh && ./backup_container_all.sh
#!/bin/bash

# Define the timestamped backup directory name
timestamp=$(date +"%Y%m%d%H%M%S")
backup_dir="/home/backup_${timestamp}"

# Check if jq is installed
if ! command -v jq &> /dev/null; then
    read -p "jq is not installed. Would you like to install it? (y/n) " jq_install
    if [[ "$jq_install" == "y" ]]; then
        apt update && apt install -y jq
    else
        echo "jq is required for this script to run. Exiting."
        exit 1
    fi
fi

# Function to do a backup of all containers' compose files
do_autocompose_all() {
    # Create backup directory
    mkdir -p "${backup_dir}/all"
    
    # Backup all container configurations into a single compose file
    docker run --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/red5d/docker-autocompose $(docker ps -aq) > "${backup_dir}/all/docker-compose-generated.yml"
}

# Function to backup the /root directory
do_backup_root() {
    mkdir -p "${backup_dir}/all"
    tar -czvf "${backup_dir}/all/root_backup.tar.gz" -C /root .
}

# Function to backup all volumes
do_backup_volumes() {
    # Create a temporary directory to store backups of all volumes
    local volumes_backup_temp="/tmp/docker_volumes_backup_${timestamp}"
    mkdir -p $volumes_backup_temp

    # Variable to save the total size of all volumes
    total_size=0

    # Calculate size of each volume
    for volume in $(docker volume ls -q); do
        size=$(docker run --rm -v ${volume}:/from_volume busybox du -sh /from_volume 2>/dev/null | cut -f1)
        echo "Volume ${volume} size: $size"
        total_size=$(($total_size + $(docker run --rm -v ${volume}:/from_volume busybox du -sk /from_volume 2>/dev/null | cut -f1)))
    done

    # Convert size to appropriate unit
    total_size_MB=$(($total_size / 1024))
    echo "Total size of all volumes: ${total_size_MB}MB"

    # Ask the user for confirmation to proceed
    read -p "Do you want to continue with the backup? (y/n) " answer

    if [ "$answer" != "y" ]; then
        echo "Backup aborted by user."
        exit 0
    fi

    # Backup each individual volume
    for volume in $(docker volume ls -q); do
        docker run --rm -v ${volume}:/from_volume -v $volumes_backup_temp:/backup busybox tar czf /backup/${volume}.tar.gz -C /from_volume ./
    done

    # Archive all the individual backup files into one
    cd /tmp
    tar czf docker_volumes_backup_${timestamp}.tar.gz docker_volumes_backup_${timestamp}

    # Show the size of the backup file
    echo "Size of the backup: $(du -sh docker_volumes_backup_${timestamp}.tar.gz | cut -f1)"

    # Move the archive to the backup directory
    mv docker_volumes_backup_${timestamp}.tar.gz "${backup_dir}/all/"

    # Cleanup temporary files
    rm -rf $volumes_backup_temp
}

# Function to backup an individual container's data
do_individual_container_backup() {
    local container_id="$1"
    local individual_backup_dir="${backup_dir}/${container_id}"

    # Ensure the container backup directory exists
    mkdir -p "${individual_backup_dir}"

    # Generate docker-compose.yml for the container
    docker run --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/red5d/docker-autocompose $container_id > "${individual_backup_dir}/docker-compose.yml"

    # Backup volumes associated with the container
    local volumes=$(docker inspect $container_id | jq -r '.[0].Mounts[]? | select(.Type == "volume") .Name')

    for volume in $volumes; do
        docker run --rm -v ${volume}:/from_volume -v ${individual_backup_dir}:/backup busybox tar czf /backup/${volume}.tar.gz -C /from_volume ./
    done

    # Backup bind mounts associated with the container
    local binds=$(docker inspect $container_id | jq -r '.[0].Mounts[]? | select(.Type == "bind") .Source')

    for bind in $binds; do
        # Exclude all mounts except those under /root/
        if [[ $bind == /root/* ]]; then
            local bind_name=$(basename $bind)
            tar -czvf "${individual_backup_dir}/${bind_name}.tar.gz" -C $bind .
        fi
    done
}

# ... [前面的代码保持不变] ...

# Main execution wrapped in a loop
while true; do
    echo "Choose an option:"
    echo "1. Run autocompose-all"
    echo "2. Backup /root directory"
    echo "3. Backup all volumes"
    echo "4. Backup all (1 -> 2 -> 3)"
    echo "5. Backup individual container"
    echo "6. Continue to backup another container"
    echo "7. Exit"
    read -p "Enter your choice (1-7): " choice

    case $choice in
        1)
            do_autocompose_all
            ;;
        2) 
            do_backup_root
            ;;
        3) 
            do_backup_volumes
            ;;
        4)
            do_autocompose_all
            do_backup_root
            do_backup_volumes
            ;;
        5)
            echo "Listing containers..."
            IFS=$'\n'
            containers=($(docker ps -a --format '{{.ID}}:{{.Names}}'))
            unset IFS
            for i in "${!containers[@]}"; do
                echo "$((i+1))) ${containers[$i]}"
            done
            read -p "#? " container_choice
            if [[ $container_choice -gt 0 && $container_choice -le ${#containers[@]} ]]; then
                IFS=':' read -ra selected_container <<< "${containers[$((container_choice-1))]}"
                do_individual_container_backup "${selected_container[0]}"
            else
                echo "Invalid choice."
            fi
            ;;
        6)
            continue
            ;;
        7)
            echo "Exiting..."
            exit 0
            ;;
        *)
            echo "Invalid choice."
            ;;
    esac

    # Prompt to continue or exit after each choice
    read -p "Do you want to continue? (y/n) " cont
    if [[ $cont != "y" ]]; then
        echo "Exiting..."
        exit 0
    fi
done



注意事项:

  1. 脚本使用了 jq 命令来解析 Docker 的 JSON 输出。确保已经在服务器上安装了 jq

  2. 在使用该脚本之前,对其进行一些测试以确保它在你的环境中正确运行是非常重要的。

在脚本中,jq 是用于解析 Docker 容器的详细信息,特别是挂载的卷信息。当你为单个容器备份时,你可能希望知道哪些卷被挂载到了这个容器。因此,我们使用 Docker 的 inspect 命令来获取关于容器的详细信息,这个命令返回一个 JSON 格式的输出。

这是脚本中使用 jq 的相关部分:

volumes=$(docker inspect $container_id | jq -r '.[0].Mounts[]? | select(.Type == "volume") | .Name')

这段代码做了以下事情:

  1. 使用 docker inspect 获取容器的详细信息。

  2. 使用 jq 从 JSON 输出中提取 volume 的名称。

  3. .Mounts[]?:遍历所有挂载点。

  4. select(.Type == "volume"):从所有挂载点中选择 volume 类型的挂载点。

  5. .Name:获取 volume 的名称。

总之,jq 是一个非常强大的命令行 JSON 解析器,允许你从复杂的 JSON 结构中轻松提取信息。在此脚本中,它用于确保我们准确地提取了与容器关联的所有 volumes 的名称。

文章作者: scotee
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 思考题Scotee
喜欢就支持一下吧