尝试从主机连接到 mysql docker 容器时出现“读取初始通信数据包”错误
Posted
技术标签:
【中文标题】尝试从主机连接到 mysql docker 容器时出现“读取初始通信数据包”错误【英文标题】:"Reading initial communication packet" error while trying to connect to a mysql docker container from the host 【发布时间】:2020-06-03 10:55:09 【问题描述】:我希望能够连接到我的 docker 容器,就好像 mysql 服务器安装在我的本地计算机上一样。我测试我的连接:
mysql -u root -proot -h 127.0.0.1 -P 3306 --protocol=tcp
如果我使用 docker 创建一个容器,我可以成功地做到这一点。像这样:
docker run --name some-mysql-standalone -p 127.0.0.1:3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7.29
如果我在 docker-compose 中使用容器作为服务,我会收到错误:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 2
MySQL 服务器正在容器内运行,我可以访问它。
我的 docker compose sn-p:
version: '2'
services:
mysql:
image: mysql:5.7.29
container_name: some_mysql
restart: unless-stopped
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/init:/docker-entrypoint-initdb.d
ports:
- 3306:3306
environment:
MYSQL_DATABASE: some_mysql
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
有趣的是,我已经使用这个docker-compose.yml
一段时间了,没有任何问题。我不确定我的环境发生了什么变化导致它停止工作。
如何让 docker-compose 中的 mysql 容器可以从主机访问?
【问题讨论】:
【参考方案1】:这帮助我解决了我的问题: 使用命令创建容器
docker run --detach --rm --name mysql-server -p 8888:3306 --env MYSQL_ROOT_PASSWORD=admin mysql:latest
并登录mysql
mysql -uroot -padmin -h127.0.0.1 -P8888 --protocol=tcp
【讨论】:
我忘了加上先用3306端口,然后换成8888,这个肯定有帮助,我自己查了【参考方案2】:在this thread 上发现了类似的错误。查看您的防火墙配置是否已更改并尝试将您的 SQL 服务器绑定到 0.0.0.0
而不是 localhost
或 127.0.0.1
。
【讨论】:
感谢您的建议,但我已经尝试了 IP、绑定地址和其他 my.cnf 设置的任何可能组合。完全删除所有容器和图像,验证 mysql 是否已在容器内实际启动,更新授权,创建新的 mysql 用户,甚至检查我的磁盘使用情况 :) 一切都安装在我的本地机器上。码头工人一如既往地输出0.0.0.0:3306->3306/tcp,
,这意味着它将端口正确地绑定到我的主机,并且实际使用了这个端口。我也尝试重新启动 docker 服务,但没有尝试重新安装它;)【参考方案3】:
正如response中的7_R3X所说,似乎是保护mysql服务器更安全。
在我的例子中,我在 mysql:5.7 之上构建的 docker 映像中运行该服务,并且 mysql 服务器是通过调用 /etc/init.d/ 启动的mysql start 而不是使用 mysql 官方镜像的入口点。因此它可能不适用于问题上下文,但它适用于 mysql 服务中的指定错误。
解决问题的步骤是:
将/etc/mysql/mysql.conf.d/mysqld.cnf中的localhost/loop地址替换为allsed -i "s/bind-address.*/bind-address = 0.0.0.0/g" /etc/mysql/mysql.conf.d/mysqld.cnf
重启mysql服务:/etc/init.d/mysql restart
然后我就可以从外部(通过主机检查)访问 docker 暴露端口
【讨论】:
【参考方案4】:首先,尝试在创建容器时设置-e MYSQL_ROOT_HOST=%
。
如果不起作用:某些 docker 镜像会忽略环境变量指令(如 -e MYSQL_ROOT_PASSWORD=<MY_PASSWORD> -e MYSQL_ROOT_HOST=%
),因此您必须手动在其他主机(%
)上添加(root)用户:
docker exec -it <YOUR_CONTAINER_NAME> bash
mysql -u root -p<MY_PASSWORD>
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '<MY_PASSWORD>';
FLUSH PRIVILEGES;
【讨论】:
【参考方案5】:有时我在停止并恢复虚拟机后会遇到此错误。解决问题的方法是重启虚拟机。
【讨论】:
【参考方案6】:从实用的角度来看,我通过显式创建网络使其工作。这是一个例子:
version: '2'
services:
mysql:
image: mysql:5.7.29
container_name: some_mysql
restart: unless-stopped
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/init:/docker-entrypoint-initdb.d
ports:
- 3306:3306
environment:
MYSQL_DATABASE: some_mysql
MYSQL_USER: root
MYSQL_PASSWORD: root
MYSQL_ROOT_PASSWORD: root
networks:
- default
...
networks:
default:
external:
name: somename_default
我认为由于无法连接,我应该尝试删除并创建一个新网络,因为 docker-compose 在后台为容器创建了一个单独的网络。我仍然不知道我遇到这个问题的原因。
【讨论】:
以上是关于尝试从主机连接到 mysql docker 容器时出现“读取初始通信数据包”错误的主要内容,如果未能解决你的问题,请参考以下文章
无法从我的 Docker 容器内部连接到主机的 localhost
无法使用 Django 应用程序从容器连接到 MySQL docker 容器