├── Dockerfile ├── backup_mysql.sh ├── install.sh ├── .env.example ├── restic_backup.sh ├── LICENSE ├── restic_backup_sftp.sh ├── tool.sh ├── run.sh └── README.md /Dockerfile: -------------------------------------------------------------------------------- 1 | # 基于debian:bullseye-slim构建xz-backup镜像 2 | from debian:bullseye-slim 3 | # 设置时区 4 | ENV TZ=Asia/Shanghai 5 | # 设置工作路径 6 | WORKDIR /opt/xp-backup 7 | # 复制当前文件夹下所有文件到到容器内 8 | COPY . . 9 | # 执行安装脚本 10 | RUN bash install.sh 11 | # 常驻运行 12 | CMD ["bash", "run.sh"] 13 | -------------------------------------------------------------------------------- /backup_mysql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##### MySQL备份脚本 ##### 3 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin:/usr/local/mysql/bin 4 | export PATH 5 | 6 | #导入环境变量 7 | . data/.env 8 | 9 | BASEDIR='/opt/xp-backup' 10 | #当前时间 11 | ctime=$(date +%Y%m%d) 12 | #上一个月的时间,精确到月份就行了 13 | ptime=$(date -d "last month" +%Y%m) 14 | 15 | 16 | #开始备份数据库 17 | backup_mysql(){ 18 | # 进入运行目录 19 | cd ${BASEDIR} 20 | # 创建备份目录 21 | MYSQL_BACKUP_DIR=${BASEDIR}/backup/mysql/${ctime} 22 | mkdir -p ${MYSQL_BACKUP_DIR} 23 | # 使用mydumper备份数据库 24 | mydumper -h ${DB_HOST} -u ${DB_USER} -p ${DB_PASSWORD} --regex "^(?!(${DB_EXCLUDE}))" -o ${MYSQL_BACKUP_DIR} -c 25 | 26 | } 27 | 28 | #删除上个月的数据 29 | delete_expire_data(){ 30 | rm -rf ${BASEDIR}/backup/mysql/${ptime}* 31 | } 32 | 33 | backup_mysql && delete_expire_data -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RESTIC_VERSION="0.17.2" 4 | 5 | # 安装所需软件 6 | install_soft(){ 7 | apt-get update 8 | # 安装mydumper和定时任务 9 | apt-get install -y mydumper cron ca-certificates wget openssh-client 10 | 11 | wget https://soft.xiaoz.org/linux/restic_${RESTIC_VERSION}_linux_amd64 12 | mv restic_${RESTIC_VERSION}_linux_amd64 /usr/bin/restic 13 | chmod +x /usr/bin/restic 14 | chmod +x *.sh 15 | # 创建数据目录 16 | mkdir -p ./data 17 | # 设置环境变量 18 | echo 'export PATH="$PATH:/opt/xp-backup"' >> /etc/profile 19 | export PATH="$PATH:/opt/xp-backup" 20 | } 21 | 22 | 23 | 24 | # 清理 25 | clean(){ 26 | # 移除wget 27 | apt-get remove -y wget 28 | rm -rf /var/lib/apt/lists/* 29 | rm -rf /var/cache/apt/archives/*.deb 30 | rm -rf /var/cache/apt/archives/partial/*.deb 31 | } 32 | 33 | # 运行 34 | install_soft && clean -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # 备份目标类型,支持s3、sftp,默认s3 2 | STORAGE_TYPE="s3" 3 | # MySQL连接地址 4 | DB_HOST=127.0.0.1 5 | # MySQL用户名 6 | DB_USER=root 7 | # MySQL密码 8 | DB_PASSWORD=xxx 9 | #需要排除的数据库,用|分割 10 | DB_EXCLUDE="test|mysql|information_schema|sys" 11 | 12 | # AWS_ACCESS_KEY_ID 13 | AWS_ACCESS_KEY_ID=xxx 14 | # AWS_SECRET_ACCESS_KEY 15 | AWS_SECRET_ACCESS_KEY=xxx 16 | # AWS_S3_URL,格式如:s3.us-west-002.backblazeb2.com 17 | AWS_S3_URL=s3.us-west-002.backblazeb2.com 18 | # AWS_BUCKET_NAME,存储桶名称 19 | AWS_BUCKET_NAME="bucket_name" 20 | 21 | #restic密码,用于加密备份和解密恢复,一旦设置不要修改 22 | RESTIC_PASSWORD="xp_backup_password" 23 | 24 | #需要排除的目录,多个目录使用空格分割,比如:--exclude=dir1 --exclude=dir2 25 | EXCLUDE_DIRS='--exclude=default' 26 | 27 | # 定时备份MySQL的时间,默认每天凌晨2点 28 | CRON_TIME_MYSQL="0 2 * * *" 29 | # 定时备份文件夹的时间,默认每天凌晨3点 30 | CRON_TIME_DIR="0 3 * * *" 31 | 32 | # SFTP用户名 33 | SFTP_USER="sftp_user" 34 | # SFTP主机 35 | SFTP_HOST="sftp_host" 36 | # SFTP端口 37 | SFTP_PORT=22 -------------------------------------------------------------------------------- /restic_backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #resitc备份脚本 3 | ##### restic备份脚本 ##### 4 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin:/usr/local/mysql/bin 5 | export PATH 6 | 7 | #导入环境变量 8 | . data/.env 9 | 10 | myip=$(hostname -I | awk '{print $1}') 11 | new_hostname=${HOSTNAME}_${myip} 12 | 13 | export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} 14 | export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} 15 | export RESTIC_PASSWORD_FILE=./data/.restic_pass 16 | 17 | #restic备份 18 | restic_backup(){ 19 | cd /opt/xp-backup 20 | 21 | # 设置密码 22 | # echo ${RESTIC_PASSWORD} > ./data/.restic_pass 23 | 24 | #初始化存储,格式为:s3.us-west-002.backblazeb2.com/bucket_name/dir 25 | S3_PATH=${AWS_S3_URL}/$AWS_BUCKET_NAME/${new_hostname} 26 | restic -r s3:${S3_PATH} init 27 | #备份数据 28 | # 需要备份的目录 29 | BACKUP_DIR="/opt/xp-backup/backup" 30 | restic ${EXCLUDE_DIRS} -r s3:${S3_PATH} --verbose backup ${BACKUP_DIR} 31 | 32 | } 33 | 34 | # 运行 35 | restic_backup -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 XiupingZou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /restic_backup_sftp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #resitc备份脚本 3 | ##### restic备份脚本 ##### 4 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin:/usr/local/mysql/bin 5 | export PATH 6 | 7 | #导入环境变量 8 | . data/.env 9 | 10 | myip=$(hostname -I | awk '{print $1}') 11 | new_hostname=${HOSTNAME}_${myip} 12 | 13 | export RESTIC_PASSWORD_FILE=./data/.restic_pass 14 | 15 | #restic备份 16 | restic_backup(){ 17 | cd /opt/xp-backup 18 | 19 | # 设置密码 20 | # echo ${RESTIC_PASSWORD} > ./data/.restic_pass 21 | 22 | #初始化存储,格式为:s3.us-west-002.backblazeb2.com/bucket_name/dir 23 | # S3_PATH=${AWS_S3_URL}/$AWS_BUCKET_NAME/${new_hostname} 24 | # sftp://user@[::1]:2222//srv/restic-repo 25 | # 先执行命令创建目标路径 26 | echo "mkdir ./${new_hostname}" | sftp -oBatchMode=no -P $SFTP_PORT $SFTP_USER@$SFTP_HOST 27 | restic -r sftp://${SFTP_USER}@${SFTP_HOST}:${SFTP_PORT}/./${new_hostname} init 28 | # 运行清理 29 | ./tool.sh clear 30 | #备份数据 31 | # 需要备份的目录 32 | BACKUP_DIR="/opt/xp-backup/backup" 33 | restic ${EXCLUDE_DIRS} -r sftp://${SFTP_USER}@${SFTP_HOST}:${SFTP_PORT}/./${new_hostname} --verbose backup ${BACKUP_DIR} 34 | } 35 | 36 | # 运行 37 | restic_backup -------------------------------------------------------------------------------- /tool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ##### name:用于查看备份列表 ##### 3 | 4 | ##### restic备份脚本 ##### 5 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin:/usr/local/mysql/bin 6 | export PATH 7 | 8 | # 进入运行目录 9 | cd /opt/xp-backup 10 | #导入环境变量 11 | . data/.env 12 | 13 | export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} 14 | export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} 15 | # 设置密码 16 | echo ${RESTIC_PASSWORD} > ./data/.restic_pass 17 | export RESTIC_PASSWORD_FILE=./data/.restic_pass 18 | 19 | myip=$(hostname -I | awk '{print $1}') 20 | new_hostname=${HOSTNAME}_${myip} 21 | 22 | #获取参数1 23 | ARG=$1 24 | #获取参数2 25 | ARG2=$2 26 | #获取参数3 27 | ARG3=$3 28 | 29 | #初始化存储,格式为:s3.us-west-002.backblazeb2.com/bucket_name/dir 30 | S3_PATH=${AWS_S3_URL}/$AWS_BUCKET_NAME/${new_hostname} 31 | S3_CONN=s3:${S3_PATH} 32 | # SFTP 33 | SFTP_CONN=sftp://${SFTP_USER}@${SFTP_HOST}:${SFTP_PORT}/./${new_hostname} 34 | 35 | # 根据STORAGE_TYPE选择存储类型 36 | case ${STORAGE_TYPE} in 37 | 's3') 38 | # S3 39 | CONN=$S3_CONN 40 | SHELL_NAME='restic_backup.sh' 41 | ;; 42 | 'sftp') 43 | # SFTP 44 | CONN=$SFTP_CONN 45 | SHELL_NAME='restic_backup_sftp.sh' 46 | ;; 47 | *) 48 | CONN=$S3_CONN 49 | SHELL_NAME='restic_backup.sh' 50 | esac 51 | 52 | case ${ARG} in 53 | 'list') 54 | #查看备份列表 55 | restic -r ${CONN} snapshots 56 | ;; 57 | 'restore') 58 | #恢复备份 59 | restic -r ${CONN} restore ${ARG2} --target ${ARG3} 60 | ;; 61 | 'clear') 62 | #解除锁定 63 | restic -r ${CONN} unlock 64 | # 清理快照,并保存最后30个,如果保留3个月,则用--keep-monthly 3 65 | restic -r ${CONN} forget --prune --keep-last 60 66 | ;; 67 | 'backup') 68 | bash ${SHELL_NAME} 69 | ;; 70 | *) 71 | echo 'args not found!' 72 | esac -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 导入定时任务 4 | run(){ 5 | # 检查./data/.env是否存在 6 | if [ ! -f "./data/.env" ]; then 7 | # 不存在,则复制一个 8 | cp .env.example ./data/.env 9 | fi 10 | # 导入环境变量 11 | . ./data/.env 12 | 13 | # 检查restic文件是否存在 14 | if [ ! -f "./data/.restic_pass" ]; then 15 | # 不存在,则设置 16 | # 设置密码 17 | echo ${RESTIC_PASSWORD} > ./data/.restic_pass 18 | export RESTIC_PASSWORD_FILE=./data/.restic_pass 19 | fi 20 | 21 | # 查看密码文件的内容,判断是否为空内容 22 | if [ ! -s "./data/.restic_pass" ]; then 23 | echo 'Please modify the .env file and set the RESTIC_PASSWORD variable.' 24 | exit 25 | fi 26 | 27 | 28 | # 写入定时任务 29 | rm -rf /etc/cron.d/xp-backup 30 | # 如果CRON_TIME_MYSQL不为空才写入 31 | if [ ! -z ${CRON_TIME_MYSQL} ]; then 32 | echo "${CRON_TIME_MYSQL} root cd /opt/xp-backup && ./backup_mysql.sh >> /var/log/xp-backup.log 2>&1" >> /etc/cron.d/xp-backup 33 | fi 34 | # echo "${CRON_TIME_MYSQL} root cd /opt/xp-backup && ./backup_mysql.sh >> /var/log/xp-backup.log 2>&1" >> /etc/cron.d/xp-backup 35 | # 判断类型是s3还是sftp 36 | if [ ${STORAGE_TYPE} == 'sftp' ]; then 37 | echo "${CRON_TIME_DIR} root cd /opt/xp-backup && ./restic_backup_sftp.sh >> /var/log/xp-backup.log 2>&1" >> /etc/cron.d/xp-backup 38 | else 39 | echo "${CRON_TIME_DIR} root cd /opt/xp-backup && ./restic_backup.sh >> /var/log/xp-backup.log 2>&1" >> /etc/cron.d/xp-backup 40 | fi 41 | # echo "${CRON_TIME_DIR} root cd /opt/xp-backup && ./restic_backup.sh >> /var/log/xp-backup.log 2>&1" >> /etc/cron.d/xp-backup 42 | # 赋予执行权限 43 | chmod 0644 /etc/cron.d/xp-backup 44 | # 添加计划任务 45 | crontab /etc/cron.d/xp-backup 46 | # 启动计划任务 47 | /etc/init.d/cron start 48 | # 查看日志 49 | touch /var/log/xp-backup.log 50 | tail -f /var/log/xp-backup.log 51 | } 52 | 53 | # 运行 54 | run -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xp-backup 2 | 3 | 基于Docker容器的备份方案,使用restic工具定期将您的MySQL数据库和文件加密备份到AWS S3。 4 | 5 | ### 特性 6 | 7 | * 加密备份 8 | * 增量备份 9 | * 自动备份MySQL数据库 10 | * 支持添加多个备份路径 11 | * 支持备份到S3或SFTP 12 | * 支持路径排除 13 | * 支持快捷命令查看备份列表(快照) 14 | * 支持快捷命令自动恢复指定备份(快照) 15 | 16 | 17 | ## 安装使用 18 | 19 | 在使用之前,请确保您熟悉Linux并掌握了Docker容器使用,此工具推荐给运维人员使用,小白请勿尝试!!! 20 | 21 | 1) 已经安装Docker环境,并安装了Docker Compose工具 22 | 2) 创建`docker-compose.yaml`文件,内容为: 23 | 24 | ```yaml 25 | version: '3' 26 | services: 27 | xp-backup: 28 | image: helloz/xp-backup 29 | container_name: xp-backup 30 | restart: always 31 | environment: 32 | - PATH=/opt/xp-backup:$PATH 33 | volumes: 34 | - ./data:/opt/xp-backup/data 35 | - /data/apps:/opt/xp-backup/backup/apps 36 | - /data/backup/mysql:/opt/xp-backup/backup/mysql 37 | # 如果使用SFTP备份方式,还需要挂载私钥文件 38 | # - ./data/id_rsa:/root/.ssh/id_rsa 39 | # - ~/.ssh/known_hosts:/root/.ssh/known_hosts:ro 40 | network_mode: "host" 41 | ``` 42 | 43 | 如果您有更多需要备份的目录,可以继续添加挂载,需要挂载到容器内部的`/opt/xp-backup/backup`目录下,比如: 44 | 45 | * `/test1/dir:/opt/xp-backup/backup/test1` 46 | * `/test2/dir:/opt/xp-backup/backup/test2` 47 | 48 | 输入命令`docker-compose up -d`启动容器,启动完毕后回在您本地挂载目录`./data`下生成2个隐藏文件,分别是: 49 | 50 | * `.env`:环境变量文件 51 | * `.restic_pass`: restic密码文件(加密备份和解密需要) 52 | 53 | 您可以输入命令`ls -al`来查看这2个文件,首次运行后自动生成这2个文件,然后删除容器:`docker-compose down`,并对这2个文件做出修改,修改完毕后再次启动容器:`docker-compose up -d` 54 | 55 | **`.env`环境变量说明:** 56 | 57 | ```bash 58 | # 备份目标类型,支持s3、sftp,默认s3 59 | STORAGE_TYPE="s3" 60 | # MySQL连接地址 61 | DB_HOST=127.0.0.1 62 | # MySQL用户名 63 | DB_USER=root 64 | # MySQL密码 65 | DB_PASSWORD=xxx 66 | #需要排除的数据库,用|分割 67 | DB_EXCLUDE="test|mysql|information_schema|sys" 68 | 69 | # AWS_ACCESS_KEY_ID 70 | AWS_ACCESS_KEY_ID=xxx 71 | # AWS_SECRET_ACCESS_KEY 72 | AWS_SECRET_ACCESS_KEY=xxx 73 | # AWS_S3_URL,格式如:s3.us-west-002.backblazeb2.com 74 | AWS_S3_URL=s3.us-west-002.backblazeb2.com 75 | # AWS_BUCKET_NAME,存储桶名称 76 | AWS_BUCKET_NAME="bucket_name" 77 | 78 | #restic密码,用于加密备份和解密恢复,一旦设置不要修改 79 | RESTIC_PASSWORD="xp_backup_password" 80 | 81 | #需要排除的目录,多个目录使用空格分割,比如:--exclude=dir1 --exclude=dir2 82 | EXCLUDE_DIRS='--exclude=default' 83 | 84 | # 定时备份MySQL的时间,默认每天凌晨2点 85 | CRON_TIME_MYSQL="0 2 * * *" 86 | # 定时备份文件夹的时间,默认每天凌晨3点 87 | CRON_TIME_DIR="0 3 * * *" 88 | # SFTP用户名 89 | SFTP_USER="sftp_user" 90 | # SFTP主机 91 | SFTP_HOST="sftp_host" 92 | # SFTP端口 93 | SFTP_PORT=22 94 | ``` 95 | 96 | **.restic_pass 密码文件** 97 | 98 | 需要自行设置一个复制的字符串,默认为:`xp_backup_password`,一旦设置后,请不要随意修改。 99 | 100 | `.env`和`.restic_pass`设置完毕后,输入命令:`docker-compose restart`重启一次容器,至此已经全部设置完毕,容器将根据您的定时任务定期将MySQL数据库和文件数据加密备份至AWS S3 101 | 102 | **补充** 103 | 104 | 如果您选择使用SFTP作为备份方式,需要进行以下操作: 105 | 106 | 1. 修改`.env`为`STORAGE_TYPE="sftp"` 107 | 2. 设置SFTP相关参数,包括`STORAGE_TYPE`/`SFTP_HOST`/`SFTP_PORT` 108 | 3. 容器启动之前先执行`ssh -i /path/to/your_private_key @ -p ` 109 | 1. `/path/to/your_private_key`私钥文件路径 110 | 2. ``服务器用户名 111 | 3. ``服务器IP 112 | 4. ``服务器端口 113 | 114 | > 注意:如果不提前执行SSH命令登录,可能会出现交互式询问,`restic`无法绕过将导致备份失败! 115 | 116 | ### 常用命令 117 | 118 | * 立即备份MySQL:`docker exec -it xp-backup backup_mysql.sh` 119 | * 立即备份文件数据:`docker exec -it xp-backup restic_backup.sh` 120 | * 查看备份列表:`docker exec -it xp-backup tool.sh list` 121 | * 清理并保留最近60个快照:`docker exec -it xp-backup tool.sh clear` 122 | * 将指定快照恢复到指定目录下:`docker exec -it xp-backup tool.sh restore snapshot_id target_path` 123 | * `snapshot_id`:快照ID 124 | * `target_path`:目标路径(将数据恢复到这个路径) 125 | 126 | ### 技术支持 127 | 128 | 如果遇到BUG或者新功能请求,请在[issues](https://github.com/helloxz/xp-backup/issues)进行反馈,如果需要人工技术支持(需要付费),通过下面方式联系我。 129 | 130 | * 微信:`xiaozme` 131 | * Telegram:`xiaozme` --------------------------------------------------------------------------------