【问题标题】:Connecting a Docker container to a remote MySQL Database将 Docker 容器连接到远程 MySQL 数据库
【发布时间】:2018-02-07 20:51:59
【问题描述】:

我正在运行 Docker 的 Windows 10 环境中并行开发 Laravel 和旧版 PHP 应用程序。对于旧的 PHP 应用程序,我想将开发转移到 Docker 容器内,但是,我似乎无法让 PHP 应用程序连接到本地网络上不同 Ubuntu 服务器上的 MySQL 数据库。我使用 Laradock 来简化 docker 容器映像和此类开发环境的设置。

这是我的设置:

  • Windows 10 主机 (IP: 172.19.0.200) -- MySQL 服务器未安装在本地
  • Ubuntu MySQL 服务器(IP:172.19.0.16)
  • TeamSQL(MySQL 客户端)

Windows 上 cmd 控制台中 ipconfig 的结果:

Ethernet adapter vEthernet (Default Switch):

Connection-specific DNS Suffix  . :
Link-local IPv6 Address . . . . . : fe80::7ce7:47d:7b91:84a8%9
IPv4 Address. . . . . . . . . . . : 172.31.215.177
Subnet Mask . . . . . . . . . . . : 255.255.255.240
Default Gateway . . . . . . . . . :

Ethernet adapter vEthernet (DockerNAT):

Connection-specific DNS Suffix  . :
Link-local IPv6 Address . . . . . : fe80::8cc5:621:daba:48e3%4
IPv4 Address. . . . . . . . . . . : 10.0.75.1
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :

Ethernet adapter Local Area Connection:

Connection-specific DNS Suffix  . :
Link-local IPv6 Address . . . . . : fe80::71fc:9102:366c:fb7d%15
IPv4 Address. . . . . . . . . . . : 172.19.0.200
Subnet Mask . . . . . . . . . . . : 255.255.0.0
Default Gateway . . . . . . . . . : 172.19.0.254

来自 Ubuntu 服务器上 ufw status 的结果(显示防火墙规则):

To                         Action      From
--                         ------      ----
22                         ALLOW       172.19.0.0/24
3306                       ALLOW       172.19.0.0/24
80                         ALLOW       172.19.0.0/24
80                         ALLOW       10.0.75.0/24
3306                       ALLOW       10.0.75.0/24
80                         ALLOW       172.20.0.0/24
3306                       ALLOW       172.20.0.0/24

Ubuntu MySQL 中select host, user from mysql.user 查询的结果:

+----------------+------------------+
| host           | user             |
+----------------+------------------+
| %              | root             |
| 10.0.2.2       | root             |
| 10.0.75.1      | root             |
| 127.0.0.1      | root             |
| 172.19.0.%     | root             |
| 172.19.0.15    | root             |
| 172.19.0.16    | root             |
| 172.19.0.200   | root             |
| 172.19.0.65    | root             |
| 172.20.0.1     | root             |
| 172.20.0.6     | root             |
| 172.31.215.177 | root             |
| localhost      | root             |
+----------------+------------------+

我可以使用 TeamSQL 使用以下连接参数从 Windows 10 系统连接到 Ubuntu MySQL 实例:

Host: 172.19.0.16
Post: 3306
User: root
Password: thisisasamplepassword

所以,我知道至少允许来自 Windows IP 的连接并且凭据有效。

但是,我无法使用此连接字符串从 Docker 容器中的旧 PHP 应用程序进行连接:

$dbHost = "172.19.0.16"
$dbPort = "3306"
$dbName = "databasename"
$dbUser = "root"
$dbPassword = "thisisasamplepassword"

$connectionString = "mysql:host=$dbHost;port=$dbPort;dbname=$dbName;
$instance = new PDO($connectionString, $dbUser, $dbPassword);

当我使用此信息时,我收到SQLSTATE[HY000] [2002] Connection timed out 错误。所以在我的挖掘中,我发现this article 关于使用 PuTTY 通过 SSH 隧道将我的 Ubuntu MySQL 服务器的端口转发到我的 Windows 10 主机。我的想法是,如果我可以将 Ubuntu MySQL 端口转发到我的 Windows 10 端口,然后从 Docker 连接到我的 Windows 10 端口(因为 Windows 10 是主机),那么也许我可以让连接正常工作。我浏览了该教程并打开了 TeamSQL 并按照文章建议使用的方式切换了信息:

Host: 127.0.0.1
Post: 3306
User: root
Password: thisisasamplepassword

我收到“连接丢失:服务器关闭连接”错误。我认为这一定是防火墙问题,所以我关闭了 Windows 防火墙,但仍然无法使用 TeamSQL,但我决定从 PHP 应用程序中尝试。

我将 PHP 应用详细信息更改为:

$dbHost = "127.0.0.1"
$dbPort = "3306"
$dbName = "databasename"
$dbUser = "root"
$dbPassword = "thisisasamplepassword"

现在我在尝试连接时收到SQLSTATE[HY000] [2002] Connection refused 错误。

我一直在研究这个问题几乎令人尴尬的时间。在这一点上,我真的不在乎这是否是一个掌上型答案;我只是想让它工作。当我在 Windows 上使用 XAMPP 时,我的 PHP 应用程序和 Ubuntu MySQL 服务器之间的连接工作正常,但我试图通过使用 Docker 缩小本地开发环境和生产开发环境之间的差距。这就是进行转换的想法。

关于如何解决此问题的任何想法?提前致谢。

编辑

绑定地址已设置为 0.0.0.0,如查询 show global variables like 'bind_address'; 所示:

+---------------+---------+
| Variable_name | Value   |
+---------------+---------+
| bind_address  | 0.0.0.0 |
+---------------+---------+
1 row in set (0.00 sec)

来自 nginx 容器内 ifconfig 的结果:

eth0  Link encap:Ethernet  HWaddr 02:42:AC:14:00:04
      inet addr:172.20.0.4  Bcast:172.20.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:612 errors:0 dropped:0 overruns:0 frame:0
      TX packets:484 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:136633 (133.4 KiB)  TX bytes:98603 (96.2 KiB)

eth1  Link encap:Ethernet  HWaddr 02:42:AC:13:00:03
      inet addr:172.19.0.3  Bcast:172.19.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:156 errors:0 dropped:0 overruns:0 frame:0
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:9832 (9.6 KiB)  TX bytes:0 (0.0 B)

lo    Link encap:Local Loopback
      inet addr:127.0.0.1  Mask:255.0.0.0
      UP LOOPBACK RUNNING  MTU:65536  Metric:1
      RX packets:4 errors:0 dropped:0 overruns:0 frame:0
      TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1
      RX bytes:235 (235.0 B)  TX bytes:235 (235.0 B)

编辑 2

根据@Canis 的建议,我执行了以下命令:

docker network create --driver=bridge --subnet=192.168.0.0/16 br0
docker network connect br0 laradock_nginx_1

我仍然无法访问 Ubuntu MySQL 容器。以下是ifconfig 的当前结果:

eth0  Link encap:Ethernet  HWaddr 02:42:C0:A8:00:02
      inet addr:192.168.0.2  Bcast:192.168.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:25 errors:0 dropped:0 overruns:0 frame:0
      TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:2154 (2.1 KiB)  TX bytes:1209 (1.1 KiB)

eth1  Link encap:Ethernet  HWaddr 02:42:AC:13:00:03
      inet addr:172.19.0.3  Bcast:172.19.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:12 errors:0 dropped:0 overruns:0 frame:0
      TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:928 (928.0 B)  TX bytes:252 (252.0 B)

eth2  Link encap:Ethernet  HWaddr 02:42:AC:14:00:04
      inet addr:172.20.0.4  Bcast:172.20.255.255  Mask:255.255.0.0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:21 errors:0 dropped:0 overruns:0 frame:0
      TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:3330 (3.2 KiB)  TX bytes:1394 (1.3 KiB)

lo    Link encap:Local Loopback
      inet addr:127.0.0.1  Mask:255.0.0.0
      UP LOOPBACK RUNNING  MTU:65536  Metric:1
      RX packets:12 errors:0 dropped:0 overruns:0 frame:0
      TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1
      RX bytes:1131 (1.1 KiB)  TX bytes:1131 (1.1 KiB)

看起来 eth1 和 eth2 仍在使用可能冲突的 IP 地址。不过,我对如何从这里开始并没有最模糊的想法。想法?

【问题讨论】:

  • 关于您在 docker 容器中使用的 localhost ip:这将指向运行 docker 映像的虚拟 Linux 客户机上的环回地址,而不是 Windows 主机。你能用 curl 或 wget 旋转图像吗?如果是这样,请尝试访问互联网,看看会发生什么。例如:wget google.com。如果能够连接,则至少允许来自容器的传出流量。
  • @Canis 我可以卷曲到 google.com 并收到 html 作为响应,所以很高兴知道。没想过尝试外部站点,只是一个内部 IP。
  • 太棒了!然后基本路由按预期工作。从容器到 Ubuntu MySQL 服务器的 ping 怎么样。这能通过吗?如果不是,这些机器是否被 Ubuntu 上的客户端防火墙以外的任何其他防火墙或过滤机制隔开?可能是 VMware 来宾隔离或其他技术的类似内容。
  • 您的 MYSQL 服务器是否配置为允许来自 localhost 以外的其他网络的流量?检查这个stackoverflow.com/a/15684341/2894123
  • 如果您也可以在容器内发布ifconfig 的转储,那就太好了。

标签: php mysql windows ubuntu docker


【解决方案1】:

您在 docker 容器中的内部 ip-network 与您的外部 ip-networks 重叠,或者设置为 host。如果未设置为host,那么这会使Linux 主机内部的路由尝试在本地查找该资源,而不是在互联网上发送请求。

尝试像这样更改容器的网络:

docker network create --driver=bridge --subnet=192.168.0.0/16 br0
docker network connect br0 your-nginx-container

请记住将your-nginx-container 替换为正在运行的容器的实际名称。如果您使用docker create 创建容器,您可以通过添加--network=br0 来指定要使用的网桥,其中br0 是我们在上面的docker network create 命令中使用的名称。

编辑

在看到您最新的ifconfig 后,我建议您尝试删除其他网络。看看这个命令有没有效果?它应该从容器中删除host 网络驱动程序,希望删除这两个接口。

docker network disconnect host laradock_nginx_1

【讨论】:

  • 感谢您的帮助!所以我按照你的建议执行了那些替换我的 Nginx 容器名称“laradock_nginx_1”的命令,但是,我仍然无法通过。我重新启动了容器,但仍然没有。我已经使用 nginx 容器中 ifconfig 的当前结果编辑了 OP。
  • @Michael 我用一个新的建议更新了我的答案,试图摆脱其他接口。在那之后,我想我们要么开始深入研究路由和路由表,要么从头开始,分析你如何使用 laradocks,从头开始,研究 composer.yml 等。
  • 嗯...这是我得到的:来自守护进程的错误响应:容器 72aae8e12e5eebc7677e7318d22ebdab033f47bebdd77575fbf650cc1ddd1ac9 未连接到网络主机...我现在必须下班,但我稍后会回来晚上。再次感谢您的帮助!
  • @Michael 不客气。不确定我当时是否能及时回答,但我建议您遵循 Digital Ocean 指南 here 并查看 Digital Ocean 特定的虚拟机步骤,然后执行 Windows 等效操作,或者设置一个机器上的一次性 Linux VM 以更准确地重现这些步骤。如果可行,请在容器内执行 ifconfig 并查看是否按预期获得了 10.0.75.X。然后尝试再次 ping MySQL 服务器。
【解决方案2】:

我用我的主机 IP 或网络解决了 laradock .env 文件中的 DOCKER_HOST_IP 设置(两者都对我有用)。

DOCKER_HOST_IP=172.16.4.1

希望可以帮助别人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 2019-09-13
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    相关资源
    最近更新 更多