脚本分为两步骤,一个是备份,一个是恢复
备份
备份流程如下
1.打开终端,新建备份目录/backup ,并给权限
mkdir /backup & chmod -R 777 /backup
2.新建备份脚本,名字为backup.sh ,粘贴以下内容 (脚本是AI写的)
#!/bin/bash
echo "开始备份..."
docker ps -a --format '{{.Names}}' | while read container; do
echo "正在备份 $container ..."
docker commit "$container" "$container"
docker save "$container" > "/backup/$container.tar"
volumes=$(docker inspect --format='{{range .Mounts}}{{println .Name .Destination}}{{end}}' $container)
echo "$volumes" | while read volume destination; do
if [ -n "$volume" ]; then
echo "正在备份 $container 的数据卷 $volume ..."
docker run --rm --volumes-from "$container" -v /backup:/backup ubuntu tar cvf "/backup/${container}_data.tar" "$destination"
echo "备份 $container 的数据卷 $volume 完成."
fi
done
echo "备份 $container 完成."
docker inspect $container > "/backup/$container.json"
done
echo "所有容器备份完成."
3.回到终端,输入以下代码运行脚本,开始备份
bash backup.sh
文件夹内会出现3类文件
json是由docker inspect生成的该容器的配置
tar是镜像
_data.tar是容器数据卷的数据
4.小雅需要备份token,在任意文件夹内新建文件xiaoya_backup.sh,粘贴以下内容:(该脚本集备份+恢复为一体)
#!/bin/bash
# 检查 /etc/xiaoya 目录是否存在
if [ -d /etc/xiaoya ]; then
echo "目录 /etc/xiaoya 已存在。"
# 将 /etc/xiaoya 目录下的所有文件打包
echo "正在打包 /etc/xiaoya 目录..."
tar -cf xiaoya_backup.tar -C /etc xiaoya
# 显示打包信息
echo "打包完成,压缩包名为 xiaoya_backup.tar。"
echo "压缩包保存在当前目录下。"
else
echo "目录 /etc/xiaoya 不存在。"
# 创建 /etc/xiaoya 目录
echo "正在创建目录 /etc/xiaoya..."
mkdir /etc/xiaoya
# 设置 /etc/xiaoya 目录权限
echo "正在设置目录 /etc/xiaoya 的权限..."
chmod 755 /etc/xiaoya
# 解压缩 xiaoya_backup.tar 到 /etc/xiaoya 目录
echo "正在解压缩 xiaoya_backup.tar 到目录 /etc/xiaoya..."
tar -xf xiaoya_backup.tar -C /etc/xiaoya
# 显示解压缩信息
echo "解压缩完成。"
fi
5.终端输入bash xiaoya_backup.sh 执行,该脚本会备份/etc/xiaoya目录下所有文件到当前目录下
6.生成的备份文件为xiaoya_backup.tar ,如果当前目录下有这个文件,脚本会自动解压缩token文件到对应目录
恢复
1.如果在新机器上,首先需要安装docker
2.portainer管理容器需要提前手动恢复,hub的地址:https://hub.docker.com/r/6053537/portainer-ce
3.把备份好的文件拷贝到待恢复的机器上的/backup目录下
4.新建文件restore.sh,并粘贴以下内容:
#!/bin/bash
echo "开始恢复..."
for file in /backup/*.tar; do
if [[ $file == *"_data.tar" ]]; then
container=$(basename "$file" _data.tar)
echo "正在恢复 $container 的数据卷..."
docker run --rm --volumes-from "$container" -v /backup:/backup ubuntu tar xvf "$file"
echo "恢复 $container 的数据卷完成."
else
container=$(basename "$file" .tar)
echo "正在恢复 $container ..."
docker load < "$file"
echo "恢复 $container 完成."
fi
done
for file in /backup/*.json; do
container=$(basename "$file" .json)
echo "正在恢复 $container 的配置..."
config=$(jq -r '.[0] | "-d --name " + .Name + " --network " + .HostConfig.NetworkMode + " " + (.Config.Env | map(" -e " + .) | join("")) + " " + (.HostConfig.PortBindings | to_entries | map(" -p " + .value[0].HostIp + ":" + .value[0].HostPort + ":" + .key) | join("")) + " " + .Config.Image' $file)
docker run $config
echo "恢复 $container 的配置完成."
done
for file in /backup/*_data.tar; do
container=$(basename "$file" _data.tar)
echo "正在覆盖 $container 的数据卷..."
docker run --rm --volumes-from "$container" -v /backup:/backup ubuntu bash -c "cd / && tar xvf /backup/${container}_data.tar"
echo "覆盖 $container 的数据卷完成."
done
echo "所有容器恢复完成."
5.保存后,在终端执行命令开始恢复:
bash restore.sh
6.恢复后,docker需要重启,执行命令
systemctl restart docker
7.部分docker容器无法自动恢复,需要手动恢复,例如小雅xiaoya(详细的配置指南请点击打开 ),恢复前需要将上文备份的xiaoya的token备份文件xiaoya_token_backup.tar跟xiaoya_backup.sh复制在同个目录,然后输入以下执行恢复小雅token文件
bash xiaoya_backup.sh
8.恢复完token后再,参考 详细的配置指南 手动恢复小雅xiaoya
一键安装和更新容器,标准模式,打开端口 5678
bash -c "$(curl http://docker.xiaoya.pro/update_new.sh)"
一键安装和更新容器,host模式(推荐,软路由和NAS上更少网络故障,打开端口 5678)
bash -c "$(curl http://docker.xiaoya.pro/update_new.sh)" -s host
webdav 账号密码
用户: guest 密码: guest_Api789
重启就会自动更新数据库及搜索索引文件
docker restart xiaoya
9.小雅keeper清理缓存命令
每天自动清理一次。如果系统重启需要手动重新运行或把命令加入系统启动。
bash -c "$(curl -s https://xiaoyahelper.zengge99.eu.org/aliyun_clear.sh | tail -n +2)" -s 3 -tg
附:备份、恢复脚本的注释
备份脚本:
- 列出所有的 Docker 容器。
- 对每个容器执行以下操作:
- 使用
docker commit
命令创建一个新的镜像,该镜像的状态与当前运行的容器相同。 - 使用
docker save
命令将新创建的镜像保存为 tar 文件。 - 使用
docker inspect
命令获取容器的所有数据卷和它们在容器内的目标路径。 - 对每个数据卷执行以下操作:
- 如果数据卷存在,使用
docker run
命令启动一个新的临时容器,该容器从当前容器中挂载数据卷,并将备份目录挂载到/backup
。 - 在新的临时容器中,使用
tar
命令将数据卷的内容打包为 tar 文件。
- 如果数据卷存在,使用
- 使用
docker inspect
命令将容器的配置信息保存为 json 文件。
- 使用
恢复脚本:
- 对备份目录中的每个 tar 文件执行以下操作:
- 如果文件名以
_data.tar
结尾,那么这是一个数据卷的备份文件。使用docker run
命令启动一个新的临时容器,该容器从对应的容器中挂载数据卷,并将备份目录挂载到/backup
。然后在新的临时容器中,使用tar
命令将 tar 文件的内容解压到数据卷中。 - 否则,这是一个容器的备份文件。使用
docker load
命令从 tar 文件中加载镜像。
- 如果文件名以
- 对备份目录中的每个 json 文件执行以下操作:
- 这是一个容器的配置文件。使用
jq
命令从 json 文件中提取容器的配置信息,然后使用docker run
命令根据这些配置信息启动新的容器。
- 这是一个容器的配置文件。使用
- 对备份目录中的每个以
_data.tar
结尾的文件执行以下操作:- 这是一个数据卷的备份文件。使用
docker run
命令启动一个新的临时容器,该容器从对应的容器中挂载数据卷,并将备份目录挂载到/backup
。然后在新的临时容器中,使用tar
命令将 tar 文件的内容解压到数据卷中。
- 这是一个数据卷的备份文件。使用
备份方法2
检查目录/backup/docker_data/是否存在,如果不存在则创建它,并创建脚本文件 docker_data_backup.sh,并设置权限为755:
mkdir -p /backup/docker_data/ && touch /backup/docker_data/docker_data_backup.sh && chmod 755 /backup/docker_data/docker_data_backup.sh
打开该目录
cd /backup/docker_data
执行脚本命令:docker_data_backup.sh
bash docker_data_backup.sh
docker_data_backup.sh脚本内容如下:
#!/bin/bash
# Helper function for countdown timer
countdown() {
local seconds=$1
local temp
while [ $seconds -gt 0 ]; do
echo -ne "倒计时 $seconds\033[0K\r"
read -t 1 -n 1 temp
if [ "$temp" = "" ]; then
echo -e "\n"
return
fi
: $((seconds--))
done
}
# 获取当前的日期和时间,格式为YYYY_MM_DD_HH_MM
NOW=$(date +"%Y_%m_%d_%H_%M")
# 记录容器名称,并按顺序编号
echo "正在列出所有Docker容器(跳过含有 '1Panel' 的容器):"
declare -a CONTAINERS
i=1
for name in $(docker ps -a --format "{{.Names}}" | grep -v "1Panel")
do
echo "[$i] $name"
CONTAINERS[$i]=$name
i=$((i+1))
done
echo "请输入容器编号进行选择备份,用空格或者逗号隔开,或直接回车备份所有容器。输入 'exit' 退出。您有10秒时间输入:"
countdown 10
read -r -t 10 index
if [ -z "$index" ]
then
array=($(seq 1 ${#CONTAINERS[@]}))
echo "没有输入或输入超时,备份所有容器..."
elif [ "$index" == "exit" ]
then
echo "正在退出脚本..."
exit 0
else
IFS=', ' read -r -a array <<< "$index"
if [ ${#array[@]} -eq 0 ]
then
echo "未提供任何编号,正在退出脚本..."
exit 1
fi
fi
echo "待备份的容器目录如下:"
for element in "${array[@]}"
do
CONTAINER_NAME="${CONTAINERS[$element]}"
echo "===== 容器:$CONTAINER_NAME ====="
docker inspect --format '{{ range .Mounts }}{{ println .Source }}{{ end }}' "${CONTAINERS[$element]}"
done
echo -e "\n按回车键继续执行备份,其他任意键退出脚本。倒计时10秒后将自动继续。"
countdown 10
read -r -n1 -t 10 pre_input
if [ "$pre_input" != "" ]; then
echo -e "\n用户已选择退出脚本..."
exit 0
fi
echo -e "\n开始备份...\n"
BACKUP_ROOT_DIR="/backup/docker_data"
BACKUP_DIR="$BACKUP_ROOT_DIR/docker_data_backup_$NOW"
mkdir -p "$BACKUP_DIR"
LOG_FILE="$BACKUP_DIR/docker_data_backup_$NOW.log"
touch "$LOG_FILE"
log_backup() {
local message="$1"
echo "${message}" | tee -a "$LOG_FILE"
}
# 备份过程
for element in "${array[@]}"
do
CONTAINER_NAME="${CONTAINERS[$element]}"
log_backup "正在备份 ${CONTAINER_NAME}:"
MOUNT_INDEX=1
VOLUMES=$(docker inspect --format '{{ range .Mounts }}{{ println .Source }}{{ end }}' "${CONTAINERS[$element]}")
for volume in $VOLUMES; do
if [[ "$volume" == "/var/run/docker.sock" ]]; then
continue
fi
CONTAINER_BACKUP_SUBDIR="${CONTAINER_NAME}_${MOUNT_INDEX}"
CONTAINER_BACKUP_DIR="${BACKUP_DIR}/${CONTAINER_BACKUP_SUBDIR}"
mkdir -p "$CONTAINER_BACKUP_DIR"
if [ -d "$volume" ] || [ -f "$volume" ]; then
echo "正在备份:$volume"
cp -a "$volume/" "$CONTAINER_BACKUP_DIR/" && \
log_backup "${volume} 已备份到 ${CONTAINER_BACKUP_SUBDIR}"
else
log_backup "WARNING: $volume 不存在,将被跳过。"
fi
((MOUNT_INDEX++))
done
log_backup "容器 ${CONTAINER_NAME} 备份完成。"
echo -e "\n" | tee -a "$LOG_FILE"
done
echo "日志记录完成,正在创建备份的tar文件..."
FINAL_BACKUP_FILE="$BACKUP_ROOT_DIR/docker_data_backup_$NOW.tar"
tar -czf "$FINAL_BACKUP_FILE" -C "$BACKUP_ROOT_DIR" "docker_data_backup_$NOW" && \
echo "备份文件已打包为:$FINAL_BACKUP_FILE"
# 删除原始备份目录
if [ -f "$FINAL_BACKUP_FILE" ]; then
echo "正在删除原始备份文件夹..."
rm -rf "$BACKUP_DIR"
log_backup "原始备份目录 ${BACKUP_DIR} 已删除。"
echo "原始备份文件夹已删除。"
else
log_backup "备份tar文件创建失败,未删除原始备份目录。"
echo "备份tar文件创建失败,未删除原始备份目录。"
fi
# 保留最新两个备份文件并删除其他旧文件
echo "检查备份文件夹内的备份文件数量..."
cd "$BACKUP_ROOT_DIR"
BACKUP_FILES=$(ls docker_data_backup_*.tar)
TOTAL_BACKUPS=$(echo "$BACKUP_FILES" | wc -l)
if [ $TOTAL_BACKUPS -gt 2 ]; then
echo "已超过设定的备份文件数量,正在删除旧文件..."
# 删除最老的备份文件,只保留最新的两个
ls -1tr docker_data_backup_*.tar | head -n -2 | xargs rm -f
echo "旧备份文件已删除。"
fi
echo -e "所有选定容器的备份流程现已完成!"
这个脚本的主要用途是备份Docker容器相关的数据。以下是脚本执行的每一步详细解释:
- 设置倒计时函数(countdown):脚本定义了一个
countdown
函数,用于为用户提供一个简单的倒计时功能,在某些操作前给予用户时间作出反应。 - 获取当前时间和日期:脚本使用
date
命令获取当前的时间,格式为年_月_日_时_分(YYYY_MM_DD_HH_MM),这将用于创建具有时间戳的备份目录和备份文件。 - 列出所有Docker容器:脚本列出当前所有运行的Docker容器名称,但跳过所有名称中包含”1Panel”字符串的容器。之后,它提供一个接口让用户输入他们想要备份的特定容器编号。如果在10秒内没有响应或用户回车,脚本将备份所有容器。
- 接收用户输入:此步骤中,脚本等待用户指定要备份的Docker容器编号。用户输入的编号用于选定具体备份哪些容器。
- 决定备份哪些容器:根据用户的选择,脚本决定备份所有的容器或是只备份指定编号的容器。
- 创建备份目录和日志文件:脚本创建一个根备份目录以及一个特定的备份目录,路径包含了之前获取的时间戳。此外还创建了一个日志文件用于记录备份过程中的事件。
- 执行备份操作:针对每个选中备份的容器,脚本会获取其挂载点的数据,并将所有数据复制到之前创建的备份目录下。备份过程中的详细信息被写入日志文件。
- 创建备份tar包:脚本打包刚才创建的备份目录为一个
.tar
文件,这样备份文件会更方便地被存储和传输。 - 删除原始备份目录:一旦
.tar
备份文件创建完成,脚本会删除原来的备份目录来释放空间,只留下打包后的tar文件。 - 清理旧的备份文件:脚本检查备份根目录下所有现有的tar备份文件的数量。如果备份文件超过了设定的数量(在本例中为2个),脚本会删除最旧的备份文件,只保留两个最新的备份文件。
- 完成备份:脚本在备份完成后给出提示,显示所有选定的容器已经备份完成。此时,根据用户的备份意图,重要数据已被安全存储。
在使用这个脚本之前,请确保您对脚本有正确的理解,并已在安全的环境中进行了测试,特别是对于删除文件和目录的操作。错误的命令或者无意的使用可能会导致数据丢失。