定期从Docker上部署的MySQL备份数据

前段时间公司停电,正巧赶上周一领导要开会要过一遍项目,然而项目所依赖的MySQL数据库是直接部署在宿主机,且因为各人部署方式不同的原因,花了很久才在开会前启动起来。于是开完会后,我第一件事就是把原先依赖的MySQL数据库迁移到Docker上,又另外写了一个脚本定时将Docker上部署的MySQL数据库备份出来,而且我们的脚本不单单可以指定要备份的数据库,还要将备份出来的SQL文件打包成压缩文件,并以一定的规范来命名,比如:test_2019-10-11-17.zip,test是前缀,2019-10-11-17代表是2019年10月11日17点的时候备份的。再来就是定期删除5个小时或10个小时之前的备份文件,当然这些都是锦上添花的事了,文末会附上备份文件脚本。

现在,我们先在Docker上部署一个MySQL实例,再创建几个用于测试的数据库,将其导出。

首先,我们创建一个MySQL实例:

?  ~ docker run --name mysql-test -v /usr/local/mysql-test:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 8706:3306 -d mysql
1a70e86992bddb493db69da55cf8bf08863ce0b59d2f5931e782125adb900d71
?  ~ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
1a70e86992bd        mysql               "docker-entrypoint..."   4 seconds ago       Up 2 seconds        33060/tcp, 0.0.0.0:8706->3306/tcp   mysql-test

  

然后我们进入到容器后,再进入到MySQL修改一下加密方式,以便部分版本较旧的Navicat可以连接我们的MySQL实例(此操作可以不做):

?  ~ docker exec -it mysql-test /bin/bash
[email protected]:/# mysql -uroot -p
Enter password:
……

mysql> ALTER user ‘root‘@‘%‘ IDENTIFIED WITH mysql_native_password BY ‘123456‘;
Query OK, 0 rows affected (0.03 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

  

我们创建一个test1数据库,再创建一张表admin,并插入两条数据:

mysql> CREATE DATABASE `test1`CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
Query OK, 1 row affected (0.02 sec)

mysql> CREATE TABLE `test1`.`admin` ( `id` INT NOT NULL AUTO_INCREMENT, `account` CHAR ( 32 ) NOT NULL, PRIMARY KEY ( `id` ) );
Query OK, 0 rows affected (0.27 sec)

mysql> INSERT INTO `test1`.`admin`(`account`) VALUES (‘admin1‘);
Query OK, 1 row affected (0.02 sec)

mysql> INSERT INTO `test1`.`admin`(`account`) VALUES (‘admin2‘);
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM `test1`.`admin`;
+----+---------+
| id | account |
+----+---------+
|  1 | admin1  |
|  2 | admin2  |
+----+---------+
2 rows in set (0.00 sec)

  

我们再来创建第二个数据库test2,并创建一张表user,再插入两条测试数据:

mysql> CREATE DATABASE `test2`CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
Query OK, 1 row affected (0.01 sec)

mysql> CREATE TABLE `test2`.`user` ( `id` INT NOT NULL AUTO_INCREMENT, `name` CHAR ( 32 ) NOT NULL, `age` TINYINT NOT NULL, PRIMARY KEY ( `id` ) );
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO `test2`.`user`(`name`,`age`) VALUES (‘Amy‘,‘16‘);
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO `test2`.`user`(`name`,`age`) VALUES (‘Tom‘,‘20‘);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM `test2`.`user`;
+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | Amy  |  16 |
|  2 | Tom  |  20 |
+----+------+-----+
2 rows in set (0.00 sec)

  

至此,我们的测试库和测试数据已经创建好了。现在,我们先尝试着用命令行备份数据库test1。

?  ~ docker exec -it mysql-test mysqldump -uroot -p123456 test1 > test1.sql
?  ~ cat test1.sql
……
CREATE TABLE `admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account` char(32) COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
……
INSERT INTO `admin` VALUES (1,‘admin1‘),(2,‘admin2‘);

  

这里简单介绍一下导出命令:

docker exec -it {container_name} mysqldump -u{db_user} -p{db_password} {database} > {file_path}
  • container_name:容器名称,此处也可填容器ID。
  • db_user:数据库账号。
  • db_password:数据库密码。
  • database:要备份的数据库。
  • file_path:备份出来的文件名。

因此,如果我们要备份多个数据库,比如test1和test2,则循环执行上面的命令,替换database即可。

让我们用Python3来执行下面这个脚本:

#!/usr/bin/env python
# encoding: utf-8
import datetime
import os
import shutil
import subprocess
import time
import zipfile

# 数据库用户名
db_user = "root"
# 数据库密码
db_password = "123456"
# 备份目录
backup_dir = "/var/test_backup"
# backup_prefix和backup_suffix分别为备份文件的前缀和后缀,如test_backup_2019-09-19-11则代表该文件是在2019年9月19日的11点时备份的
backup_prefix = "test_backup"
backup_suffix = "%Y-%m-%d-%H"
# 备份数据库列表
backup_databases = [
    "test1",
    "test2",
]
# 容器名
container_name = "mysql-test"
# 过期小时,定期删除5个小时前的备份文件
expire_hour = 5

# 获取备份文件名
def get_backup_filename():
    t = time.strftime(backup_suffix, time.localtime())
    return "%s_%s" % (backup_prefix, t)

def get_backup_path():
    return "%s%s%s" % (backup_dir, os.sep, get_backup_filename())

# 获取过期时间戳
def get_expire_time():
    t = datetime.datetime.now() - datetime.timedelta(hours=expire_hour)
    return int(time.mktime(t.timetuple()))

def create_dir(dir_path):
    # 如果目录存在则退出
    if os.path.exists(dir_path):
        return
    os.mkdir(dir_path)

cmd_template = "docker exec -it {container_name} mysqldump -u{db_user} -p{db_password} {database} > {file_path}"

# 备份指定数据库
def backup_database(backup_path, database):
    file_path = os.sep.join([backup_path, "%s.sql" % database])
    d = {
        "container_name": container_name,
        "db_user": db_user,
        "db_password": db_password,
        "database": database,
        "file_path": file_path,
    }
    cmd = cmd_template.format(**d)
    subprocess.call(cmd, shell=True)

def zip_dir(dir_path):
    file_path = ‘.‘.join([dir_path, "zip"])
    if os.path.exists(file_path):
        os.remove(file_path)
    z = zipfile.ZipFile(file_path, ‘w‘, zipfile.ZIP_DEFLATED)
    for root, directories, files in os.walk(dir_path):
        fpath = root.replace(dir_path, ‘‘)
        fpath = fpath and fpath + os.sep or ‘‘
        for filename in files:
            z.write(os.path.join(root, filename), fpath + filename)
    z.close()

# 备份数据库
def backup():
    backup_path = get_backup_path()
    try:
        create_dir(backup_path)
        for database in backup_databases:
            backup_database(backup_path, database)
        zip_dir(backup_path)
    finally:
        shutil.rmtree(backup_path)

# 清理过期备份文件
def clean():
    expire_time = get_expire_time()
    for root, directories, files in os.walk(backup_dir):
        for file in files:
            if not file.startswith(backup_prefix):
                continue
            if not file.endswith(".zip"):
                continue
            file_path = os.sep.join([root, file])
            t = os.path.getctime(file_path)
            if t < expire_time:
                os.remove(file_path)

if __name__ == "__main__":
    try:
        backup()
    finally:
        clean()

  

执行完毕后,我们会发现备份目录下多了一个zip文件,我们可以用unzip命令来查看下zip文件的内容:

?  ~ python36 backup.py
?  ~ ll /var/test_backup
total 4.0K
-rw-r--r-- 1 root root 1.8K Oct 12 09:55 test_backup_2019-10-12-09.zip
?  ~ unzip -v /var/test_backup/test_backup_2019-10-12-09.zip
Archive:  /var/test_backup/test_backup_2019-10-12-09.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
    2085  Defl:N      784  62% 10-12-2019 09:55 e42329a0  test1.sql
    2104  Defl:N      801  62% 10-12-2019 09:55 046297a6  test2.sql
--------          -------  ---                            -------
    4189             1585  62%                            2 files

  

测试脚本可以正常备份Docker上的MySQL实例的多个数据库,我们就可以用Linux自带的crontab命令来自动执行脚本。

原文地址:https://www.cnblogs.com/beiluowuzheng/p/11655242.html

时间: 2024-10-10 05:15:46

定期从Docker上部署的MySQL备份数据的相关文章

MySQL 备份数据那点事

mysqldump 什么是 mysqldump ? mysqldump 是 MySQL 用于执行逻辑备份的一款工具,可以根据原始数据库对象以及表的定义和数据来生成一系列可以被执行的 SQL 语句. 通常我们用它作为备份或者迁移数据. mysqldump 命令还可以输出成 CSV 文件,其他边界的文本或者 XML 格式. 如何使用 mysqldump? 导出整个数据库(包含数据) mysqldump -u username -p dbname > dbname.sql 导出数据库结构 mysqld

在docker上部署mysql

1.拉取官方镜像5.6的版本.(查看有哪些版本,可以在阿里云的镜像仓库查看,我配置的镜像是阿里云的) docker pull mysql:5.6 2.查看拉取的镜像,获取镜像id docker images 3.运行镜像.-d 后台运行,-e 配置环境变量,用户名为root,密码为123456,-p 配置端口映射 --name 容器名 docker run -d -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 --name mysql5.6 镜像id 4.查

mysql 备份数据迁移,出错的处理

项目历史遗留/usr/lib/mysql 下所有数据文件,之前用Debian 下的mysql5.1 的MyISAM引擎,现在机器是ubuntu,只有mysql5.5,mysql5.6 默认InnoDB引擎,恢复的过程. 1.Ubuntu上安装mysql5.5,把/usr/lib/mysql 下所有数据文件拷贝到Ubuntu系统中相应目录,并设置文件权限和owner. 启动 sudo service mysql start 报错,/var/log/mysql/error.log 各种文件写.创建错

linux的docker上如何安装mysql

1.安装docker,网上一堆,这里不细说. 2.进入linux后,使用docker命令下载mysql,命令如: docker pull mysql:5.7 运行该命令后,则会显示以下日志: 5.7: Pulling from mysql 4c8cbfd2973e: Pull complete 60c52dbe9d91: Pull complete c2b0136be90f: Pull complete 273cd71eacf0: Pull complete 543ff72402d8: Pull

Docker教程系列五:Docker上部署tomcat

1下载tomcat镜像(7-jre8代表tomcat7和java jdk8,tomcat需要java环境,点击下面连接可以查看可下载的版本) 查看可下载版本 docker pull tomcat:7-jre8 2创建tomcat容器 docker run -di --name=tomcat -p 8080:8080 -v tomcat/myhtml:/usr/local/tomcat/webapps --privileged=true tomcat:7-jre8 3部署web应用 将自己网站的w

Docker教程系列六:Docker上部署Nginx

1下载Nginx镜像 docker pull nginx 2创建Nginx容器 docker run -di --name=nginx -p 80:80  nginx/bin/bash 3测试Nginx 浏览器地址栏输入: Linux系统ip 4配置反向代理 官方的nginx镜像,nginx配置文件nginx.conf 在/etc/nginx/目录下. 在容器内编辑配置文件不方便,我们可以先将配置文件从容器内拷贝到宿主机,编辑修改后再拷贝回去. (1)从容器拷贝配置文件到宿主机 docker c

mysql 备份数据语句

rem ******MySQL backup start********@echo offforfiles /p "D:\website\备份\数据库日常备份" /m backup_*.sql -d -30 /c "cmd /c del /f @path"set "Ymd=%date:~0,4%%date:~5,2%%date:~8,2%0%time:~1,1%%time:~3,2%%time:~6,2%""C:\Program Fil

[原创]在Docker上部署mongodb分片副本集群。

一.安装docker. 请参考:http://www.cnblogs.com/hehexiaoxia/p/6150584.html 二.编写dockerfile. #在根目录下创建dockerfile. $ vi dockerfile #version 1.0 from ubuntu #maintainer maintainer hdx #install run apt-get clean run apt-get update run apt-get install -y vim run apt

Docker教程系列七:Docker上部署Redis

1下载Redis镜像 docker pull redis 2创建Redis容器 docker run -di --name=redis -p 6379:6379 redis 3客户端测试 在你的本地电脑命令提示符下,用window版本redis测试 redis-cli -h docker所在Linux系统ip 原文地址:https://www.cnblogs.com/xiangzhuo/p/9484438.html