Docker新手教程(07)Docker与MySQL

0七、Docker与MySQL

一、场景说明和使用思路

场景说明:mysql

既然说服务器,怎么能离开各类数据库呢?而 MySQL 显然是最好用的数据库之一。git

可是博主本身经验来讲,最讨厌配 MySQL 的环境了,还好有 Docker 能够简单解决这个问题。github

使用思路:sql

Docker的容器是能够被删除、复制的。docker

但显然,MySQL 做为一个数据库,是不能接受这样的状况发生(由于会致使数据丢失)。shell

初步的解决思路,是容器负责业务逻辑,而存储数据存储于容器外。数据库

这样,便实现了业务代码(指 MySQL 的逻辑部分)与数据(指数据文件)分离的效果。express

其余说明:安全

为了方便省事,使用 MySQL5.6 版本。bash

由于 5.7 版本,会有一些很麻烦的事情出现。

二、生成MySQL容器

2.一、拉取MySQL镜像

命令:

docker pull mysql:5.6
复制代码

效果:

拉取了 MySQL 5.6 版本最新的 image

[root@qq20004604 ~]# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
docker-demo-01-express   0.0.1               416f1050c9bf        42 hours ago        907MB
mysql                    5.6                 98455b9624a9        2 weeks ago         372MB
复制代码

2.二、生成一个MySQL容器

命令:

docker container run --name [name] -p 3306:3306 -e MYSQL_ROOT_PASSWORD=[password] -d mysql:[version]
复制代码

示例代码:

docker container run --name mysql-demo -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234567890 -d mysql:5.6
复制代码

说明:

  • docker container run:经过image启动容器,也能够写为 docker run,但推荐使用更全的命令;
  • --name [name]:生成的容器的名字,若是不写,则会随机生成一个名字;
  • -p 3306:3306:将容器端口映射本机端口;
  • -e MYSQL_ROOT_PASSWORD=[password]:设置环境变量,这里指设置 MySQL 的默认密码。注意,不须要带括号也不须要带引号来包裹密码;
  • -d mysql:[version]:这里指你基于哪一个 MySQL 来生成容器;

示例代码如上,效果是:

  • 生成一个MySQL容器,容器名字是 mysql-demo
  • 容器是基于 MySQL 5.6 的 image 生成的;
  • 能够经过访问主机的端口 3306 来访问容器里的 MySQL;
  • MySQL 的初始密码是1234567890;

2.三、进行一些配置

首先,咱们一般须要远程访问,因此要配置一下。

进入容器的 MySQL:

  • docker container ps -a 列出全部容器;
  • 而后 docker container exec -it [containerID] /bin/bash 进入容器并输入命令行;
  • 此时已经进入容器了;
  • mysql -u root -p 进入mysql,会提示输入密码,输入密码便可(若是按我上面示例代码,默认密码是 1234567890

对 MySQL 进行配置:

容许 MySQL 被远程访问:

grant all privileges on *.* to 'root'@'%' identified by '[password]';
flush privileges;
复制代码
  • [password]:是密码,他被引号所包含在内,容许任何一个 IP 访问 root 帐号经过上面这个密码;
  • 第二行是刷新上面这行配置;
  • 注意,本机访问密码和这里的访问密码是独立的(互不干扰);

此时状况:

能够在其余机子上远程访问 MySQL,远程访问命令:

mysql -h [serverIP] -P 3306 -u root -p 
复制代码

而后输入密码便可登陆进去了


其余:

  1. 若是有相似 the 'information_schema.session_variables' feature is disabled 这样的报错,尝试使用 set @@global.show_compatibility_56=ON; 来解决。一般是由于使用 5.7 版本而不是 5.6 版本而出现的;

2.四、将 MySQL 数据放在容器以外

等等,虽然 MySQL 跑起来了,可是数据还在容器里呀?

解决方法很简单,将容器内外 link 起来便可。

核心方法是建立容器时,经过参数:-v [容器外路径]:[容器内路径] 来实现。

这样当容器内路径(该文件夹)下内容有所改动时,会被同步到容器以外。

#### 2.五、测试收尾,移除旧的 MySQL 容器:

  • 先执行 docker containers ps -a 查到全部容器,而后找到测试用的容器的 ID;
  • 再执行 docker rm [containerID] 删除测试容器;

### 三、数据持久化

命令:

docker run --name mysql-demo -v $PWD/mysqldata:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234567890 mysql:5.6
复制代码

说明:

  • 基于 MySQL 5.6 持久化生成容器;
  • 关键命令是:-v $PWD/mysqldata:/var/lib/mysql
  • 此时 MySQL 的数据,既保存在容器内,也保存在容器外;
  • 容器外本机目录为:$PWD/mysqldata,即当前目录下($PWD)的 mysqldata 文件夹下;
  • 容器内目录是 /var/lib/mysql(这个是 MySQL 默认目录);
  • 其余以前都写了,略;

四、持久化 + SQL预执行

理论上来讲,咱们指望 Docker 镜像生成容器并启动完毕后,咱们就不须要进行管理了。

但实际上来讲,不少时候并不能知足这样的要求。

以 MySQL 为例,一些权限管理、库表预建立之类的事情,并不能在建立的时候就实现。

而且在我实际实践中,MySQL 5.6 在做为 咱们自定义的 Docker 的基础镜像时,虽然能够正常运行。但若是生成容器时添加了持久化配置,却会提示权限错误没法正常运行。

由于这样的缘由,我决定将本来一次性操做(生成镜像后自动执行脚本),拆分为两步:

  1. 基于 MySQL 5.6 的镜像,使用持久化配置;
  2. 生成容器后,手动执行脚原本实现预先配置;

3.1 预先准备内容

避免手动执行命令,所以咱们应该预先准备一些脚本。

先列出文件目录:

create-image-mysql.sh    # 运行这个脚本建立容器
app                       # 用于在容器内执行的内容放这里
|--init.sh                # shell脚本,在这里将上面的SQL文件执行
|--data.sql               # 预建立数据库表SQL,用于在数据库初始化后,建立一些须要的database和table
|--privileges.sql         # 权限管理SQL,相关权限管理的SQL写在这里
复制代码

其中:

  • create-image-mysql.sh:这个脚本将于用于建立容器、建立数据持久化文件夹、将数据拷贝进容器并执行脚本;
  • app:这个文件夹内容将被拷贝进脚本,具体功能将在下面解释;

3.二、create-image-mysql.sh 建立管理容器

初始状况下,咱们只有一个下载好的 MySQL5.6 镜像(甚至都木有这个镜像,但这个耗时就过久了)。因此这个脚本要作的事情不少,包括下载image,建立容器,将容器外脚本拷贝进容器,执行初始化脚本等。

文件内容:

#!/usr/bin/env bash
# 若是须要使用其余镜像,记得自行修改脚本
# 修改映射到本机的端口也同样

appfilename="app"
mysqldatafilename="mysqldata"
imagename="docker-demo-02-mysql:0.0.1"
containername="mysql-demo"

# 创建持久化文件夹
if [ ! -d $mysqldatafilename ]; then
  mkdir "$mysqldatafilename"
fi

echo "【1】下载 mysql:5.6.43 版本 image"
docker pull mysql:5.6.43
echo "下载完成或无需下载"

echo "【2】先用本来镜像生成容器,初始化不须要密码(后续添加),并进行持久化配置"
echo "$PWD/$mysqldatafilename"
docker run --name "$containername" -d -v "$PWD/$mysqldatafilename":/var/lib/mysql -p 3306:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=yes mysql:5.6.43

# 若是本身手动执行的话,下面这行脚本能够在建立容器时即添加帐号密码
#docker run --name mysql-demo -d -v "$PWD/$mysqldatafilename":/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234567890 mysql:5.6.43

# 而后把 app 文件拷贝到容器里面
echo "【3】而后把 app 文件拷贝到容器里面"
docker cp "$PWD/$appfilename" "$containername":/

echo "【4】执行容器内的初始化脚本"
docker exec "$containername" sh "/$appfilename/init.sh"
复制代码

说明:

  • 这个脚本作了这些事情:
  • 【下载mysql镜像】:为了防止没有相关镜像,因此直接下载。若是已经下载的话并无什么影响;
  • 【经过镜像生成容器】:这个生成过程,包括持久化设置、设置端口映射、初始化不须要密码等;
  • 【将app文件夹拷贝到容器内】:其中 init.sh 文件是必须的,其余根据 init.sh 文件的内容而定;
  • 【执行在容器内的 init.sh 文件】:用于初始化容器的配置;
  • 注意一件事情,当执行这里最后一行脚本时,并不表明容器内 MySQL 服务已经彻底启动完毕。因此在 init.sh 脚本内作了等待处理,以增长容错性;

3.三、核心脚本:init.sh

全部在容器内,须要执行的内容,好比 SQL 脚本呀,或者是一些配置内容呀,都经过它来执行。

在这个脚本里,有如下命令:

#!/usr/bin/env bash
# 等待 MySQL 启动完毕
echo '当前 mysql 服务状态:'
echo `service mysql status`
echo "1.等待15秒,确保mysql已经启动了,否则 SQL 可能没法顺利导入"
sleep 15
echo '当前 mysql 服务状态:'
echo `service mysql status`

# 导入预建立库表的sql文件
echo "2.开始导入数据"
mysql < /app/data.sql
echo '3.导入数据完毕.....并等待3秒.....'
sleep 3

# 因为最开始设置mysql为免密登录,为了安全,在此设置mysql密码,并进行权限配置
echo '4.开始进行权限配置.....'
# 导入修改mysql权限设置的文件
mysql < /app/privileges.sql
echo '5.修改密码完毕.....'

echo '----------------------------------------------------------'
echo "mysql容器启动完毕。若是导入数据时,显示 Can't connect to local MySQL server through socket,则说明导入失败。容器外手动执行命令【docker exec mysql-demo sh /app/init.sh】便可"
echo '----------------------------------------------------------'
复制代码

说明:

  • 在这个脚本里,作了这些事情:
  • 【等待 MySQL 启动完毕】:因为第一次启动容器后,mysql 服务并非当即可用的(他须要必定时间来配置),所以咱们手动等待15秒时间(具体等待多久,跟服务器性能有关);
  • 【导入预建立库表SQL】:可能咱们须要预先建立一些库和表格,将这些sql语句写入 data.sql 文件中;
  • 【权限管理SQL】:之因此这个SQL放到后面,是由于初始状况咱们不须要密码就能导入数据(启动容器时配置的环境变量),导入这个SQL后,以后再导入sql文件就须要帐号密码了;
  • 【通报完毕,并显示提示信息】:告知用户什么状况下是正确的情况(虽然理论上也能够本身写个脚本判断输出);
  • 【其余】:若是你有其余须要执行的命令,能够在这个脚本里执行,或者写在其余shell文件里,在这个脚本里执行该shell文件;

3.四、建立库表SQL

正常状况下, MySQL 每每须要预建立一些 database 和 table,以供程序使用,而这些最好在容器建立的时候就作到。

这里是由 data.sql 文件来实现的。

在这个 SQL 文件里,有如下内容:

-- 建立数据库
DROP database IF EXISTS `docker_test_database`;
create database `docker_test_database` default character set utf8 collate utf8_general_ci;
-- 切换到test_data数据库
use docker_test_database;
-- 建表
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
	`id` bigint(20) NOT NULL,
	`name` varchar(255) DEFAULT NULL,
	`age` bigint(20) NOT NULL,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- 插入数据
INSERT INTO `person` (`id`,`name`,`age` )
VALUES
   (0,'Tom',18);
复制代码

说明:

  • 这个SQL文件作了如下事情:
  • 【若是有库docker_test_database,则扔掉】:只有当须要一个新的database才须要这么写;
  • 【建立docker_test_database】:建立 database,并切换到这个 database;
  • 【若是有表person,则扔掉】:缘由同上面;
  • 【创建表】:建立table,并预设表结构;
  • 【插入一条测试数据】:若是插入成功,说明 MySQL 能够正常运行;
  • 若是须要其余sql操做,也能够写在这个 SQL 文件里,或者每一个database一个sql文件,而后依次导入。

3.五、权限管理SQL

一个良好的数据库必然会有多个不一样权限的角色,只有这样才能确保数据库的安全性和稳定性。所以,咱们须要有一个权限管理SQL。

文件内容:

use mysql;
select host, user from user;
-- 任意地点的root帐号能够用一个很是复杂的密码登陆(瞎打的),用于禁止无密码登陆
GRANT ALL ON *.* to root@'%' identified by 'fwefwefvvdsbwrgbr9jj24intwev0h0nbor32fwfmv1' with grant option;
-- 容许root用户以密码 123456 来登陆(仅限本地)
GRANT ALL ON *.* to root@'localhost' identified by '123456' with grant option;
-- 将 docker_test_database 数据库的权限受权给建立的docker用户,密码为 1234567890,但只能本机访问(指容器内)
-- 若是用户docker不存在,则建立用户docker
GRANT ALL ON docker_test_database.* to docker@'localhost' IDENTIFIED by '1234567890';
-- 其余任意地方能够访问,须要使用密码 1654879wddgfg
GRANT ALL ON docker_test_database.* to docker@'%' IDENTIFIED by '1654879wddgfg';
-- mysql新设置用户或权限后须要刷新系统权限不然可能会出现拒绝访问:
FLUSH PRIVILEGES;
复制代码

说明:

  • 这个脚本里作了这些事情:
  • 【切换到mysql这个库】:这个库负责权限管理;
  • 【查看当前用户有哪些】:显示当前mysql用户;
  • 【禁止建立容器时设置的无密码登陆】:这个是为了安全性所实现的,密码尽可能复杂一些,由于这个是容许远程访问root帐号;
  • 【容许root用户本地登陆】:这个是本机(容器内)登陆root帐号,因此密码能够简单一些。但如有实际须要,也应该写复杂一些。
  • 【为docker_test_database这个库创造一个用户】:这个用户 docker 专门负责操做 docker_test_database 这个 database,因此权限比较低一些,容许本地访问(有密码);
  • 【容许docker用户远程访问】:这个是为了测试远程能够访问数据库,也能够不容许远程访问(避免出现数据库入侵);
  • 总的来讲,是权限控制的一些内容。这个SQL推荐在最后执行,避免其余SQL输入数据时须要密码的问题。

3.六、验证

远程验证连接为:

mysql -h [远程主机IP地址] -P 3306 -u root -p
复制代码

而后输入密码便可。

四、总结

将以上文件拷贝到主机,而后执行 create-image-mysql.sh 脚本便可。会自动安装并配置好 MySQL。

经过以上操做,咱们实现了需求。如今,咱们再来回顾一下这个需求作了什么事情:

  • 安装了 MySQL 5.6 版本;
  • 持久化 MySQL 数据(将 MySQL 数据存储到容器外);
  • 预先建立了一些 database 和 table;
  • 对 MySQL 进行了权限管理配置;

本项目资源请在个人github项目地址查看:

github.com/qq20004604/…

相关文章
相关标签/搜索