MySQL容器化部署与自动备份实战

举报
yd_273651526 发表于 2026/11/02 15:52:19 2026/11/02
【摘要】 本文详细介绍了在华为云弹性云服务器(ECS)Ubuntu 22.04 环境下,利用 Docker Compose 容器化部署 MySQL 8.0 数据库、配置字符集与 InnoDB 缓冲池参数调优,并结合 mysqldump 与 Crontab 实现每日自动化压缩热备份与过期归档清理的完整方案。

前言

在中小型 Web 项目或个人开发者应用的后端架构中,关系型数据库 MySQL 依然是最核心的基础组件之一。相比直接在华为云弹性云服务器(ECS)宿主机上通过二进制包或 APT 源安装 MySQL,采用 Docker Compose 容器化编排 不仅能快速锁定数据库版本、隔离依赖环境,还能通过数据卷挂载实现配置与持久化数据的解耦。

与此同时,“数据无价”,任何生产或测试环境都必须具备完善的容灾备份机制。本文将完整演示在华为云 Ubuntu 22.04 实例上,使用 Docker Compose 部署优化后的 MySQL 8.0 实例,并编写 Shell 脚本配合 Crontab 实现每日自动化压缩热备份与过期备份清理。


一、 环境准备与目录规划

在开始部署前,我们在宿主机的数据盘或 /opt 目录下规划清晰的目录结构,分别用于存放编排文件、自定义配置、持久化数据以及备份归档文件:

# 创建 MySQL 容器化工作目录与子目录
sudo mkdir -p /opt/mysql8/{conf,data,logs,backup}

# 进入工作主目录
cd /opt/mysql8

各目录职责说明:

  • conf/:存放自定义的 my.cnf 配置文件(字符集、连接数与内存缓冲池调优)。
  • data/:挂载容器内 /var/lib/mysql,确保容器销毁或重建时数据不丢失。
  • logs/:存放慢查询日志与错误日志。
  • backup/:存放每日定时导出的 .sql.gz 压缩备份文件。

二、 编写 MySQL 8.0 调优配置文件

为了避免中文乱码问题,并让 MySQL 更好地适应 2核4G 或 1核2G 等不同规格的华为云 ECS 实例,我们先在 /opt/mysql8/conf/my.cnf 中写入标准化配置:

sudo tee /opt/mysql8/conf/my.cnf << 'EOF'
[mysqld]
# 基础设置与默认字符集
user = mysql
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-time-zone = '+08:00'

# 禁用域名反向解析,加快客户端连接速度
skip-name-resolve

# 连接数与超时控制
max_connections = 500
wait_timeout = 600
interactive_timeout = 600

# InnoDB 缓冲池调优(可根据服务器实际内存大小调整,2G内存建议设为 512M)
innodb_buffer_pool_size = 512M
innodb_log_file_size = 128M
innodb_flush_log_at_trx_commit = 1

# 开启慢查询日志,记录超过 2 秒的 SQL 语句
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2

[client]
default-character-set = utf8mb4
EOF

三、 使用 Docker Compose 启动 MySQL 8.0

1. 编写 docker-compose.yml 文件

出于安全考虑,如果不涉及跨公网远程直连,建议将端口仅绑定在宿主机本地回环地址 127.0.0.1:3306(或者通过华为云安全组严格限制仅允许特定内网/办公网 IP 访问 3306 端口):

sudo tee /opt/mysql8/docker-compose.yml << 'EOF'
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql8-server
    restart: always
    ports:
      - "127.0.0.1:3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: "StrongPassword_2026!"
      MYSQL_DATABASE: "app_prod_db"
      TZ: "Asia/Shanghai"
    volumes:
      - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf:ro
      - ./data:/var/lib/mysql
      - ./logs:/var/log/mysql
    command:
      - --default-authentication-plugin=mysql_native_password
EOF

2. 启动容器并验证状态

赋予日志目录合适的权限后,一键拉起服务:

sudo chmod -R 777 /opt/mysql8/logs
sudo docker-compose up -d

# 查看容器运行状态与初始化日志
sudo docker ps | grep mysql8-server
sudo docker logs --tail 50 mysql8-server

当日志中出现 ready for connections. Version: '8.0.x' 时,说明数据库已成功初始化并正常对外提供服务。


四、 编写自动化热备份与历史归档清理脚本

为了防止人工误删表或硬件意外造成数据丢失,我们利用 docker exec 结合 mysqldump 的 --single-transaction 参数实现不锁表的在线热备份,并使用 gzip 实时压缩以节省华为云云硬盘空间。

1. 创建备份脚本 mysql_backup.sh

sudo tee /opt/mysql8/mysql_backup.sh << 'EOF'
#!/bin/bash

# 配置参数
CONTAINER_NAME="mysql8-server"
DB_USER="root"
DB_PASS="StrongPassword_2026!"
DB_NAME="app_prod_db"
BACKUP_DIR="/opt/mysql8/backup"
DATE_STR=$(date +"%Y%m%d_%H%M%S")
RETENTION_DAYS=14

# 确保备份目录存在
mkdir -p ${BACKUP_DIR}

echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始备份数据库: ${DB_NAME}" >> ${BACKUP_DIR}/backup.log

# 执行在线热备份并直接通过 gzip 高比率压缩
docker exec ${CONTAINER_NAME} mysqldump -u${DB_USER} -p"${DB_PASS}" \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  ${DB_NAME} 2>/dev/null | gzip > ${BACKUP_DIR}/${DB_NAME}_${DATE_STR}.sql.gz

# 检查备份文件是否成功生成且非空
if [ -s "${BACKUP_DIR}/${DB_NAME}_${DATE_STR}.sql.gz" ]; then
    FILE_SIZE=$(du -sh "${BACKUP_DIR}/${DB_NAME}_${DATE_STR}.sql.gz" | awk '{print $1}')
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 备份成功: ${DB_NAME}_${DATE_STR}.sql.gz (大小: ${FILE_SIZE})" >> ${BACKUP_DIR}/backup.log
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [错误] 备份失败,请检查容器状态或密码配置!" >> ${BACKUP_DIR}/backup.log
    rm -f "${BACKUP_DIR}/${DB_NAME}_${DATE_STR}.sql.gz"
    exit 1
fi

# 自动清理超过 14 天的历史旧备份,释放磁盘空间
find ${BACKUP_DIR} -name "${DB_NAME}_*.sql.gz" -type f -mtime +${RETENTION_DAYS} -delete
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 已清理超过 ${RETENTION_DAYS} 天的过期备份。" >> ${BACKUP_DIR}/backup.log
EOF

# 赋予脚本执行权限并设置仅 root 可读(保护脚本内的密码信息)
sudo chmod 700 /opt/mysql8/mysql_backup.sh

2. 手动测试备份与恢复命令

先手动运行一次脚本,验证备份产物是否正常生成:

sudo /opt/mysql8/mysql_backup.sh
ls -lh /opt/mysql8/backup/

日后若需要从某次压缩备份中恢复数据,只需执行以下流式解压导入命令即可:

gunzip < /opt/mysql8/backup/app_prod_db_xxxxxxx.sql.gz | docker exec -i mysql8-server mysql -uroot -p"StrongPassword_2026!" app_prod_db

3. 配置 Crontab 每日凌晨定时执行

将脚本加入系统计划任务,设置在每天业务低峰期(凌晨 02:30)自动执行备份:

(sudo crontab -l 2>/dev/null; echo "30 2 * * * /opt/mysql8/mysql_backup.sh") | sudo crontab -

总结

通过 Docker Compose 编排与自定义 my.cnf 挂载,我们在华为云 ECS 上实现了 MySQL 8.0 的标准化快速交付;而结合 --single-transaction 热备与 find 定时轮转清理脚本,则在零额外成本的前提下构建起了可靠的数据安全防线。对于重要生产数据,后续还可以进一步结合华为云对象存储服务(OBS)命令行工具,将本地生成的 .sql.gz 备份同步上传至异地云存储桶中,实现更高等级的灾备保护。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。