本文主要内容是在通过Docker部署mysql环境后,Docker登录mysql时遇到的一系列问题汇总。
常见问题
问题一:数据库连接报错
node服务(此处为nest框架)连接远程docker中mysql时,报如下错误:
client does not support authentication protocol requested by server;consider upgrading Mysql client
刚开始一下摸不着头脑,不知道报的错误是啥意思,也是刚接触mysql,不太懂mysql的一些东西,然后就开始找度娘,参考了很多文章的解决方案,最终通过如下方案解决:
解决方案:
1. docker exec -it mysql容器 bash # 进入mysql容器
2. mysql -u root -p 登录mysql,输入密码
3. mysql> use mysql;
4. select user,host from user;
5. 注意我的root,host是'%',然后执行
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123'; # 设置复杂度高的密码
或
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123';
信息如下:
会发现有两个root用户,可以把其中一个删除,具体如下操作:
命令:DROP USER 'username'@'host';
DROP USER 'root'@'localhost';
用户被删除后user表中就不存在该用户的数据。但是有一点需要注意的是,user表中是通过用户名和主机名来唯一确定一个用户,如果运行CREATE USER 'testuser'@'10.1.1.1' IDENTIFIED BY 'password';和CREATE USER 'testuser'@'10.1.1.2' IDENTIFIED BY 'password';这两条语句,会在user表中插入两条信息。因此,删除用户的时候也只能分两次删除
问题二:mysql设置允许用户远程登录
执行如下操作:
mysql> use mysql;
select user,host from user;
查看结果是否是root用户仅容许本地(localhost)登录,即如下截图:
是的话,需要修改的他的host为'%',表示任意IP均可以进行登录,即root对应的host改为'%',表示任意IP就可以进行登录了,即执行如下命令就可:
mysql> update user set host='%' where user='root';
mysql> flush privileges; # 记得一定要刷新权限,否则不会生效
上述的问题通过Navicat连接远程数据库时,刚开始以为是两个不同的问题,其实是一个问题,具体会报如下错误信息
2003 - Can't connect to MySQL xxx (61 "Connection refused")
或者
telnet: Unable to connect to remote host: Connection refused
这个问题查询了很多资料,网上多数方法都无法从根本上解决问题,该问题的根本原因mysql用户访问权限,在此总结下该问题的解决方案:
检查mysql用户访问权限
1. docker exec -it mysql容器 bash # 进入mysql容器
2. mysql -u root -p 登录mysql,输入密码
3. mysql> use mysql;
4. select user,host from user;
5. update user set host='%' where user='root'; # 更新域属性,'%'表示允许外部访问,即修改已有用户的host字段
6. select host,user from user;
7. flush privileges; // 刷新权限(必须刷新,否则不生效)
8. exit;
9. 一定要记得重启动mysql docker容器(必须重启,否则不生效)
10. navicat重新连接
重新连接数据库, 测试成功,成功连接
问题三:Docker进入MySQL Access denied for user 'root'@'localhost' (using password: YES)
可能密码正确,但是拒绝访问;也有可能是密码错误,但是拒绝访问。还请往下看,直接跳过密码验证访问 MySQL.
可能密码正确,但是拒绝访问;也有可能是密码错误,但是拒绝访问。继续往下看,经过排查发现密码是正确的,接下来操作直接跳过密码验证访问MySQL.
默认情况下是需要密码登录,而MySQL 8版本以上开始时候没有设置密码,所以需要修改如下配置文件:
解决方案:
1. 在进入MySQL 容器的前提下使用命令:`cd /etc/mysql/conf.d/` 进入conf.d这个文件夹下
2. 使用命令:`ls`查看 conf.d这个文件夹下是否存在docker.cnf这个文件
3. 如果存在,进行如下操作:
- 使用命令:`vim docker.cnf` 进入vim编辑器,对docker.cnf进行编辑,前提你已经在Docker里安装了vim,如何安装vim下面会说
- 文件中已经存在:`[mysqld]和skip-host-cache和skip-name-resolve`三行代码
- 在此基础上新增:`skip-grant-tables`这行代码,保存并退出vim编辑模式
- 最后使用命令重启Docker里MySQL容器:`docker restart mysql容器ID`
- 重新进入MySQL 容器:`docker exec -it mysql容器ID bash`
- 重新访问MySQL: `mysql -u root -p` 就可以访问到Docker里的MySQL了
4. 如果不存在 docker.cnf文件,进行如下操作
- 进入mysql容器,cd /etc/mysql/使用命令:`touch docker.cnf`创建 docker.cnf文件
- 使用命令:`vim docker.cnf`对该文件进行编辑
- 在文件中第一行添加:`[mysqld]`, 第二行添加:`skip-host-cache`,第三行添加:`skip-name-resolve`,第四行添加:`skip-grant-tables`,保存并退出vim编辑模式
- 最后使用命令重启Docker里MySQL容器:`docker restart mysql容器ID`
- 重新进入MySQL 容器:`docker exec -it mysql容器ID bash`
- 重新访问MySQL: `mysql -u root -p` 就可以访问到Docker里的MySQL了
注意:
- 跳过密码登录进去时如果还提示上述错误信息,通过指令flush privileges刷新一下权限
- 记得改完/etc/mysql/conf.d/之后,mysql可以成功进入后,需要退出,重启mysql容器,然后再进入,去掉
skip-grant-tables这行代码,然后退出,重启mysql容器,再进入就可以正常通过设置的密码登录了。 mysql> grant all privileges on *.* to 'root'@'%' with grant option;# 设置其他主机可访问root用户
docker容器中安装vim
在使用docker容器时,有时候里边没有安装vim,敲vim命令时提示说:vim: command not found,这个时候就需要安装vim,可是当在容器中输入apt-get install vim命令时,提示:
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package vim
这时候需要输入:apt-get update,这个命令的作用是:同步 /etc/apt/sources.list和 /etc/apt/sources.list.d中列出的源的索引,这样才能获取到最新的软件包。
等更新完毕以后再敲命令:apt-get install vim命令即可
总结:
问题1、问题2、问题3其实可以归类为一种原因,即可以理解为mysql用户权限相关的问题,只是报错形式不一样。
Mysql用户管理
添加用户
以root用户登录数据库,运行以下命令
命令:`CREATE USER 'username'@'host' IDENTIFIED BY 'password'`
CREATE USER 'testuser'@'%' IDENTIFIED BY '123';
上面的命令创建了用户testuser,密码是123。在mysql.user表里可以查看到新增用户的信息。
授权
命令格式:GRANT privileges ON databasename.tablename TO 'username'@'host'
比如:
# 对用户testuser授予在所有主机上对test库的SELECT权限
GRANT SELECT ON test.* TO 'testuser'@'%';
# 对所有库都授予INSERT权限后,user表中的该用户Insert_priv的值被置为Y
GRANT INSERT ON *.* TO 'testuser'@'%';
# 给该用户赋予所有权限
GRANT ALL privileges ON *.* TO 'testuser'@'%';
# 执行完授予权限的命令后,必须执行以下命令使修改生效
flush privileges;
说明
-
privileges:用户的操作权限,如SELECT , INSERT , UPDATE,如果要授予所有权限用all privileges
-
databasename:数据库名,指定要授予权限的库,如果要对所有库授予权限用
*代替 -
tablename:表名,指定要授予权限的表,如果要对所有表授予权限用
*代替 -
username:被授予权限的用户名
-
host:被授予权限的主机,如果要对所有主机授予权限用%代替
撤销用户权限
命令:`REVOKE privileges ON databasename.tablename FROM 'username'@'host';`
例子:`REVOKE ALL privileges ON *.* FROM 'testuser'@'%';`
修改密码
命令: `SET PASSWORD FOR 'username'@'host' = PASSWORD('newpassword');`
例子: `SET PASSWORD FOR 'testuser'@'%' = PASSWORD('abcdef');`
flush privileges;
删除用户
命令:DROP USER 'username'@'host';
DROP USER 'root'@'localhost';
总结
一般情况下我们在使用过程中,运行apt-get update,然后执行apt-get install -y vim
参考文档: