记一次docker的mysql损坏修复经历

一、问题描述

近日由于市政电路整改,机房被迫断电。其中有一台ubuntu主机没有手工关机,重新送电后ubuntu主机重启成功。但在ubuntu宿主上用docker安装的mysql动无法启动。

(1)尝试进入docker命令行:

$ docker exec -it mysql57 env LANG=C.UTF-8 /bin/bash
得到

Error response from daemon: Container 40580276ee2f0bf30e59d9ff670977b27856a36ed10b788e3a3fce8f17d7849b is not running

(2)面向百度得到docker logs {容器}的建议。结果:

$ docker logs mysql57

Initializing database
Database initialized
MySQL init process in progress...
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
/entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
MySQL init process done. Ready for start up.

(3) 请教GPT后得到删除并重建的建议。

二、使用docker部署mysql的一些思考

对于数据库,最重要的就是数据的安全性要得到保证。
所以必须要确保即使docker容器损坏后,仍然能够拿到mysql存储的数据文件。
因此在初始化docker容器时,只要将数据目录挂载到宿主机上的自定义目录即可。

三、实施重建

这里假设我的宿主用户名为study

1.删除旧的已损坏的mysql实例

docker stop mysql57
docker rm mysql57

2.创建在宿主机上创建mysql数据相关目录

备份损坏前的数据文件

#进入数据目录的父目录
/home/study/database
#备份文件夹
sudo zip -r MYSQL_DATA.zip MYSQL_DATA
#删除原有的DATA目录
sudo rm -rf MYSQL_DATA
sudo mkdir MYSQL_DATA
sudo chmod -R 755 /home/study/database

这里我在宿主上创建了一个文件夹/home/study/database/MYSQL_DATA作为mysql的数据目录。因此这里要先备份它。

这是我初次安装时创建的一些目录和文件 :

#日志目录
sudo mkdir -p "/home/study/database/logs"
#数据目录
sudo mkdir -p "/home/study/database/MYSQL_DATA"
#配置目录 
sudo mkdir -p "/home/study/database/conf"
#创建文件
sudo touch /home/study/database/logs/mysqld-error.log
sudo touch  /home/study/database/conf/mysqld.pid
3.重建实例
sudo docker run --name mysql57 -p 3308:3306 -e MYSQL_ROOT_PASSWORD=studyDB -d  \ 
--mount type=bind,src=/home/study/database/logs/mysqld-error.log,dst=/var/log/mysqld.log \  
--mount type=bind,src=/home/study/database/MySQL_DATA,dst=/var/lib/mysql mysql/mysql-server:5.7.18 

命令解读:

sudo 以管理员身份执行
docker run 是docker容器初始化的命令。

--name mysql57 容器取名为mysql57后期维护用这个名字,相当于给容器ID取个别名。
-p 3308:3306 这里有两个端口3306是容器中mysql进程监听的端口,3308是通过宿主IP来访问数据库时宿主机的端口。相当于将容器中的3306映射到宿主机的3308上。

-e MYSQL_ROOT_PASSWORD=studyDB 指定root帐号的密码

-d 选项是 "detached""daemon" 的缩写,它的作用是将容器在后台运行,而不是占用当前终端会话。具体来说,它指示Docker将容器作为后台进程启动,然后返回到命令行终端,允许您继续使用该终端而不会阻止在容器上运行的应用程序。

\ 用于将一条很长的命令分成多行来书写。相当于行与行之间的连接符。

--mount type=bind,src=/home/study/database/logs/mysqld-error.log,dst=/var/log/mysqld.log
  这一句--mount是挂载宿主文件路径,src是宿主路径,dst是容器中的命令
  相当于在docker容器中创建了一个文件软链接,指定此参数后,在容器中往路径/var/log/mysqld.log中写入内容时,实际内容会被写入到宿主的/home/study/database/logs/mysqld-error.log这个文件。

--mount type=bind,src=/home/study/database/MySQL_DATA,dst=/var/lib/mysql 
  这一句--mount是挂载宿主文件目录路径,src是宿主路径,dst是容器中的命令
  相当于在docker容器中创建了一个文件软链接,指定此参数后,在容器中往目录/var/lib/mysql下写入内容时,实际内容会被写入到宿主的/home/study/database/MySQL_DATA目录下。

mysql/mysql-server:5.7.18  这是docker pull拉取的镜像名称,意思是以它为模板运行实例。

以上执行成功后,启动mysql容器:

#启动容器
docker start mysql57
#修改容器重启策略,让它随宿主机开机自启
docker update --restart=always mysql57

进入容器并设置中文支持

#第一步:进入时加环境变量参数env LANG=C.UTF-8 
docker exec -it mysql57 env LANG=C.UTF-8 /bin/bash
#第二步:安装vi程序
yum install vi
#第三步:vi /etc/profile  文件尾插入
LANG=en_ZW.utf8
#第四步:配置生效
source /etc/profile
#验证mysql登录
mysql -uroot -pstudyDB --default-character-set=utf8
#退出mysql命令行
quit

#修改mysql配置
vim /etc/my.cnf  添加下面的sql_mode和lower_case_table_names
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
#解析SQL语句时,忽略库表名称大小写
lower_case_table_names=1

#退出mysql容器
exit

4.还原数据

#停止mysql
sudo docker stop mysql57
#进入备份所在目录
cd /home/study/database
#直接解压覆盖所有文件
sudo unzip MYSQL_DATA.zip
#重启mysql
sudo docker start mysql57
#进入容器命令行
docker exec -it mysql57 env LANG=C.UTF-8 /bin/bash

四、总结

这是在生产环境使用docker后第一次遇到容器损坏的情况。
本次事故能够得到解决主要得益于新技术应用之前做好了风险把控,将Mysql的数据目录映射到宿主的文件夹中。否则一旦容器损坏,后果难以设想。

你可能感兴趣的:(docker,mysql,容器)