您的位置:首页 > 新闻 > 资讯 > Java跨Docker容器备份数据库数据

Java跨Docker容器备份数据库数据

2024/7/4 5:48:25 来源:https://blog.csdn.net/m0_63684495/article/details/139237034  浏览:    关键词:Java跨Docker容器备份数据库数据


Java跨Docker容器备份数据库数据


    • Java容器

    • MySQL容器

    • 前置背景

    • 思路整理

    • 编写备份脚本

    • 容器启动

    • 检验效果


    • Java代码执行备份


    我的个人博客:Lichg,欢迎大家访问。

    前置背景

    • 在我们的开发部署场景中,通常多数使用Docker进行部署。当你的数据库和项目都使用Docker进行部署,此时我想要通过Java程序进行数据备份,那么就无法实现,因为是两个相互独立的容器。

    • 在本篇文章中,我提供我的解决方法仅供参考。

    思路整理

    1. 因为你的两个Docker容器是相互独立的,你的Java容器要操作MySQL,所以你的Java容器要具备可以执行MySQL命令的能力

    2. 但是,MySQL和Java是隔离的,无法直接使用MySQL命令备份,所以就想到使用docker的exec命令去操作MySQL容器让他备份。

    3. 备份完事以后,备份的文件还在MySQL容器中,宿主机也看不到想要的备份的SQL脚本,所以MySQL容器要挂载数据卷,把备份的SQL脚本备份出来。

    编写备份脚本

    本脚本我是从别人那里拿的,根据自己的需求修改即可

    #!/bin/bash#备份路径BACKUP=/backups/mysql#当前时间DATETIME=$(date +%Y-%m-%d)echo "===== 备份开始 ====="#数据库名称DATABASE=你的数据库名#数据库地址HOST=数据库地址#数据库用户名DB_USER=用户名#数据库密码DB_PW=密码#创建备份目录[ ! -d "${BACKUP}/$DATABASE" ] && mkdir -p "${BACKUP}/$DATABASE"echo "备份文件存放于${BACKUP}/$DATABASE/$DATABASE-$DATETIME.sql"#开始备份mysqldump -h ${HOST} -u${DB_USER} -p${DB_PW}  ${DATABASE} > ${BACKUP}/$DATABASE/$DATABASE-$DATETIME.sqlecho "===== 导出成功,开始传输 ====="#压缩成tar.gz包cd $BACKUPtar -zcvf $DATABASE.tar.gz $DATABASE#备份到服务器B#scp $DATABASE-$DATETIME.sql root@ip:/home/mysqlBackup#删除备份目录  如果取消注释此命令 会删除sql脚本文件 只保留打包完成后的压缩包# rm -rf ${BACKUP}/$DATABASE/$DATETIME#删除10天(不含)前备份的数据,这边可以自行更改find $BACKUP -mtime +10 -name "*.tar.gz" -exec rm -rf {} \;echo "===== 数据库备份到服务器成功 ====="

    容器启动

    这里如果你的容器已经启动了也没关系,直接跑一遍docker命令即可。

    Java:

    这里最主要的是数据卷的绑定,因为你的Java容器需要可以使用docker命令,所以你得把docker挂载进去。其他的根据自己的需求修改就行。

    docker run -d \-v $JOB_NAME-data:/tmp \--net=host \-e PARAMS="--spring.profiles.active=prod" \-v /var/run/docker.sock:/var/run/docker.sock \-v /usr/bin/docker:/usr/bin/docker \--name $JOB_NAME $JOB_NAME

    MySQL:

    version: '3'services:mysql:image: mysql:5.7container_name: mysqlvolumes:- mysql-conf:/etc/mysql/conf.d- mysql-data:/var/lib/mysql# 数据库备份脚本存储路径,映射进去:这里是把你准备的备份脚本从宿主机映射到MySQL容器中,让他可以执行- /export/shell/mysql:/home/shell/mysql# 数据库的备份文件挂在地址:这里是MySQL备份完成后,将备份文件从容器中映射到宿主机中- /export/backups/mysql/57:/backups/mysql# 将宿主机的时区挂载到容器:不挂载可能导致容器内和宿主机的时间不一致,导致备份脚本文件名称的日期出错- /etc/localtime:/etc/localtime:roenvironment:- MYSQL_ROOT_PASSWORD=自行设置你的数据库密码ports:- "3306:3306"mem_limit: 512mvolumes:mysql-conf:mysql-data:

    检验效果

    Java容器

    1. 先进入到你的Java容器中:

    docker exec -it Java容器名 bash
    1. 进来以后可以直接使用下面的命令,查看是否挂载Docker成功:

    docker -v
    1. 出现版本号即为成功

    image-20240527104710429

    1. 如果你出现了权限不足的问题,你需要退回到你的宿主机内,给docker.sock进行权限修改,没有的话直接省略此步骤即可:

    chmod -R 777 /var/run/docker.sock
    1. Java容器中查看你的MySQL版本,如果正常出现版本号基本就没什么问题了:

    # 注意这里没有 -it 参数docker exec mysql mysql -V

    image-20240527111754983

    MySQL容器

    1. 进入MySQL容器:

    docker exec -it mysql bash
    1. 找到你自己设置的挂载备份脚本的路径,查看脚本是否挂载成功:

    image-20240527112516583

    1. 你可以直接执行下你的脚本,看下效果

    sh 你的脚本名称

    image-20240527113328530

    1. 可以到你的备份目录查看下备份的效果,这里有其他的是因为我的程序设置的每七天自动备份一次:

    image-20240527113507659

    1. 到你的宿主机挂载的脚本备份路径查看:

    image-20240527113846237

    image-20240527113918053

    1. 这里还是有一个可能存在的坑:

    如果你发现你备份的数据SQL脚本,分明是18号备份的但是SQL的脚本文件的名称上却是17号,这是因为:你的数据库备份脚本中,有一个参数是获取当前系统的时间,那么就说明你的MySQL容器中的时间跟宿主机的时间不一致,运行容器时没有对时区进行挂载数据卷。

    image-20240527114446397

    Java代码执行备份

    代码执行这里我是使用了xxl-job定时任务去做,每七天备份一次,其他的实现方式可以根据你们自己的需求去进行更改。

        @XxlJob("mysqlBackup")public void mysqlBackup(){//获取Runtime实例Runtime runtime = Runtime.getRuntime();// 数据库备份命令String command = "docker exec mysql sh /home/shell/mysql/course_compete.sh";//获取命令所得的缓冲流结果BufferedReader bufferedReader = null;// 执行命令try {Process exec = runtime.exec(command);//初始化缓冲阅读器bufferedReader = new BufferedReader(new InputStreamReader(exec.getInputStream()));// 逐行读取输出String line;//此时就可以对获取的结果in进行操作了,可以使用in.readline()逐步获取每一行的结果内容while ((line = bufferedReader.readLine()) != null){log.info("获取到的行数据:{}", line);}} catch (IOException e) {log.error("竞赛模块数据库备份异常");throw new RuntimeException(e);}finally {if(bufferedReader != null){try {bufferedReader.close();} catch (IOException e) {throw new RuntimeException(e);}}}}

    版权声明:

    本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

    我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com