1614 words
8 minutes
VirtualBoxからDocker Desktop上のMySQLへ接続する方法

WSL2 + Docker Desktop上で動かしているMySQLへ、VirtualBoxのゲストOSから接続する。

今回の環境では、DockerのMySQLをホストWindowsの3307番ポートに公開していた。

0.0.0.0:3307->3306/tcp

しかし、VirtualBoxから、

<ホストPCのIPv4>:3307

へ直接接続することはできなかった。

最終的にはWindowsのportproxyを使って、

VirtualBox
↓
Windowsホスト
↓
portproxy
↓
localhost:3307
↓
Docker Desktop / WSL2
↓
MySQL:3306

という経路を作ることで接続できた。

この記事では、その設定手順だけまとめる。

実際に「Dockerでポート公開してるのになんで繋がらんねん」と順番に調べた記録はこちら。

WSL2 + Docker DesktopのMySQLにVirtualBoxから接続できなかった話

前提#

今回確認した環境は以下。

ホストPC
├─ Windows
├─ WSL2
├─ Docker Desktop
│ └─ MySQLコンテナ
│
└─ VirtualBox
└─ Windows

MySQLコンテナは、

コンテナ側 : 3306
Windows側 : 3307

として公開している。

まずdocker psで確認する。

Terminal window
docker ps

MySQLのPORTSが今回の環境では以下のようになっていた。

0.0.0.0:3307->3306/tcp

以下では、この3307をDocker Desktop上のMySQLへ接続するポートとして扱う。

1. ホストWindowsのIPv4アドレスを確認する#

ホストWindowsで、

Terminal window
ipconfig

を実行する。

WSL2やVirtualBoxが入っていると複数のネットワークアダプターが表示される。

今回使用したのは、ホストPCが実際のネットワーク接続に使っているアダプターのIPv4アドレス。

Wi-Fi接続なら、例えば以下のような箇所を見る。

Wireless LAN adapter Wi-Fi:
IPv4 Address. . . . . . . . . . . : 192.168.x.x

以降、このアドレスを、

<ホストPCのIPv4>

とする。

2. localhostからMySQLの公開ポートへ接続できるか確認する#

ホストWindowsで、

Terminal window
Test-NetConnection localhost -Port 3307

を実行する。

今回の環境では、

TcpTestSucceeded : True

となった。

ここがFalseなら、今回とは状況が違う。

今回解決したのは、

localhost:3307
→ True

なのに、

<ホストPCのIPv4>:3307
→ False

となるケース。

3. portproxyでVirtualBox向けの入口を作る#

Windowsの管理者PowerShellを開く。

今回の切り分けでは、まず13307番ポートを入口として設定した。

Terminal window
netsh interface portproxy add v4tov4 `
listenaddress=0.0.0.0 `
listenport=13307 `
connectaddress=127.0.0.1 `
connectport=3307

これで、

Windows:13307
↓
localhost:3307

へ転送する。

設定は以下で確認できる。

Terminal window
netsh interface portproxy show all

今回なら、

0.0.0.0 13307 → 127.0.0.1 3307

という形になる。

4. Windows Firewallで13307を許可する#

VirtualBoxからWindowsの13307へ接続するため、受信を許可する。

管理者PowerShellで、

Terminal window
New-NetFirewallRule `
-DisplayName "VirtualBox to Docker MySQL 13307" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 13307 `
-Action Allow

を実行する。

5. ホストWindows自身から確認する#

まずVirtualBoxへ行く前に、ホストWindows自身から確認する。

Terminal window
Test-NetConnection <ホストPCのIPv4> -Port 13307

今回の環境では、

TcpTestSucceeded : True

になった。

ここがTrueになってからVirtualBox側を確認する。

6. VirtualBoxから確認する#

VirtualBoxのゲストWindowsで、

Terminal window
Test-NetConnection <ホストPCのIPv4> -Port 13307

を実行する。

こちらも、

TcpTestSucceeded : True

になれば、VirtualBoxからWindowsホストのportproxyまで通信できている。

今回確認できた経路はこう。

VirtualBox
↓
<ホストPCのIPv4>:13307
↓
Windows portproxy
↓
127.0.0.1:3307
↓
Docker Desktop / WSL2
↓
MySQL:3306

7. アプリ側でポートを指定できない場合#

今回もう一つ引っかかったのがこれ。

接続対象のアプリに、MySQLのポート番号を指定する設定が見当たらなかった。

13307を指定できないのであれば、VirtualBoxから見える入口自体をMySQL標準の3306番にすればいい。

13307の設定を削除する場合は、

Terminal window
netsh interface portproxy delete v4tov4 `
listenaddress=0.0.0.0 `
listenport=13307

そして3306を入口にする。

Terminal window
netsh interface portproxy add v4tov4 `
listenaddress=0.0.0.0 `
listenport=3306 `
connectaddress=127.0.0.1 `
connectport=3307

経路はこうなる。

VirtualBox
↓
<ホストPCのIPv4>:3306
↓
Windows portproxy
↓
127.0.0.1:3307
↓
Docker Desktop / WSL2
↓
MySQL:3306

Firewall側でも3306の受信を許可する。

Terminal window
New-NetFirewallRule `
-DisplayName "VirtualBox to Docker MySQL 3306" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 3306 `
-Action Allow

VirtualBox側から、

Terminal window
Test-NetConnection <ホストPCのIPv4> -Port 3306

がTrueになれば、ポート指定できないアプリからも通常のMySQLポートとして接続できる形になる。

うまくいかないときの切り分け#

今回の調査で役に立ったのは、いきなりVirtualBoxから確認するのではなく、接続経路を順番に見ることだった。

① localhost:3307
↓
② ホストIPv4:portproxyのポート
↓
③ VirtualBox → ホストIPv4:portproxyのポート

例えば、

Terminal window
Test-NetConnection localhost -Port 3307

がFalseなら、まずDocker Desktop側までの接続を見る。

これがTrueで、

Terminal window
Test-NetConnection <ホストPCのIPv4> -Port 13307

がFalseなら、Windows側のportproxyやFirewallを確認する。

ホスト自身からTrueなのにVirtualBoxからFalseなら、そこからVirtualBoxとWindowsホスト間の通信を疑う。

一気にMySQLまで見ようとせず、

「どの地点まではTrueなのか」

を見ると切り分けしやすい。

補足:3307 → 3307のportproxyではうまくいかなかった#

今回最初は、

0.0.0.0:3307
↓
127.0.0.1:3307

というportproxyを作った。

設定自体は、

Terminal window
netsh interface portproxy show all

で表示された。

IP HelperサービスもRunningで、IPv6のバインドも有効だった。

しかし、

Terminal window
netstat -ano | findstr :3307

ではLISTENしている状態を確認できず、Test-NetConnectionもFalseのままだった。

そこで入口を13307へ変更したところ、接続できるようになった。

そのため今回の環境では、

13307 → 3307

のように別ポートを入口として使っている。

なお、ここでは「なぜ3307→3307ではLISTENしなかったのか」までは確認していない。

今回実際に確認できたのは、

3307 → 3307
接続できなかった
13307 → 3307
接続できた

というところまで。

まとめ#

今回の環境では、VirtualBoxからDocker Desktop上のMySQLへ直接接続するのではなく、

VirtualBox
↓
Windowsのportproxy
↓
Docker Desktop / WSL2
↓
MySQL

という経路を作ることで接続できた。

ポイントは、docker psで、

0.0.0.0:3307->3306/tcp

と表示されていることだけで判断せず、

localhost → Windows自身のIPv4 → VirtualBox

と順番にTest-NetConnectionしていくこと。

今回はその切り分けをしていった結果、Windows側にportproxyで入口を作るところまでたどり着いた。

遠回り込みでどうやってここにたどり着いたかは、本編にまとめている。

WSL2 + Docker DesktopのMySQLにVirtualBoxから接続できなかった話