docker 搭建Mysql比较蛋疼的点是配置文件映射,本文将会重点围绕这一点进行介绍。
docker部署mysql非常快速。了解docker安装mysql十分有必要,在深入mysql学习过程中可能会遇到不同版本细节对比,或者需要对比子版本号的bug修挂情况差异对比情况,这时候用docker快速运行和卸载不同版本的mysql,或者一个机器上跑多个不同版本的mysql都是十分方便的。
本次实验的个人是用的是 Win11物理机 + VM 16虚拟机软件 + CetnerOs7.9 版本+ docker + mysql5.7 的方案(这个层层套娃有点绷不住)。
个人认为最佳答案是查阅官方文档照着一步步做即可,吊打网络上的所有博客:Install Docker Engine on Ubuntu | Docker Documentation
个人在安装过程中碰到了下面的问题。
Job for docker.service failed because start of the service was attempted too often.
一般出现在安装docker之后切换国内镜像重启会报这样的错误:
Job for docker.service failed because start of the service was attempted too often. See "systemctl status docker.service" and "journalctl -xe" for details. To force a start use "systemctl reset-failed docker.service" followed by "systemctl start docker.service" again.
解决办法是把daemon.json配置文件改成daemon.conf(官方真是闲的没事干=-=)。
mv daemon.json daemon.conf
Error response from daemon: Gethttps://registry-1.docker.io/v2/: net/http: request canceled 报错
拉取镜像的时候发现总是拉取失败,解决方案如下:
vim 打开/etc/resolv.conf
sudo vi /etc/resolv.conf
将 nameserver 改为8.8.8.8
# Generated by NetworkManager
# nameserver 192.168.1.1
# nameserver 192.168.0.1
nameserver 8.8.8.8
~
修改之后重启docker:
sudo systemctl restart docker
最后检查重试:
[roothome.php?mod=space&uid=485241 docker]# sudo docker pull mysql:5.7
[zxd@localhost seata]$ docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 13614 [OK]
mariadb MariaDB Server is a high performing open sou… 5197 [OK]
phpmyadmin phpMyAdmin - A web interface for MySQL and M… 713 [OK]
percona Percona Server is a fork of the MySQL relati… 597 [OK]
bitnami/mysql Bitnami MySQL Docker Image 80 [OK]
databack/mysql-backup Back up mysql databases to... anywhere! 77
linuxserver/mysql-workbench 45
ubuntu/mysql MySQL open source fast, stable, multi-thread… 40
linuxserver/mysql A Mysql container, brought to you by LinuxSe… 38
circleci/mysql MySQL is a widely used, open-source relation… 28
google/mysql MySQL server for Google Compute Engine 22 [OK]
rapidfort/mysql RapidFort optimized, hardened image for MySQL 13
bitnami/mysqld-exporter 4
ibmcom/mysql-s390x Docker image for mysql-s390x 2
vitess/mysqlctld vitess/mysqlctld 1 [OK]
newrelic/mysql-plugin New Relic Plugin for monitoring MySQL databa… 1 [OK]
hashicorp/mysql-portworx-demo 0
rapidfort/mysql-official RapidFort optimized, hardened image for MySQ… 0
docksal/mysql MySQL service images for Docksal - https://d… 0
mirantis/mysql 0
rapidfort/mysql8-ib RapidFort optimized, hardened image for MySQ… 0
cimg/mysql 0
eclipse/mysql Mysql 5.7, curl, rsync 0 [OK]
drud/mysql 0
silintl/mysql-backup-restore Simple docker image to perform mysql backups… 0 [OK]
使用下面的命令获取镜像,个人用了mysql-5.7的版本:
docker pull mysql:5.7
可以使用下面的命令检查当前下载的所有镜像:
docker images
个人获取到的镜像内容如下:
[zxd@localhost seata]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 0256c63af7db 5 days ago 117MB
mysql 5.7 d410f4167eea 2 weeks ago 495MB
redis <none> 3e12e2ceb68f 2 weeks ago 117MB
apache/rocketmq 4.9.4 a2a50ca263c3 5 months ago 548MB
apacherocketmq/rocketmq-dashboard latest eae6c5db5d11 14 months ago 738MB
hello-world latest feb5d9fea6a5 15 months ago 13.3kB
在正式的启动Mysql镜像之前,先建立映射目录的配置。
mkdir -p /opt/mysql/data /opt/mysql/logs /opt/mysql/conf
在/root/mysql/conf中创建XXXX.cnf文件(XXX名字叫什么都行,后缀不能改)。这里个人创建的mysql.conf:
touch mysql.cnf
创建容器,命令中将数据日志,配置文件映射到宿主机,注意这里的 root 密码为 root :
docker run -p 13306:3306 --name mysql -v /opt/mysql/conf:/etc/mysql/conf.d -v /opt/mysql/logs:/logs -v /opt/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
运行之后,我们执行docker ps查看当前运行的mysql镜像:
[zxd@localhost conf]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e95a0bc7b4a4 mysql:5.7 "docker-entrypoint.s…" About a minute ago Up About a minute 33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp mysql
相关运行参数解释如下:
-d:后台运行容器
-p将容器的端口映射到本机的端口
-v将主机目录挂载到容器的目录
-e设置参数
如果要访问mysql,需要先进入对应的容器当中,我们先docker ps查看容器ID。
[root@localhost opt]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
56f5e5575d35 mysql:5.7 "docker-entrypoint.s…" 20 minutes ago Up 20 minutes 33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp mysql
之后进入到容器。
docker exec -it 56f5e5575d35 /bin/bash
然后执行下面的命令进入到mysql。
bash-4.2# mysql -uroot -proot
[zxd@localhost conf]$ mysql -uroot -proot -P 13306
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.51 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
退出容器,最后查看/opt/mysql/data目录是否有数据文件,如果出现下面类似的内容说明映射正确:
[zxd@localhost conf]$ sudo ls /opt/mysql/data
auto.cnf client-cert.pem ibdata1 ibtmp1 performance_schema server-cert.pem
ca-key.pem client-key.pem ib_logfile0 mysql private_key.pem server-key.pem
ca.pem ib_buffer_pool ib_logfile1 mysql.sock public_key.pem sys
为了方便操作,这里单独运行容器的命令单独抽出来。
mkdir -p /opt/mysql/data /opt/mysql/logs /opt/mysql/conf
docker run -p 13306:3306 --name mysql57 --restart=always -v /opt/mysql/conf:/etc/mysql/conf.d -v /opt/mysql/logs:/logs -v /opt/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
可以用下面的命令进行备份
docker exec 容器ID sh -c ' exec mysqldump --all-databases -uroot -p"root" ' > /mydocker/mysql/all-databases.sql
docker exec 58fa52f21404 sh -c ' exec mysqldump --all-databases -uroot -p"root" ' > /mydocker/mysql/all-databases.sql
不出意外是下面的报错:
bash: /mydocker/mysql/all-databases.sql: No such file or directory
新建一个备份SQL的存储位置:
[root@localhost xander]# mkdir -p /opt/mysql/backup
再重新执行一遍
docker exec 58fa52f21404 sh -c ' exec mysqldump --all-databases -uroot -p"root" ' > /opt/mysql/backup/all-databases.sql
再次执行之后检查相关文件夹发现成功导出。
[root@localhost xander]# ls -alF /opt/mysql/backup/all-databases.sql
-rw-r--r-- 1 root root 3450718 Apr 16 05:13 /opt/mysql/backup/all-databases.sql
停止容器
docker stop 容器id
强制停止容器
docker kill 容器ID
删除容器
docker rm [-f] 容器ID
删除所有容器(谨慎使用)
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm
个人的运行情况,容器内的配置文件在/etc目录。my.cnf文件内容如下(引入了conf.d 、mysql.conf.d路径下的文件):
bash-4.2# cat my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
最后一部分包含的配置可以将对应目录下的所有配置文件配置引入:
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
!includedir /etc/mysql/conf.d/
表示包含/etc/mysql/conf.d/这个路径下面的配置文件,前提是必须以为.cnf为后缀
!includedir /etc/mysql/mysql.conf.d/
表示包含/etc/mysql/mysql.conf.d/这个路径下面的配置文件,前提是必须以为.cnf为后缀
相对应容器内的/etc/mysql/conf.d/下有之前自定义的mysql.cnf配置文件,我们可以通过修改此宿主机的配置文件影响/etc/mysql/mysql.conf.d/mysql.cnf目录的内容,而my.cnf中又引入了此文件,也就达到了映射配置文件的目的:
bash-4.2# ls /etc/mysql/conf.d/
mysql.conf
下面就进入到关键的验证宿主配置影响容器运行的mysql配置环节。
我们首先会想到直接修改/etc/mysql/mysql.conf.d/XXX.cnf文件,但是docker的镜像是没有vim的,执行通常都会报错。
在容器当中执行下面的命令可以让其具备修改文件的能力。
yum install -y vim
或者
yum install -y vi
之后就可以使用vi或者vim的命令了。注意不同的Mysql的镜像版本配置文件的存储位置和内容可能存在差别,以上的配置仅为个人机器的实际部署情况。
另外还需要注意vim命令会在重新部署mysql的容器失效,这是docker本身设计导致,个人未找到快捷方案,只能说尽量避免容器内操作和修改文件,在部署容器的时候做好宿主机的配置映射。
由于下文的实验中需要用到主机远程访问虚拟机docker的mysql数据库,为了确保验证结果不会受到外部原因的干扰,需要在docker的mysql当中支持root用户远程连接mysql数据库。
生产中禁止root身份远程访问mysql数据库。
grant all privileges on *.* to 'root'@'%' identified by '修改为对应系统的密码' with grant option;
操作完成之后刷新:
flush privileges;
设置之后就可以远程访问,如果无法访问则检查Linux防火墙设置,或者直接把防火墙关了。
systemctl stop firewalld
上面方式重启Linux服务器之后会重新启动防火墙,永久关闭方式如下。
systemctl disable firewalld
最后我们用navicat连接测试,注意这里的端口号是13306。
为什么这里笔者不使用默认端口?源自过去玩了十多年Linux的大佬同事建议,10000以内的端口经常被各种开源中间件使用,确保防止端口不冲突给开源中间件的启动端口号前面加个1是个好习惯。
如果在容器内部进行配置修改/etc/my.cnf,那么重新部署mysql容器之后所有的改动都会还原,docker环境中要永久生效建议使用映射配置文件到宿主机器的方式。
那么要如何配置?这里回到开头介绍的docker启动脚本的映射配置/opt/mysql/conf:/etc/mysql/conf.d,我们可以在/opt/mysql/conf新建*.cnf文件的方式,在宿主机当中修改容器的mysql配置。
重新部署容器之后,安装过的vim等命令也会一同消失.....
vim /opt/mysql/conf/mysql.cnf
在容器当中对应的配置文件路径如下:
bash-4.2# ls /etc/mysql/conf.d/
mysql.cnf
修改mysql.cnf,我们在里面进行一些极端设置,比如整个服务器的最大连接数设置为0:
[mysqld]
# sort 缓冲
sort_buffer_size = 16M
# read缓冲
read_rnd_buffer_size = 2M
# 最大连接数,为了测试是否生效,这里暂时改为0,但是测试完成之后需要修改回来
max_connections = 0
需要注意的是,MySQL允许的最大连接数实际为:max_connections+1,因为这超出的一个用户其实是作为超级管理员来使用的。
也就是说如果我们设置为 0,max_connections 实际上为 1(下面的实验也可以验证),因为要预留给 root操作权限。
上面我们尝试修改服务器最大连接数为0,这个配置意味着只允许一个(基本是给root)客户端访问,我们可以通过show varibales like "max_connections";或者在两个客户端连接进行测试,验证宿主机的修改是否可以影响到docker内的Mysql。
[root@localhost xander]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38114e273e5a mysql:5.7 "docker-entrypoint.s…" 2 hours ago Up 27 minutes 33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp mysql57
[root@localhost xander]# docker restart 38114e273e5a
之后我们使用docker exec -it xxx /bin/bash,然后mysql -uroot -p的方式连接到服务端,使用show variables like 'max_connections';检查连接数是否被修改,如果是默认值151说明配置存在问题。
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1 |
+-----------------+-------+
1 row in set (0.06 sec)
[root@localhost conf]# docker rm 761f4d17ddf4
761f4d17ddf4
docker run -p 13306:3306 --name mysql57 --restart=always -v /opt/mysql/conf:/etc/mysql/conf.d -v /opt/mysql/logs:/logs -v /opt/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
[root@localhost xander]# docker run -p 13306:3306 --name mysql57 --restart=always -v /opt/mysql/conf:/etc/mysql/conf.d -v /opt/mysql/logs:/logs -v /opt/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
58fa52f21404dc8e070bade7cc8f38dbc4a585c1fb1157443f03652bb640c076
[root@localhost conf]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38114e273e5a mysql:5.7 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 33060/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp mysql57
进入到容器内:
docker exec -it 38114e273e5a /bin/bash
bash-4.2# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.41 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
查看系统参数发现配置依然是生效的:
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1 |
+-----------------+-------+
1 row in set (0.01 sec)
从这个实验也可以说明,max_connections 永远会预留一个连接入口(给root使用)。
个人查找到某一篇stackflow的文章看到如下对话,基本上属于文件命名的问题:
It turns out that on top of requiring a.cnfending for files in!include(and!includedir), you also can't have extra dots. The solution was to change the filename frommy.cnf.localtomy-local.cnf.
事实证明,除了要求 !include(和 !includir)中的文件以 .cnf 结尾之外,也不能有额外的点。最稳妥解决办法是将文件名从my.cnf.local改为my-local.cnf。
哪怕是做了文件映射,依然有可能碰到max_connections参数修改无效的情况,下面是一些解决思路:
引自:MySQL :: MySQL 8.0 Reference Manual :: 5.1.8 Server System Variables
max_connections | Command-Line Format | --max-connections=# |
---|---|---|
System Variable | max_connections | |
Scope | Global | |
Dynamic | Yes | |
SET_VARHint Applies | No | |
Type | Integer | |
Default Value | 151 | |
Minimum Value | 1 | |
Maximum Value | 100000 |
The maximum permitted number of simultaneous client connections. The maximum effective value is the lesser of the effective value ofopen_files_limit- 810, and the value actually set formax_connections.
注意:max_connections 实际生效值是open_files_limit和max_connections当中较小者。
For more information, seeSection5.1.12.1, “Connection Interfaces”.
个人在实验过程中连接docker的mysql出现如下的报错。
bash-4.2# mysql -uroot -p
mysql: [Warning] skipping '!includedir /etc/mysql/conf.d/' directive as maximum includerecursion level was reached in file /etc/mysql/conf.d/mysql.cnf at line 41!
mysql: [Warning] skipping '!includedir /etc/mysql/mysql.conf.d/' directive as maximum includerecursion level was reached in file /etc/mysql/conf.d/mysql.cnf at line 42!
经过谷歌搜索并没有找到这个报错的原因,但是想到之前的mysql.cnf配置是从容器的my.cnf原样拷贝的,怀疑是拷贝的配置文件格式某一处有错误,所以把其他所有的干扰项删除只保留了自定义的部分,再次尝试之后发现这个报错就再也没有出现过了。
如果照着本文操作,那么最后的配置肯定是max_connections=0,实验完成之后记得把这个参数配置修改回去。比如本地学习可以大胆点开放个10024,当然生产根据情况设置。
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 10024 |
+-----------------+-------+
1 row in set (0.07 sec)
以上内容可能在不同的用户机器会有不同的表现,一切请以个人的运行情况为准,如果遇到问题查阅Mysql的官方文档是非常必要的。