场景说明:mysql
既然说服务器,怎么能离开各类数据库呢?而 MySQL 显然是最好用的数据库之一。git
可是博主本身经验来讲,最讨厌配 MySQL 的环境了,还好有 Docker 能够简单解决这个问题。github
使用思路:sql
Docker的容器是能够被删除、复制的。docker
但显然,MySQL 做为一个数据库,是不能接受这样的状况发生(由于会致使数据丢失)。shell
初步的解决思路,是容器负责业务逻辑,而存储数据存储于容器外。数据库
这样,便实现了业务代码(指 MySQL 的逻辑部分)与数据(指数据文件)分离的效果。express
其余说明:安全
为了方便省事,使用 MySQL5.6 版本。bash
由于 5.7 版本,会有一些很麻烦的事情出现。
命令:
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
复制代码
命令:
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-demo
;首先,咱们一般须要远程访问,因此要配置一下。
进入容器的 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
复制代码
而后输入密码便可登陆进去了
其余:
the 'information_schema.session_variables' feature is disabled
这样的报错,尝试使用 set @@global.show_compatibility_56=ON;
来解决。一般是由于使用 5.7 版本而不是 5.6 版本而出现的;等等,虽然 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
复制代码
说明:
-v $PWD/mysqldata:/var/lib/mysql
;$PWD/mysqldata
,即当前目录下($PWD
)的 mysqldata 文件夹下;/var/lib/mysql
(这个是 MySQL 默认目录);理论上来讲,咱们指望 Docker 镜像生成容器并启动完毕后,咱们就不须要进行管理了。
但实际上来讲,不少时候并不能知足这样的要求。
以 MySQL 为例,一些权限管理、库表预建立之类的事情,并不能在建立的时候就实现。
而且在我实际实践中,MySQL 5.6 在做为 咱们自定义的 Docker 的基础镜像时,虽然能够正常运行。但若是生成容器时添加了持久化配置,却会提示权限错误没法正常运行。
由于这样的缘由,我决定将本来一次性操做(生成镜像后自动执行脚本),拆分为两步:
避免手动执行命令,所以咱们应该预先准备一些脚本。
先列出文件目录:
create-image-mysql.sh # 运行这个脚本建立容器
app # 用于在容器内执行的内容放这里
|--init.sh # shell脚本,在这里将上面的SQL文件执行
|--data.sql # 预建立数据库表SQL,用于在数据库初始化后,建立一些须要的database和table
|--privileges.sql # 权限管理SQL,相关权限管理的SQL写在这里
复制代码
其中:
create-image-mysql.sh
:这个脚本将于用于建立容器、建立数据持久化文件夹、将数据拷贝进容器并执行脚本;app
:这个文件夹内容将被拷贝进脚本,具体功能将在下面解释;初始状况下,咱们只有一个下载好的 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"
复制代码
说明:
全部在容器内,须要执行的内容,好比 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 '----------------------------------------------------------'
复制代码
说明:
data.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。
文件内容:
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 -h [远程主机IP地址] -P 3306 -u root -p
复制代码
而后输入密码便可。
将以上文件拷贝到主机,而后执行 create-image-mysql.sh 脚本便可。会自动安装并配置好 MySQL。
经过以上操做,咱们实现了需求。如今,咱们再来回顾一下这个需求作了什么事情:
本项目资源请在个人github项目地址查看: