title: Connecting a Docker container to a remote MySQL Database
body: <p>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. </p>
  
  <p>Here's my setup:</p>
  
  <ul>
  <li>Windows 10 Host (IP: 172.19.0.200) -- MySQL server is NOT installed locally</li>
  <li>Ubuntu MySQL Server (IP: 172.19.0.16)</li>
  <li>TeamSQL (MySQL client)</li>
  </ul>
  
  <p>Results from <code>ipconfig</code> in cmd console on Windows:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Results from <code>ufw status</code> on Ubuntu server (to display firewall rules):</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Results from <code>select host, user from mysql.user</code> query in Ubuntu MySQL:</p>
  
  <pre><code>+----------------+------------------+
  | 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             |
  +----------------+------------------+
  </code></pre>
  
  <p>I can connect to the Ubuntu MySQL instance from the Windows 10 system using TeamSQL using these connection parameters:</p>
  
  <pre><code>Host: 172.19.0.16
  Post: 3306
  User: root
  Password: thisisasamplepassword
  </code></pre>
  
  <p>So, I know that at least connection from the Windows IP is allowed and that the credentials work.</p>
  
  <p>However, I cannot connect from my legacy PHP app in the Docker container using this connection string:</p>
  
  <pre><code>$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);
  </code></pre>
  
  <p>When I use this information, I receive a <code>SQLSTATE[HY000] [2002] Connection timed out</code> error. So in my digging, I found <a href="https://hostpresto.com/community/tutorials/how-to-connect-to-a-remote-mysql-server-via-an-ssh-tunnel/" rel="nofollow noreferrer">this article</a> 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:</p>
  
  <pre><code>Host: 127.0.0.1
  Post: 3306
  User: root
  Password: thisisasamplepassword
  </code></pre>
  
  <p>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.</p>
  
  <p>I changed the PHP app details to this:</p>
  
  <pre><code>$dbHost = "127.0.0.1"
  $dbPort = "3306"
  $dbName = "databasename"
  $dbUser = "root"
  $dbPassword = "thisisasamplepassword"
  </code></pre>
  
  <p>And now I receive a <code>SQLSTATE[HY000] [2002] Connection refused</code> error when I try to connect.</p>
  
  <p>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.</p>
  
  <p>Any thoughts on how to resolve this issue? Thanks in advance.</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Bind address has been set to 0.0.0.0 as shown with this query <code>show global variables like 'bind_address';</code>:</p>
  
  <pre><code>+---------------+---------+
  | Variable_name | Value   |
  +---------------+---------+
  | bind_address  | 0.0.0.0 |
  +---------------+---------+
  1 row in set (0.00 sec)
  </code></pre>
  
  <p>Results from <code>ifconfig</code> from within nginx container:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>Using the suggestion from @Canis, I executed these commands:</p>
  
  <pre><code>docker network create --driver=bridge --subnet=192.168.0.0/16 br0
  docker network connect br0 laradock_nginx_1
  </code></pre>
  
  <p>I still can't access the Ubuntu MySQL container. Here are the current results for <code>ifconfig</code>:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>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?</p>