3

I'm developing Laravel and legacy PHP applications side-by-side in a Windows 10 environment running Docker. For the legacy PHP app, I'd like to move development to inside a Docker container, however, I cannot seem to get the PHP app to connect to a MySQL database that is on a different Ubuntu server on the Local Network. I use Laradock to simplify the docker container images and setup for this type of development environment.

Here's my setup:

  • Windows 10 Host (IP: 172.19.0.200) -- MySQL server is NOT installed locally
  • Ubuntu MySQL Server (IP: 172.19.0.16)
  • TeamSQL (MySQL client)

Results from ipconfig in cmd console on Windows:

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

Results from ufw status on Ubuntu server (to display firewall rules):

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

Results from select host, user from mysql.user query in Ubuntu MySQL:

+----------------+------------------+
| 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             |
+----------------+------------------+

I can connect to the Ubuntu MySQL instance from the Windows 10 system using TeamSQL using these connection parameters:

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

So, I know that at least connection from the Windows IP is allowed and that the credentials work.

However, I cannot connect from my legacy PHP app in the Docker container using this connection string:

$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);

When I use this information, I receive a SQLSTATE[HY000] [2002] Connection timed out error. So in my digging, I found this article about using PuTTY to forward the ports of my Ubuntu MySQL server to my Windows 10 host via a SSH tunnel. My thought was that if I could forward the Ubuntu MySQL port to my Windows 10 port and then connect to my Windows 10 port from Docker (since Windows 10 is the host) then maybe I could get the connection working. I walked through that tutorial and opened TeamSQL and switched the information as the article suggested to use:

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

I'm receiving a "Connection lost: The server closed the connection" error. I figured this had to be a firewall issue, so I turned off Windows Firewall but still no luck with TeamSQL, but I decided to try from within the PHP app.

I changed the PHP app details to this:

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

And now I receive a SQLSTATE[HY000] [2002] Connection refused error when I try to connect.

I've been working on this issue for an almost embarrassing amount of time. At this point, I really don't care if it's a facepalm-type answer; I'm just trying to get it to work. The connection between my PHP app and Ubuntu MySQL server worked when I just used XAMPP on Windows, but I'm trying to narrow the gap between my local dev environment and production dev environment by using Docker. That's the idea behind making the switch.

Any thoughts on how to resolve this issue? Thanks in advance.

EDIT

Bind address has been set to 0.0.0.0 as shown with this query show global variables like 'bind_address';:

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

Results from ifconfig from within nginx container:

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)

EDIT 2

Using the suggestion from @Canis, I executed these commands:

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

I still can't access the Ubuntu MySQL container. Here are the current results for 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)

It looks like eth1 and eth2 are still using IP addresses that may conflict. I haven't the foggiest idea as to how to proceed from here though. Thoughts?

Michael
  • 2,016
  • 5
  • 35
  • 51
  • Regarding the localhost ip you are using in the docker container: This will point to the loopback address on the virtual Linux guest your docker image is running under, not the Windows host. Are you able to spin up an image with curl or wget? If so, try to access the internet and see what happens. Ex: wget http://google.com. If that is able to connect, then at least outgoing traffic from the container is allowed. – Canis Feb 07 '18 at 21:09
  • @Canis I can curl to google.com and I receive the html in response, so that's good to know. Hadn't thought of trying an external site, just an internal IP. – Michael Feb 07 '18 at 21:12
  • Great! Basic routing works as expected then. How about a ping from the container to the Ubuntu MySQL server. Does that come through? If not, are these machines separated by any other firewall or filtering mechanism other than the client firewall on the Ubuntu? Could be VMware guest isolation or something similar for other technologies. – Canis Feb 07 '18 at 21:18
  • is your MYSQL server configured to allow traffic from other networks than localhost? check this https://stackoverflow.com/a/15684341/2894123 – Mazel Tov Feb 07 '18 at 21:20
  • If you also could post a dump of the `ifconfig` inside the container that would be great. – Canis Feb 07 '18 at 21:21
  • @Canis When I try to curl to 172.19.0.16 this is what I receive: `curl: (7) Failed to connect to 172.19.0.16 port 80: No route to host`. Windows Firewall is still disabled locally, there's another business level firewall that I tried disabling, but to no avail. But no other firewalls beside the Ubuntu server firewall. – Michael Feb 07 '18 at 21:22
  • @Canis I've added the `ifconfig` results from the nginx container. – Michael Feb 07 '18 at 21:28
  • @MazelTov I forgot to add that detail, but yes, I had already configured the MySQL server to allow traffic from other networks. I've edited the post to show this. – Michael Feb 07 '18 at 21:29

2 Answers2

0

Your internal ip-network inside the docker container is overlapping with your external ip-networks, or is set to host. If not set to hostthen that makes the routing inside the Linux host try to find that resource locally, rather than send the request out on the internet.

Try to change the network for your container like so:

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

Remember to substitute the your-nginx-container for the actual name of your running container. If you are creating the container with docker create you can specify the network bridge to use by adding --network=br0, where br0 is the name we used in the docker network create command above.

Edit

After seeing your latest ifconfig I suggest you try to remove the other networks. Can you see if this command has any effect? It should remove the host network driver from the container, hopefully removing both of the interfaces.

docker network disconnect host laradock_nginx_1
Community
  • 1
  • 1
Canis
  • 4,130
  • 1
  • 23
  • 27
  • Thanks for your help! So I executed those commands substituting my Nginx's container name 'laradock_nginx_1' as you suggested, however, I still can't get through. I restarted the container and still nothing. I've edited the OP with the current results from `ifconfig` in the nginx container. – Michael Feb 07 '18 at 22:22
  • @Michael I've updated my answer with a new suggestion to try to get rid of the other interfaces. After that, I guess we'll either start digging into routing and route tables, or starting from scratch, analyzing how you use laradocks, starting with a clean slate, looking into the composer.yml etc. – Canis Feb 07 '18 at 22:30
  • Hmm... This is what I get: Error response from daemon: container 72aae8e12e5eebc7677e7318d22ebdab033f47bebdd77575fbf650cc1ddd1ac9 is not connected to network host... I have to leave work for now, but I'll be back later this evening. Thank you again for your help! – Michael Feb 07 '18 at 22:35
  • @Michael You are very welcome. Not sure if I'm around at that time to answer promptly, but I suggest that you follow the Digital Ocean guide [here](http://laradock.io/guides/) and just look past the Digital Ocean specific virtual machine steps, and do the Windows equivalent instead, or set up a throwaway Linux VM on your machine to more closely reproduce the steps. When that works, do a `ifconfig` inside the container and see if you get the 10.0.75.X as expected. Then try to ping the MySQL server again. – Canis Feb 07 '18 at 22:43
0

I solved this setting DOCKER_HOST_IP in laradock .env file with my host ip or network (both worked for me).

DOCKER_HOST_IP=172.16.4.1

Hope can help someone.