如何从Docker容器的主机卷备份MySQL数据库

82次阅读
没有评论

问题描述

在使用Docker时,有一个需求是希望能够从Docker容器的主机卷备份MySQL数据库。他已经在主机上安装了一个LAMP服务器,并且已经有一个与主机上的MariaDB服务器关联的数据库,并且使用automysqlbackup进行备份。这部分工作正常。
现在,用户正在使用Docker服务器进行一个新项目,其中一个容器中有一个MySQL 5.7数据库,并且使用一个主机文件夹的卷来保存这个新项目的数据库,例如:/path/on/host/dockerise/db/。
用户希望也能够备份这个新的数据库。
用户提出了以下几种备份方式:
1. 是否可以使用automysqlbackup进行备份?用户认为不行,因为它使用主机上的MariaDB服务器和mysqldump,并且不应该在同一个数据库上同时工作两个服务器。
2. 是否可以直接使用mysqldump进行备份?
3. 或者只需创建一个bash脚本并使用CRON进行定时备份?

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

根据用户的需求,我们可以使用一个bash脚本来备份MySQL数据库。以下是一个示例脚本,可以在Docker容器中运行,并将备份保存在容器的卷中:

#!/bin/bash
DATE_TIME=`date +"%Y%m%d_%H%M"`
CONTAINER_NAME="mysql_server"
CONTAINER=`docker ps -q -f name=${CONTAINER_NAME}`
PASSWORD=`docker exec ${CONTAINER} sh -c 'echo $MYSQL_ROOT_PASSWORD'`
BACKUP_FILE=${DATE_TIME}_${CONTAINER_NAME}.backup.sql.gz
CONTAINER_BACKUP_DIR="/var/lib/mysql/"
HOST_DATA_DIR="/path/on/my/VM/correspond/to/docker/volume/"
HOST_BACKUP_DIR="/other/path/on/VM/"

## 在容器中运行备份命令
docker exec ${CONTAINER} sh -c "/usr/bin/mysqldump -h localhost -u root -p${PASSWORD} --all-databases | gzip -9 -c > ${CONTAINER_BACKUP_DIR}${BACKUP_FILE}"

## 将备份文件移动到最终目录
mv ${HOST_DATA_DIR}${BACKUP_FILE} ${HOST_BACKUP_DIR}

在上面的示例中,我们首先获取当前的日期和时间,并将其作为备份文件的一部分。然后,我们指定了容器的名称和相关的容器和主机目录。接下来,我们使用docker exec命令在容器中运行mysqldump命令来备份所有数据库,并将备份文件压缩为gzip格式。最后,我们将备份文件移动到最终的备份目录中。

请注意,根据用户的需求,您可能需要根据实际情况修改脚本中的路径和其他参数。

如果您希望自动定期运行备份脚本,您可以使用CRON作业来调度脚本的运行。以下是一个示例脚本,可以在CRON作业中使用来管理备份文件的旋转和删除旧备份:

## 旋转备份文件以保留最新的MAX_BACKUP个文件
MAX_BACKUP=3
HOST_DATA_DIR="/path/on/my/VM/correspond/to/docker/volume/"
HOST_BACKUP_DIR="/other/path/on/VM/"
CONTAINER_NAME="mysql_server"

rotate-databases-backup.log文件的路径
echo ${HOST_BACKUP_DIR}${BACKUP_FILE} >> ${HOST_DATA_DIR}rotate-databases-backup.log

## 计算已备份的文件数量和总文件数量
BACKUPED_NB=$(ls ${HOST_BACKUP_DIR}*${CONTAINER_NAME}.backup.sql.gz | wc --lines)
TOTAL=$(wc --lines < ${HOST_DATA_DIR}rotate-databases-backup.log)

## 计算需要删除的文件数量
FILES_NB_TO_DELETE=$(expr $TOTAL - $MAX_BACKUP)

## 如果需要删除文件,则删除旧备份文件
if [[ $FILES_NB_TO_DELETE -gt 0 ]]; then
    head --lines=$FILES_NB_TO_DELETE ${HOST_DATA_DIR}rotate-databases-backup.log | xargs rm
    ls ${HOST_BACKUP_DIR}*${CONTAINER_NAME}.backup.sql.gz > ${HOST_DATA_DIR}rotate-databases-backup.log
fi

在上面的示例中,我们首先将备份文件的路径添加到rotate-databases-backup.log文件中。然后,我们计算已备份的文件数量和总文件数量,并计算需要删除的文件数量。最后,如果需要删除文件,我们使用xargs rm命令删除旧的备份文件。

请注意,根据用户的需求,您可能需要根据实际情况修改脚本中的路径和其他参数。

方案2

根据用户的需求,我们可以使用automysqlbackup进行备份。以下是一个示例脚本,可以在CRON作业中使用来定期运行automysqlbackup:

#!/bin/bash
automysqlbackup

在上面的示例中,我们只需要运行automysqlbackup命令即可。automysqlbackup会自动备份MySQL数据库,并将备份文件保存在指定的位置。

请注意,根据用户的需求,您可能需要根据实际情况修改脚本中的路径和其他参数。

方案3

根据用户的需求,我们可以创建一个bash脚本,并使用CRON作业来定期运行该脚本。以下是一个示例脚本,可以在CRON作业中使用来定期运行备份:

#!/bin/bash
DATE_TIME=`date +"%Y_%m_%d_%H_%M"`
CONTAINER_NAME="mariadb"
CONTAINER=`docker ps -q -f name=${CONTAINER_NAME}`
PASSWORD=`docker exec ${CONTAINER} sh -c 'echo $MYSQL_ROOT_PASSWORD'`
BACKUPFILE=${DATE_TIME}_${CONTAINER_NAME}.backup.gz

echo "Backup of MariaDb"
echo ""
echo "Old backups will be deleted."
echo "Database Container Name: $CONTAINER_NAME"
echo "Database Container:  $CONTAINER"
echo "Writing backup to ${BACKUPFILE}"
echo ""

docker exec ${CONTAINER} sh -c "find /backup/ -mindepth 1 -mtime +8 -delete; /usr/bin/mariabackup --backup --user root --password=${PASSWORD} --stream=xbstream | gzip > /backup/${BACKUPFILE}"

echo ""
echo "Backup finished"

在上面的示例中,我们首先获取当前的日期和时间,并将其作为备份文件的一部分。然后,我们指定了容器的名称和相关的容器和主机目录。接下来,我们使用docker exec命令在容器中运行mariabackup命令来备份数据库,并将备份文件压缩为gzip格式。最后,我们将备份文件移动到最终的备份目录中。

请注意,根据用户的需求,您可能需要根据实际情况修改脚本中的路径和其他参数。

如果您希望自动定期运行备份脚本,您可以使用CRON作业来调度脚本的运行。以下是一个示例CRON作业的配置,用于每天定时运行备份脚本:

0 0 * * * /path/to/backup-script.sh

在上面的示例中,我们将备份脚本的路径替换为实际的脚本路径,并将CRON作业配置为每天的午夜运行备份脚本。

请注意,根据用户的需求,您可能需要根据实际情况修改CRON作业的配置。

以上是几种备份MySQL数据库的方法,您可以根据自己的需求选择适合您的方法。希望对您有帮助!

正文完