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

Posted

技术标签:

【中文标题】无法使用 Django 应用程序从容器连接到 MySQL docker 容器【英文标题】:Cannot connect to MySQL docker container from container with Django app 【发布时间】:2017-04-11 01:44:15 【问题描述】:

当我尝试从运行我的 Django 应用程序的 docker 容器连接到运行 mysql 的容器时,我收到以下错误:

django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on '172.17.0.2' (111)")

这是我运行 MySQL 容器的方式:

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=testdb -e MYSQL_ROOT_HOST=172.17.0.2 -d mysql/mysql-server:5.7

如果我没有指定MYSQL_ROOT_HOST,当我尝试从容器与 Django 应用程序连接时会收到此错误:

django.db.utils.OperationalError: (1130, "Host '172.17.0.3' is not allowed to connect to this MySQL server")

这是我的 Django 设置:

DATABASES = 
    'default': 
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testdb',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '172.17.0.2',
        'PORT': '',
    

我已验证 MySQL 容器正在使用 IP 172.17.0.2:

$ docker inspect mysql |grep -i ipaddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

【问题讨论】:

你的数据库docker容器的名字是mysql吗? 是的,名字是mysql。 MySql 通常需要几秒钟才能启动,您是想立即连接还是稍等一下?另外,fwiw,看起来您在启动容器时不需要指定MYSQL_ROOT_HOST 尝试将您的容器名称“mysql”作为 django db 设置中的主机值。这就是我拥有它的方式。 我在启动 MySQL 容器后等了一分钟,得到了相同的结果。无论我指定MYSQL_ROOT_HOST,我都会得到不同的结果,我会更新我的帖子。 【参考方案1】:

我必须在 Django 容器中授予 root 用户访问数据库的权限:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'172.17.0.3' IDENTIFIED BY 'password' WITH GRANT OPTION;
SET PASSWORD FOR root@'172.17.0.3' = PASSWORD('root');
FLUSH PRIVILEGES;

其中172.17.0.3 是应用程序所在容器的 IP。不需要MYSQL_ROOT_HOST

【讨论】:

虽然是肮脏的解决方案,但 Web 容器的 IP 并不总是相同。【参考方案2】:

docker run --rm -d -p 9999:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_ROOT_HOST='%' mysql/mysql-server:5.7

重要的部分是MYSQL_ROOT_HOST='%'

【讨论】:

【参考方案3】:

此行为已在此处完整记录:(https://github.com/mysql/mysql-docker#mysql_root_host) 并按预期工作。 我会引用它:

默认情况下,MySQL 创建 'root'@'localhost' 命令。此帐户 只能从容器内部连接,需要使用 的 docker exec 命令,如 Connect to MySQL 下所述 MySQL 命令行客户端。要允许来自其他主机的连接,请设置 这个环境变量。例如,值“172.17.0.1”, 这是默认的 Docker 网关 IP,将允许来自 Docker 主机。

您可以看到实际的 .sh 脚本,该脚本从该环境变量中设置了允许的主机:https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/docker-entrypoint.sh#L63-L68

【讨论】:

所以我正在做的事情是不可能的?连接到 MySQL 容器(至少使用官方镜像)的唯一方法是从容器本身? 是的。但为什么这对你来说是个问题? 让数据库在一个容器中运行而应用程序在另一个容器中运行不是一个有效的用例吗? 是的,绝对有效。而且我通常将 dbhost 放在某种环境变量中,这在生产设置和开发设置中是不同的(我为此有单独的文件)。 DATABASES dict 仅引用那些环境。变量,因此您不必更改代码中的任何内容。可能只需要编写简单的 .sh 脚本,它每次都会使用相同的 ip 运行您的容器 官方文档应该提到容器之间的示例用法和连接设置。他们只说link 命令,而没有提及权限:hub.docker.com/r/mysql/mysql-server 遵循文档但仍然得到:ERROR 1130 (HY000): Host '172.26.0.1' is not allowed to connect to this MySQL server【参考方案4】:

正如@valignatev 所建议的,使用这个环境变量可以解决一个问题。

我确实是这样创建容器的:

 docker run --rm -dit -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_ROOT_HOST=172.17.0.1 --name mysql_container -p 3306:3306 mysql-mysql-server

172.17.0.1 是我的默认 docker 网关

一旦容器启动,我可以像这样从我的主机连接:

 mysql -h localhost -P 3306 --protocol=tcp -u root -p

【讨论】:

您似乎正在尝试从主机连接到 MySQL 容器。我的问题是我无法从 Django 容器连接到 MySQL 容器。 这并不能完全解决 OP 的问题,但 100% 解决了我的问题。我无法从主机连接到 MySQL 容器。仅供参考,这也应该有效:MYSQL_ROOT_HOST=172.*.*.*

以上是关于无法使用 Django 应用程序从容器连接到 MySQL docker 容器的主要内容,如果未能解决你的问题,请参考以下文章

无法从 golang 连接到 docker postgres 容器

Django docker 容器无法连接到 mysql 容器,出现错误“无法连接到 'db' (111) 上的 MySQL 服务器”)

Python Flask SQLAlchemy 容器无法连接到 MySQL 容器

无法从 Docker 容器连接到外部 SQL Server

无法从 docker 容器连接到数据库 [重复]

无法使用桥接网络模式从 docker 容器连接到远程 SQL 服务器