在Docker中安装Mysql
前言
此篇幅内容较多,讲解的很详细,也有很多知识点。能耐心认真的读完,就很不错了~
如果你觉得此文章不错的话,或者是根据此文档进行安装mysql的话,抽空在文档最下方留个言吧让我看到你的支持
Docker 中国官方镜像加速
如果觉得国外下载速度太慢,可以配置一个“Docker 中国官方镜像加速”,来提高镜像下载的速度。
一般情况下,都会永久性的配置镜像加速,在Linux中修改 /etc/docker/daemon.json 文件,填入以下内容:
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
如果daemon.json不存在的话,需要自己创建一下。
文件修改保存成功之后,记得重启一下Docker服务,以便让这个镜像加速生效。
重启Docker服务
我们在【在centos系统中安装Docker】一节中讲过Docker随着服务器重启自动启动的内容,正好可以通过命令service docker restart来实现Docker服务的重启。
然后我们在Linux中执行命令:
service docker restart
出现下图所示结果,表明Docker服务已经重新启动了!这样就可以永久性的使用Docker加速服务了。
如果不做特别的配置的话,之前处于运行状态的容器,随着Docker服务的重启也会停止运行。
下载mysql镜像
docker pull mysql
如果配置了镜像加速,那么在下载mysql镜像或者其他比较大的文件的时候,会发现下载速度变得非常快!
启动mysql容器
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql
其中 -e 的作用是用于设置环境变量,mysql默认用户名为root,则MYSQL_ROOT_PASSWORD即为root设置密码,即123456
查看运行的mysql容器
docker ps
如下图:
mysql容器已经正常启动了!
进入mysql容器
既然mysql服务启动了,如果我们想对mysql进行操作(比如进入命令行操作、客户端连接等操作),该怎么办?
通过 docker exec 命令进入mysql容器:
docker exec -it c9 /bin/bash
其中的“c9”指的当前mysql容器ID的前面部分值(在上图就可以看出来mysql容器的ID是 c94faeed480a)。
回车运行效果如下图:
其实这个时候,命令行控制台可以输入mysql相关的命令了。
连接mysql数据库
mysql -u root -p123456
如下图:
这个就是我们非常熟悉的mysql命令行界面了!
我们可以在这里创建数据库、表等操作。再次印证了Docker的强大和方便!
查看当前所有的数据库
在mysql命令行中执行命令:
show databases;
如下图所示:
完全就是和平常使用mysql一样。
创建数据库、表、新增测试数据
- 创建数据库
create database docker_test;
效果如下图:
这里我就创建了一个数据库docker_test
- 选择数据库
首先需要选择具体的数据库,执行命令选择刚刚创建的数据库:
use docker_test
- 创建表:
create table test(name varchar(20),age int(11));
创建了test表,有2个字段:name、age
- 添加测试数据:
insert into test values("Kitty",26),("Tom",18),("Jack",36);
这里就简单添加3条测试数据。
我们查询一下数据是否存在于数据库中:
select * from test;
一切OK!
客户端连接mysql数据库
既然mysql成功启动并运行,除了能在命令行中操作mysql数据库之外,肯定也是必须要能在客户端上连接和操作数据库才行。
下面我就在我本地电脑上通过数据库客户端软件连接一下这个mysql数据库, 看看能不能正常连接和操作。
我使用的是DataGrip客户端软件,如果你们需要的话,可以下载使用 https://pan.baidu.com/s/1NkzEG_rjwFBylUSMxfIUzw
如果版本低的话,可以到官方下载最新版本 https://www.jetbrains.com/datagrip/
打开本地DataGrip客户端,新建连接mysql数据库
输入正确的mysql相关信息,连接数据库:
输入完成之后,可以点击下方的 Test Connection 按钮,来测试连接是否正常。
查看创建的****数据库和表:
到此,mysql的相关服务已经正常访问和操作了。这和我们传统的使用mysql没有什么不同。
客户端中操作表数据
我们通过DataGrip客户端,在test表中手动再添加一条数据,然后我们在docker中看看是否能查看到新增的数据:
【注意】:我这里添加了一条带有中文的数据。
进入mysql容器中查询表数据
呀!是不是发现问题了~ 没错,中文乱码!怎么解决呢?
mysql容器中解决表数据中文乱码
查看mysql容器的ID:
进入mysql的docker容器:
docker exec -it c9 /bin/bash
编辑mysql配置文件:
vim /etc/mysql/my.cnf
如果提示 vim: command not found 的错误信息,需要安装相关依赖包,执行下面两个命令即可:
apt-get update
apt-get install vim
在my.cnf文件中加入以下配置:
[mysqld]
character-set-server=utf8
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
最终修改结果为:
重新进入mysql容器,查询表数据,显示结果为:
可以看到,已经正常显示中文了!
停止并重启mysql容器,再次查看效果
客户端DataGrip重新连接mysql:
客户端连接正常!
进入mysql容器,查看表数据:
mysql容器重启之后,查询数据正常显示中文!一切没什么问题了~
通过commit命令提交新的镜像
根据在mysql容器中所做的更改,创建新的mysql镜像。
回想一下,我们在mysql容器中做了什么更改?
创建数据库、表、新增数据、修改my.cnf配置文件,就是这些吧~
使用commit命令****提交新镜像
通过在Linux命令行中执行命令,提交新的镜像:
docker commit c9 mysql-new
其中,“c9”就是指的容器ID,新的镜像名称为“mysql-new”。
如下图:
查看所有镜像列表:
是不是发现了我们创建的新的镜像mysql-new了。
启动新创建的mysql镜像
由于上面我们已经运行了一个mysql的容器了,端口是3306,所以我们新运行一个mysql容器的时候,端口号就不能是3306了,这里我指定为3307,且容器的别名是mysql-new,方便区分查看。
进入新创建的mysql容器
-
查看mysql数据库信息
-
查看my.cnf配置文件内容
从上面2张图中,可以明显的看到,我们之前创建的数据库docker_test、表test,都没有了!但是修改的my.cnf配置文件的内容还是保留着的。
why??? 为什么会这样呢?
官方文档在commit命令的介绍中,有这样一段话:
The commit operation will not include any data contained in volumes mounted inside the container.
意思是commit操作并不会包含容器内挂载数据卷中的数据。
如果对于“数据卷”不了解的话,确实看不懂是什么意思。
数据卷与数据卷容器
生产环境中使用Docker的过程中,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。
容器中管理数据主要有两种方式:
数据卷(Data Volumes):数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器。
数据卷容器(Data Volume Containers):数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷,供其他容器挂载使用的。
根据官方文档对于commit的介绍中,可以猜测到为何之前创建的数据库、表都不见了,原因是因为mysql容器的挂载数据卷引起的。
我们可以通过命令查看到别名是“mysql”的容器挂载数据卷的目录。
看一下我们的“mysql”容器的ID信息,方便查看。
通过命令docker inspect查看mysql这个容器的数据卷挂载信息:
docker inspect c9
执行命令之后,由于显示的内容比较多,这里我们就贴一下重要的信息:
通过图中可以看到,mysql容器将容器内的/var/lib/mysql路径作为volume挂载。真正的数据库相关数据文件所在的目录就是“Source”对应的目录,即:/var/lib/docker/volumes/1b0b17f6a4f78d357a187116d75991db8ee784213e67cc9b9988c8ef647fe563/_data
我们可以进入mysql容器查看/var/lib/mysql目录下的内容:
发现的确是mysql数据库的数据文件(红色区域)。
这时候,我们切换到Linux命令行,进入到mysql容器的数据挂载目录,看看该目录下有什么内容:
/var/lib/docker/volumes/1b0b17f6a4f78d357a187116d75991db8ee784213e67cc9b9988c8ef647fe563/_data
如下图所示:
咦~ 是不是发现了什么!把黄色区域的内容与上图中红色区域内容进行对比,是不是内容一模一样!
这也就印证了,当初我们在mysql容器中创建的数据库、表等,真正的数据库文件存放的位置就是在宿主机下面,而不是存放在容器中。
到此,我们终于知道了为何mysql-new容器中的数据库、表都不见了,原来数据库文件是存放在宿主机上的。
那该如何解决这个问题呢?怎样才能让mysql-new容器启动之后可以正常加载我们之前创建的数据库、表等数据呢?这就引入了下面的正题 —— 数据挂载。
数据挂载
docker的数据挂载分为三种,volume、bind mount和tmpfs,关于三种的具体说明,有兴趣了解的可以看一下官网的文档 https://docs.docker.com/storage/
参考文档 《基于docker部署mysql的数据持久化问题》 https://www.jianshu.com/p/530d00f97cbf
上面的文章里面,把问题描述的非常详细清楚。我这里就不多做说明了。
使用 -v 实现数据挂载(数据卷)
如果我们想在 run 一个新的mysql容器的时候,可以正常访问我们之前在mysql容器中创建的数据库、表数据,则在docker run命令启动容器的时候,就需要指定挂载目录。
注意:要想让新的mysql容器能正常挂载名称是“mysql”容器,前提是需要先停止名称是“mysql”的容器,不然的话,即使run命令配置正确,容器启动的时候会一直报错:
上图就是因为没有事先停止mysql容器导致的。
下面开始具体操作:
- 先停止mysql容器
- 重新启动一个新的mysql容器,命令如下:
docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql-v -v /var/lib/docker/volumes/1b0b17f6a4f78d357a187116d75991db8ee784213e67cc9b9988c8ef647fe563/_data:/var/lib/mysql mysql
最重要的一个参数 -v :挂载数据卷。-v 后面的值中间有“:”号,前半部分指的是宿主机的目录(也就是我们上面的mysql容器的数据库存储的目录),后半部分指的是容器的目录。
实现的效果就是说:新启动的容器,挂载宿主机的目录,实现数据共享。
运行结果:
登录新的mysql-v容器,查看数据库信息
直接看下图的命令操作吧:
看到效果了吧!在这个mysql-v的新容器里面,已经可以看到我们一开始在“mysql”容器中创建的数据库和表了。
也就实现了容器之间的数据共享。
核心的实现就是在run命令里面加入了 -v 参数。如果不太明白-v的含义的,可以自行网上查询资料了解学习,加深印象。
上面我们解决了容器挂载数据卷的问题,但是细心的朋友,可能还有一个疑问:
为什么修改了my.cnf配置文件、以及运行mysql镜像时指定的MYSQL_ROOT_PASSWORD=123456,却依然可以在新容器mysql-new中使用呢,为什么这俩样数据不会消失呢?
官方文档对于commit命令还有这样一段描述:
It can be useful to commit a container’s file changes or settings into a new image.
谷歌翻译过来的意思就是:将容器的文件更改或设置提交到新映像可能很有用。
还记得我们当初运行第一个mysql容器的时候,docker run 命令是怎样的,这里贴一下当时启动容器的命令:
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name=mysql mysql
其中,里面使用到了 -e 参数,设置了root用户的密码为123456。
所以,结合官方文档对commit的介绍(It can be useful to commit a container’s file changes or settings into a new image. ),就可以知道,通过 -e 设置的信息,在使用commit提交新镜像的时候,这些设置被容器保留了下来,commit命令使用这些设置构建了新的镜像,在新容器里面使用的是相同的设置。
这也印证了,我们在mysql-new容器中登录数据库的时候,登录密码写的是123456。因为在第一次启动mysql服务的时候,用户root密码是通过 -e 指定的,所以在commit提交新的镜像的时候,是被一同提交到了新镜像mysql-new中。
数据卷容器
通过数据卷容器也可以实现多个容器间的数据共享。
如果要授权一个容器访问另一个容器的数据卷,我们可以使用-volumes-from参数来执行docker run。
(这里就不多做说明了,有兴趣的可以网上自行查阅资料研究)