基于docker的mysql安装实战
前言
最近需要基于两台windows服务器(24核128G核80核128G)搭建数仓,数仓决定采用hadoop+spark的方式搭建。
由于操作系统是基于windows的,而数仓系统大多是基于linux,因此决定采用docker容器化进行安装。
万里长征,决定现行采用mysql安装踩点。
什么是docker
docker是一个用Go语言实现的开源项目,可以让我们方便的创建和使用容器,docker将程序以及程序所有的依赖都打包到docker container,这样你的程序可以在任何环境都会有一致的表现。
简单理解,docker通过容器化技术,将环境和应用程序一起打包运行,进而屏蔽环境差异,实现“build once, run everywhere”,同时实现快速部署。
docker的基本概念
- dockerfile
- image
- container
实际上你可以简单的把image理解为可执行程序,container就是运行起来的进程。
那么写程序需要源代码,那么“写”image就需要dockerfile,dockerfile就是image的源代码,docker就是”编译器”。
因此我们只需要在dockerfile中指定需要哪些程序、依赖什么样的配置,之后把dockerfile交给“编译器”docker进行“编译”,也就是docker build命令,生成的可执行程序就是image,之后就可以运行这个image了,这就是docker run命令,image运行起来后就是docker container。
docker的底层实现
docker基于Linux内核提供这样几项功能实现的:
NameSpace
我们知道Linux中的PID、IPC、网络等资源是全局的,而NameSpace机制是一种资源隔离方案,在该机制下这些资源就不再是全局的了,而是属于某个特定的NameSpace,各个NameSpace下的资源互不干扰,这就使得每个NameSpace看上去就像一个独立的操作系统一样,但是只有NameSpace是不够。
Control groups
虽然有了NameSpace技术可以实现资源隔离,但进程还是可以不受控的访问系统资源,比如CPU、内存、磁盘、网络等,为了控制容器中进程对资源的访问,Docker采用control groups技术(也就是cgroup),有了cgroup就可以控制容器中进程对系统资源的消耗了,比如你可以限制某个容器使用内存的上限、可以在哪些CPU上运行等等。
有了这两项技术,容器看起来就真的像是独立的操作系统了。
mysql镜像安装&运行
如果只是想跑起来,mysql docker镜像的安装和运行非常的简单
- 在docker hub中搜索mysql镜像,或者docker desktop搜索镜像,查找我们需要的mysql docker镜像,本人选择的tag为 8.0.33,tag对应的有pull命令。
- 运行
docker pull mysql:8.0.33
下载之前搜索到的镜像。 - 运行命令
docker run --name test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.33
启动容器
其中 -p 3306:3306 表示将容器内的3306桥接到本机的3306端口,-d mysql:8.0.33 为之前我们下载的镜像名称。
要是不想命令,也可以直接在docker desktop上点击运行。
这样,一个mysql容器就运行了,但是这个容器只是试玩的,它存在以下几个问题
- 资源未隔离【可能导致该容器占用完整个服务器的情况】
- 存储未考虑【容器内的数据在容器重启后便会丢失】
- 配置未优化【mysql默认配置无法满足生产要求】
因此在实际的生产部署中,我们需要解决上面三个情况
问题解决
资源隔离问题
资源方面,初步拍脑袋决定给mysql的容器为5G4核,网络的话,期望container能组成局域网,但是mysql服务最好在主机上有端口映射,这样主机可以对外提供服务。磁盘方面,则不进行限制了。
内存隔离
与操作系统类似,容器可以使用的内存包括两部分:物理内存和Swap【不理解的可以阅读深入理解swap交换分区理解及扩存了解下物理内存和swap的作用及关系】。
Docker通过下面两组参数来控制容器内存的使用量。
-m 或 –memory:设置内存的使用限额,例如:100MB,2GB。
–memory-swap:设置内存+swap的使用限额。
默认情况下,上面两组参数为-1,即对容器内存和swap的使用没有限制。如果在启动容器时,只指定-m而不指定–memory-swap, 那么–memory-swap默认为-m的两倍。
举例
1 | 允许该容器最多使用200MB的内存和100MB 的swap。 |
那么我们到底应该怎么设置呢?
参考redhat公司的推荐ch-swapspace
- 内存小于4GB时,推荐不少于2GB的swap空间;
- 内存4GB~16GB,推荐不少于4GB的swap空间;
- 内存16GB~64GB,推荐不少于8GB的swap空间;
- 内存64GB~256GB,推荐不少于16GB的swap空间。
本次mysql容器规划5G,那么推荐是不少于4GB,由于docker swap默认不得小于memory,因此就采用5GB,
因此最终的运行参数为
1 | docker run --name mysql -m 5G --memory-swap=5G -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.33 |
CPU 隔离
docker对cpu的隔离分为三种
- CPU份额控制:-c或–cpu-shares
- CPU核控制:–cpuset-cpus、–cpus
- CPU周期控制:–cpu-period、–cpu-quota
具体这里就不进行展开了,可以阅读Docker资源(CPU/内存/磁盘IO/GPU)限制与分配指南进行了解。
本人直接采用了CPU核控制。
–cpus: 限制容器运行的核数;从docker1.13版本之后,docker提供了–cpus参数可以限定容器能使用的CPU核数。这个功能可以让我们更精确地设置容器CPU使用量,是一种更容易理解也常用的手段。
1 | 容器最多可以使用主机上两个CPU ,除此之外,还可以指定如 1.5 之类的小数。 |
由于本次规划的分配核数为4,因此最终的一个参数为
1 | docker run --name mysql --cpus=4 -m 5G --memory-swap=4G -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.33 |
网络配置
docker网络相关的文章可以阅读全网最详细的Docker网络教程详解这篇文章进行了解。
对外提供服务,通过 -p 参数进行映射即可。
1 | 将容器内的3306端口映射到宿主机的1306端口 |
容器的局域网设置
- 创建网络
1
docker network create -d macvlan --subnet=172.16.1.0/24 --gateway=172.16.1.1 -o parent=eth0 dw-network
- 查看是否安装成功结果如下,可以看到dw-network网络创建完毕
1
docker network ls
1
2
3
4
5
6PS C:\Users\dell> docker network ls
NETWORK ID NAME DRIVER SCOPE
415ecf186909 bridge bridge local
b01f87d53a20 dw-network macvlan local
0ec71466bed7 host host local
417fdf60fc8c none null local - 启动容器并绑定固定ip
1
2
3
4
5
6
7
8
9docker run --net=dw-network --name="test1" --ip=172.16.1.11 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.33
docker run --net=dw-network --name="test2" --ip=172.16.1.12 -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0.33
查看容器
docker ps -a
可以看到有两个容器已经启动
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
569bb77f586e mysql:8.0.33 "docker-entrypoint.s…" 4 seconds ago Up 2 seconds test2
224b3db441ae mysql:8.0.33 "docker-entrypoint.s…" 30 seconds ago Up 29 seconds test1 - 网络验证
1
2
3
4进入容器
docker exec -it test1 /bin/bash
docker exec -it test1 /bin/bash
容器内telnet,yum都没,暂时就不验证了。。。。
磁盘隔离
Block IO 是另一种可以限制容器使用的资源。Block IO 指的是磁盘的读写,docker 可通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽
注:目前 Block IO 限额只对 direct IO(不使用文件缓存)有效。
这里就不进行权重限制了,后续有需求再进行配置。
如果使用的话,应该会采用权重策略。毕竟磁盘是最大的资源瓶颈。
存储持久化问题
docker内的文件都是临时的,当重启时,数据就会全部丢失。
但是docker贴心的提供了volume技术解决这一持久化问题。
即将宿主机的目录映射到容器目录。
mysql设计目录相关的,一个为/etc/my.cnf,一个为存储和日志,存储和日志默认配置都在/var/lib/mysql目录下,因此建立对应的volume映射
宿主机目录 | 容器目录 |
---|---|
D:\work\docker\mysql/conf/my.cnf | /etc/my.cnf |
D:\work\docker\mysql/conf/ | /etc/mysql |
D:\work\docker\mysql/logs | /var/log/mysql |
D:\work\docker\mysql/data | /var/lib/mysql |
因此一个参数为
1 | docker run --name test-mysql -p 3306:3306 \ |
mysql 性能配置
mysql的内存分配,参考
实战操作
铺垫了这么久,终于可以进行最后的实战操作记录了。
1.镜像下载
1 | docker pull mysql:8.0.33 |
目录&文件准备
1 | mkdir docker #docker总目录 |
命令启动
创建网络
1 | docker swarm init |
容器启动
1 | docker run --name="mysql" ` |
docker run -it –network dw-network –rm mysql 8.0.33 -hlocalhost -uroot -p
docker run -it –rm mysql 8.0.33 -hlocalhost -uroot -p
一些注意点
[Warning] World-writable config file ‘/etc/mysql/conf.d/my22.cnf’ is ignored.
这个报错,因为配置文件权限为777,mysql认为安全隐患较大,因此忽略。
解决方法
windows下本人未找到对应的linux权限
进入容器
修改文件权限
1 | chmod 644 my.cnf |
rpc error code = PermissionDenied desc = network dw-network not manually attachable.
当使用swarm的overlay网络,在该网络中运行容器时报“network xx not manually attachable”的错误
默认情况下使用docker network create -d overlay NET 创建的网络只能被swarm service使用,如果需要被独立的容器使用,需要添加–attachable选项
1 | docker network create -d overlay --attachable my-attachable-overlay |
总结
不知怎么的,以前docker看的云里雾里的东西,现在看起来也能理解了,一些踩坑点自己就能想到。
总的来说,使用docker安装应用,在有官方镜像的情况下,突出一个轻松加简单,我们只需自己做好资源的规划和配置即可。
build once,run anywhere,在docker这个技术下,很好的实现了。
香~