利用 Github Actions 备份数据库
数据无价,做好备份至关重要!用宝塔面板时,数据库自动备份到 OSS,轻松省事。现在换用 Docker 后,只能手动备份,有点麻烦,要是能自动化就好了。
上周末想到利用 Github Actions 实现自动备份,因为不太熟悉脚本,折腾了两天,好歹也是折腾出了结果。原理还是挺简单的,通过 Github Actions 定时执行任务,远程连接到数据库并转储程文件,将文件通过 Telegram Bot 发送至指定群组。当然,除了这个额外还加了一个发送至支持 S3 协议的云存储服务。其实还能扩展更多,比如 FTP、WebDAV 等等。
准备
Telegram
创建机器人
点击BotFather,按照提示创建机器人,并获得机器人的 Token。
创建频道
这里使用 Telegram Desktop 版为例,创建频道并把刚刚的机器人添加为频道管理员。
获取频道 ID
点击Get Chat ID机器人并且添加,点击下方Channel按钮,选择刚刚创建的频道,即可看到频道 ID。
注意:前面的减号也是它的一部分。
S3 存储
这里使用七牛云的存储服务,其他的自行尝试,比如赛博菩萨的R2。
配置
创建仓库
点击New Repository创建一个仓库,用于存放备份脚本,建议使用私密仓库。当然,你也可以使用你原本已有的仓库,怎么样都行,总之,要有个仓库。
创建 secrets
点击New repository secret,依次添加下面的必填密钥。
密钥名称 | 是否必填 | 默认值 | 说明 |
---|---|---|---|
DB_BACKUP_MYSQL_IP | 是 | 数据库的IP | |
DB_BACKUP_MYSQL_PORT | 否 | 3306 | 数据库的端口 |
DB_BACKUP_MYSQL_USERNAME | 是 | 数据库的用户名,建议只读用户 | |
DB_BACKUP_MYSQL_PASSWORD | 是 | 数据库的密码,建议只读用户 | |
DB_BACKUP_MYSQL_DATABASE | 是 | 数据库的名称 | |
DB_BACKUP_TELEGRAM_CHAT_ID | 是 | Telegram 频道 ID | |
DB_BACKUP_TELEGRAM_BOT_TOKEN | 是 | Telegram 机器人 Token | |
DB_BACKUP_S3_ACCESS_KEY | 是 | S3 存储服务的 AccessKey | |
DB_BACKUP_S3_SECRET_KEY | 是 | S3 存储服务的 SecretKey | |
DB_BACKUP_S3_HOST_BASE | 是 | S3 存储服务的域名 | |
DB_BACKUP_S3_HOST_BUCKET | 是 | S3 存储服务的域名 | |
DB_BACKUP_S3_BUCKET_NAME | 是 | S3 存储空间的名称 | |
DB_BACKUP_S3_PREFIX_PATH | 是 | S3 存储空间下的路径 | |
DB_BACKUP_S3_DAYS | 否 | 30 | S3 存储空间数据保留天数 |
DB_BACKUP_S3_USE_HTTPS | 否 | true | S3 是否使用 HTTPS |
DB_BACKUP_S3_SIGNATURE_V2 | 否 | false | S3 是否使用签名 V2 |
创建 workflow
在仓库中选择Actions->New workflow->Set up a workflow yourself,自定义一个文件名,然后粘贴下面的 YAML 脚本。
name: Backup Blog Database
on:
workflow_dispatch:
schedule:
- cron: '18 3 * * *' # 定时备份频率
jobs:
backup:
runs-on: ubuntu-latest
steps:
- name: Set environment variables
run: |
echo "FILENAME=backup-blog-mysql-$(TZ=Asia/Shanghai date +"%Y%m%d%H%M%S").sql.gz" >> $GITHUB_ENV
echo "CAPTION=#博客 $(TZ=Asia/Shanghai date -d "now" +%Y-%m-%d\ %H:%M:%S)" >> $GITHUB_ENV
- name: Install mysql-client
run: sudo apt-get install mysql-client -y
- name: Check mysqldump version
run: mysqldump --version
- name: Dump database
run: |
mysqldump -h ${{ secrets.DB_BACKUP_MYSQL_IP }} -P ${{ secrets.DB_BACKUP_MYSQL_PORT || 3306 }} -u${{ secrets.DB_BACKUP_MYSQL_USERNAME }} -p${{ secrets.DB_BACKUP_MYSQL_PASSWORD }} ${{ secrets.DB_BACKUP_MYSQL_DATABASE }} | gzip > ${{ env.FILENAME }}
- name: Upload backup to telegram
run: |
curl -F document=@"${{ env.FILENAME }}" "https://api.telegram.org/bot${{ secrets.DB_BACKUP_TELEGRAM_BOT_TOKEN }}/sendDocument" --form 'chat_id="${{ secrets.DB_BACKUP_TELEGRAM_CHAT_ID }}"' --form 'caption="${{ env.CAPTION }}"'
- name: Install s3cmd
run: sudo apt-get install s3cmd -y
- name: Check s3cmd version
run: s3cmd --version
- name: Configure s3cmd
run: |
cat << EOF > ~/.s3cfg
[default]
access_key = ${{ secrets.DB_BACKUP_S3_ACCESS_KEY }}
secret_key = ${{ secrets.DB_BACKUP_S3_SECRET_KEY }}
host_base = ${{ secrets.DB_BACKUP_S3_HOST_BASE }}
host_bucket = ${{ secrets.DB_BACKUP_S3_HOST_BUCKET }}
use_https = ${{ secrets.DB_BACKUP_S3_USE_HTTPS || true}}
signature_v2 = ${{ secrets.DB_BACKUP_S3_SIGNATURE_V2 || false}}
EOF
- name: Upload backup to s3
run: |
s3cmd put ${{ env.FILENAME }} s3://${{ secrets.DB_BACKUP_S3_BUCKET_NAME }}/${{ secrets.DB_BACKUP_S3_PREFIX_PATH }}/
- name: Remove old backup from s3
run: |
s3cmd sync s3://${{ secrets.DB_BACKUP_S3_BUCKET_NAME }}/${{ secrets.DB_BACKUP_S3_PREFIX_PATH }}/ ./ --delete-removed
find . -type f -mtime +${{ secrets.DB_BACKUP_S3_DAYS || 30}} -print0 | xargs -0 -I {} basename {} | xargs -I {} s3cmd del s3://${{ secrets.DB_BACKUP_S3_BUCKET_NAME }}/${{ secrets.DB_BACKUP_S3_PREFIX_PATH }}/{}
注意:
- 如果只想使用 Telegram 或者 S3 备份,那么可以分别删除掉对应步骤即可;
- 定时执行的时间,脚本中是每天凌晨三点十八分(问就是因为我女儿是三月十八日出生的)执行,这个时间是 Github 机房时区的时间。
无问题后点击右上角Commit changes...,提交到代码仓库。
测试
来到仓库的Actions页面,点击左侧Backup Blog Database,再点击右侧的Run workflow下拉按钮,保存默认的参数,点击Run workflow,即可开始执行任务。
Telegram 和 S3 存储空间中如果能够看到备份文件,则表示成功。