混乱その2、ネットワークについて。
WindowsホストからWSL2へのNW接続にはホストでport forwardが必要?
という疑問。
手元でdocker-composeで立ち上げている、Docker Desktop for Windows based on WSL2でのJenkins/Rocket.chat/wiki.jsをバックエンドに持つnginx、特にホストでport fowardしなくてもWindowsホスト名のURLでアクセスできている(Windows Defender Firewallでinboudは開けている)のです。
まずは仕組みの情報収集から。
一昨年(2019年)の8、9月頃、Windows 10 Build 18945リリースの記事でホストWindowsからlocalhostでWSL2にNWアクセスできる改良が盛り込まれたという記事がメディアから多数リリースされてました。
- ASCII.jp:Windows Subsystem for Linux 2におけるネットワークの改良 (1/2)
- Linuxがほぼそのまま動くようになった「WSL2」のネットワーク機能:Windows 10 The Latest - @IT
- 「WSL 2」最大の課題であった“localhost”問題が解決 ~「Windows 10」Build 18945 - 窓の杜
WSL2化に伴い、”本物”のLinux KernelをLWUVM(軽量ユーティリティ)で動作させて「WSL 2 と WSL 1 の比較 | Microsoft Docs」の機能比較でWSL1の「❌」を「✅」に改良したわけですが、これによってWSL2側のTCP/IPスタックも本物化されネットワークセグメントがHyer-Vの仮想ネットワークスイッチを使って分離されたことに起因するものとなっています。
確かに我が家も記事通りになっています。
Docker composeでnginx(port:8443)を含むサーバーを立ち上げた状態で、Windowsホストでポートの状態をnetstatで見ると以下のような感じです。わかりやすくする為、関係のない情報は削除しています。
対象プログラムがまちまち([com.docker.backend.exe]/[svchost.exe]/[wslhost.exe)なのが謎ですが、0.0.0.0:8443(IPv4)/[::]:8443/[::1]:8443(IPv6)でlocalhostをListenしているのが、恐らく記事にあるlocalhostで接続できる様になった部分。
すべてがwslhost.exeだと記事の内容と整合してスッキリするのですが、記事はあくまでWSL2に関するものですので、Docker Desktop for Windowsサービスを停止した状態で確認してみるのがいいかもしれません。
Docker コンテナとHost間の通信に関しては、Windows環境ですと”host.docker.internal”が関わっていそうです。
”host.docker.internal”はWindows/Macのみ(Linuxにはない、というか必要性がそもそもない?)にある、コンテナからホストに接続する為のスペシャルDNS名(出所:Docker公式ドキュメント)。
コンテナ起動してChromeでアクセスした状態netstatすると以下のような感じになりました(同じく間引いています)。
6つのポートを使っている理由はわからないのですが、”host.docker.internal”の仕組みを使ってHOST-コンテナ間通信を実現してくれている様です。
冒頭の疑問の自己結論。
- HOST→WSL2間のlocalhoost接続とは全く別の仕組み。
- Docker Desktop for Windowsを使っていれば、Dockerfile(docker-compose.yml)での定義に沿って適切にDokcerがHOST-コンテナ双方向の通信をセットアップしてくれる。
Ubuntu on WSL2にDebianパッケージでDocker導入するパターンを「WSL2 と Docker (compose)ーその1 - ケ・セラ・セラ」で言及しましたけど、同じ機構は機能しないでしょうし、WSL2によるHOSTとのネットワーク分離と相まって、HOSTのサーバー名で外部からコンテナにアクセスするには、こちらの場合、手動でport fowardが必要そうですね。
※現環境を壊して試すインセンティブが今はないので未検証です。
やはり、Winな環境での通常運用では、素直にWin向けを使うのがベターというありきたりな顛末となりました。
最後に利用しているDocker Desktop for Windows環境情報を。