尝试从主机连接到 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 而不是 localhost127.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地址替换为all sed -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

如何通过 SSH 连接到 MySQL Docker 容器?

无法使用 Django 应用程序从容器连接到 MySQL docker 容器

Mariadb docker容器无法使用Python连接到主机上的MySQL服务器(111连接被拒绝)

如何从 docker 容器连接到远程 mysql 托管?

元数据库未连接到 MySQL(docker 容器)