创建MySQL容器的教程有很多,搜了一大堆都是使用-v映射自己的配置文件和数据文件,而且都是指定的原先容器内的MySQL默认数据存储路径,但公司一般都会将数据文件、binglog、redolog、slowlog、errlog等文件分类存储,放在自己定义的路径下。本篇博客就讲一下如何加载外部自定义配置文件,并将数据库运行的数据分类持久化到宿主机。
本篇博客基于docker run -v的一个特性:如果映射的目录在容器内不存在,那么就会自动在容器内创建。最终达到的效果就是可以随时根据自己的配置文件启动MySQL容器,且产生的数据和日志文件都持久化在宿主机,不会丢失。
首先看一下我规划的宿主机和容器内的目录结构(见下面的图,画了好久)。通过宿主机的目录简单讲下各个文件夹的意思
1)3306文件夹下存放3306端口的MySQL实例(如果有3307实例,那就新建3307文件夹进行存放,以此类推。。。。)
2)data存放数据文件,就是一些idb、frm文件。
3)errlog存放数据库运行的日志,如果MySQL有报错那就去这里看。
4)logdir文件夹下是binglog和redolog两个文件夹。
5)slowlog文件夹是存放慢日志。
6)tmpdir文件夹是数据库临时文件。
7)mysqld.pid和mysql.sock是数据库运行时产生的文件,数据库停止就会消失。(名字命名可能有些差异)
8)conf文件夹是MySQL的配置文件my.cnf(Windows下是my.ini)
宿主机的这些文件夹和容器文件夹的映射关系通过下面的图就能看明白。
环境:Centos7.3 、MariaDB10.1.13镜像、my.cnf文件
我的配置文件中和路径相关的参数如下:
# 这个是MySQL容器默认的数据库安装路径
basedir = /usr
socket = /mysqldata/3306/data/discard/other/mysql.sock
pid-file = /mysqldata/3306/data/discard/other/mysqld.pid
# 数据
datadir = /mysqldata/3306/data
# 错误日志
log-error = /mysqldata/3306/data/discard/errlog/mysqld.err
# 这个缺省为datadir,可不写
innodb_data_home_dir = /mysqldata/3306/data
# binlog
log-bin=/mysqldata/3306/discard/data/logdir/binlog/binlog
# redolog
innodb_log_group_home_dir = /mysqldata/3306/data/discard/logdir/redolog
# 临时文件
tmpdir=/mysqldata/3306/data/discard/tmpdir
#慢查询日志
slow_query_log_file='/mysqldata/3306/data/discard/slowlog/slow.log'
步骤:
一、在宿主机上创建数据目录(后来发现个坑,要给conf文件夹赋权755,我也不知道为啥)
mkdir -p /mysqldata/3306/data
mkdir -p /mysqldata/3306/logdir/binlog
mkdir -p /mysqldata/3306/logdir/redolog
mkdir -p /mysqldata/3306/errlog
mkdir -p /mysqldata/3306/tmpdir
mkdir -p /mysqldata/3306/slowlog
mkdir -p /mysqldata/3306/conf
chmod -R 755 /mysqldata/3306/conf
二、拉取镜像
docker pull mariadb:10.1.13(这里填自己公司的镜像路径或者外网的仓库地址)
检查下有没有
docker image ls | grep mariadb
三、启动容器
启动容器,镜像名和第二步镜像名称一致
(启动后,宿主机的/mysqldata/3306/data下会出现空的discard文件夹,可以删除。但每次重启容器就会产生)
docker run -d --name mysql3306 -e MYSQL_ROOT_PASSWORD=123456 --net=host \
-v /mysqldata/3306/data:/mysqldata/3306/data \
-v /mysqldata/3306/errlog:/mysqldata/3306/data/discard/errlog \
-v /mysqldata/3306/logdir/binlog:/mysqldata/3306/data/discard/logdir/binlog \
-v /mysqldata/3306/logdir/redolog:/mysqldata/3306/data/discard/logdir/redolog \
-v /mysqldata/3306/tmpdir:/mysqldata/3306/data/discard/tmpdir \
-v /mysqldata/3306/slowlog:/mysqldata/3306/data/discard/slowlog \
-v /mysqldata/3306:/mysqldata/3306/data/discard/other \
-v /mysqldata/3306/conf:/etc/mysql/conf.d \
--privileged=true mariadb:10.1.13
参数解释:
1)name 指定要创建的容器名
2)-e 指定MySQL用户的密码
3)--net是网络模式,这里用的host模式,即和宿主机共用一个网络命名空间,其实就是使用宿主机的IP和端口。也可以使用
-p 3306:3306这种方式来映射端口,但是它俩不能一起使用哦。
4)-v 地址映射。冒汗前是宿主机目录,冒号后是对应的容器内目录(如果该目录不存在,会自动创建)。映射关系就像图中画的一样,大家仔细对应一下,最后一个之所以要将conf文件夹映射到/etc/mysql/conf.d下,是因为官方文档说:将含有.cnf文件结尾的文件夹映射到这个文件夹下后,在启动MySQL容器的时候,会自动使用我们的配置文件来替换原来的。文档地址:https://hub.docker.com/_/mariadb。我把那段话截出来了:
5)--privileged=true 容器内的root拥有真正root权限,否则容器内root只是外部普通用户权限
四、查看镜像状态及日志(多种方式)
docker ps -a | grep mysql3306
docker logs mysql3306
docker inspect mysql3306
五、查看启动的端口占用情况
netstat -tunl|grep 3306
六、修改容器为自启动(根据自己的需求可改可不改)
docker container update --restart=always mysql3306
七、进入镜像
docker exec -it mysql3306 bash
八、测试连接mysql(或者在外部用Navicate连接)
mysql -uroot -p
1、为什么不将errlog/slowlog/logdir/tmpdir等放在和data目录同级,和宿主机一样,多方便。
我一开始也是这么想的,但是发现容器创建的这几个文件夹的时候,只会将数据文件夹赋用户组mysql:mysql,其它几个文件夹都是一堆乱七八糟的用户组,导致启动容器的时候没有权限读取这几个文件夹下的内容,从而启动失败。
具体可以通过 docker inspect 容器名 这个命令查如下的参数
"Config": {
......
"Entrypoint": [
"/docker-entrypoint.sh"
],
......
}
这个是容器的入口函数,即容器启动后会自动执行/docker-entrypoint.sh这个脚本。
通过查看该脚本,发现它仅把数据库数据文件夹(data)赋予了mysql:mysql用户组。
2、为什么还要在data下加一个discard目录?
也可以不加,直接放在data目录下。但是当你连接mysql后,用 show databases; 看一下(或者Navicate看一下),会发现多出来了errlog/slowlog/logdir/tmpdir这几个数据库,MySQL把data下的文件夹都当成了数据库。所以为了美观,我就加了层discard目录。
第一次写关于数据库的文章,呼,写了一个多小时,欢迎大佬们批评指正。