🔥

Windows WSL2環境でのDocker Desktopネットワーク接続問題と解決策

に公開

はじめに

Windows 11 Pro (22H2) 環境下で、WSL2 (Ubuntu 22.04 LTS) と Docker Desktop for Windows (v4.2x) を利用している際に、Dockerコンテナから外部ネットワークへの接続が不能になる事象が発生した。

具体的には、コンテナ内で ping 8.8.8.8apt-get update を実行すると、名前解決または通信がタイムアウトする。ホストであるWindowsやWSL2ディストリビューション自体からは外部ネットワークへアクセス可能であるにもかかわらず、Dockerコンテナ内からの通信のみが失敗する状況である。

本稿は、この問題の調査過程と解決策をまとめた技術的備忘録である。

原因

WSL2は、Windowsホストとは独立した仮想イーサネットアダプター (vEthernet (WSL)) を持つ仮想マシン上で動作する。Docker Desktopは、WSL2統合機能を有効にすると、このWSL2の環境内にDockerデーモンを配置する。

この問題の主な原因は、WSL2のネットワーク構成、特にDNS設定にあることが多い。WSL2は起動時に、Windowsホストのネットワーク設定を基に /etc/resolv.conf を自動生成する。しかし、VPN接続やネットワークアダプターの優先順位変更、Windowsのアップデートなど、何らかの要因でこの自動生成プロセスが失敗し、不正なDNSサーバーのIPアドレスが設定されることがある。

結果として、WSL2およびその上で動作するDockerコンテナが名前解決できなくなり、外部への接続が失敗する。また、ファイアウォールやWindowsのネットワークスタック自体の不整合が原因となるケースも考えられる。

解決策

問題の切り分けと解決のため、以下の手順を段階的に実行する。

1. WSL2自体のDNS設定を確認・修正する

まず、Dockerコンテナではなく、WSL2ディストリビューション自体で名前解決が機能しているかを確認する。

# WSL2のターミナルで実行
cat /etc/resolv.conf

nameserver として表示されるIPアドレスが、Windowsホストが使用するDNSサーバーと異なる、あるいは到達不能なアドレスである場合、DNS設定が問題である可能性が高い。

WSL2は起動のたびに /etc/resolv.conf を上書きするため、このファイルを直接編集しても恒久的な解決にはならない。DNS設定の自動生成を無効化し、手動で設定を固定する。

/etc/wsl.conf ファイルを作成または編集し、以下の内容を記述する。

[network]
generateResolvConf = false

設定を適用するため、PowerShellまたはコマンドプロンプトでWSLを完全にシャットダウンする。

wsl --shutdown

WSLを再起動後、/etc/resolv.conf を手動で作成する。ここでは、パブリックDNSであるGoogle Public DNSを設定する例を示す。

# WSL2のターミナルで実行
sudo rm /etc/resolv.conf
sudo sh -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
sudo sh -c 'echo "nameserver 8.8.4.4" >> /etc/resolv.conf'

再度、WSL2からネットワーク接続を確認する。

# WSL2のターミナルで実行
ping -c 3 google.com

この時点でWSL2から外部への接続が回復すれば、原因はDNS設定にあったと特定できる。

2. Dockerコンテナからのネットワーク接続を再確認する

WSL2のネットワークが回復した後、Dockerコンテナ内からの接続をテストする。

# PowerShellまたはWSL2のターミナルで実行
docker run --rm busybox nslookup google.com
docker run --rm busybox ping -c 3 8.8.8.8

これで接続が成功すれば問題は解決している。DockerはWSL2のネットワーク設定を継承するため、WSL2側のDNS設定が修正されれば、コンテナのネットワークも正常に機能する。

3. Windowsネットワーク設定を確認する

上記手順でも解決しない場合、Windowsホスト側の設定が影響している可能性がある。

  • Windows Defender ファイアウォール: vEthernet (WSL) アダプターに関連する通信がブロックされていないか確認する。一時的にファイアウォールを無効にして、問題が解消するかを試すことで切り分けが可能である。
  • VPNクライアント: VPNソフトウェアがルーティングテーブルを変更し、WSL2のトラフィックを妨害することがある。VPNを無効にして接続を試す。
  • ネットワークスタックのリセット: 管理者権限で開いたコマンドプロンプトで以下のコマンドを実行し、Windowsのネットワーク設定を初期化する。実行後、PCの再起動が必要である。
netsh winsock reset

4. Docker DesktopとWSLをリセットする

最終手段として、関連コンポーネントの設定を工場出荷状態に戻す。

  1. Docker Desktopのリセット: Docker Desktopの "Troubleshoot" (トラブルシューティング) メニューから "Reset to factory defaults" (工場出荷時の設定にリセット) を実行する。これにより、すべてのイメージ、コンテナ、ボリュームが削除されるため、事前にバックアップを取得すること。
  2. WSLの再起動: wsl --shutdown コマンドでWSLを完全に停止させてから、再度起動する。

まとめ

WSL2環境におけるDocker Desktopのネットワーク接続不良は、多くの場合、WSL2が自動生成するDNS設定ファイル (/etc/resolv.conf) の不整合に起因する。

/etc/wsl.conf を用いてDNS設定の自動生成を抑制し、手動で信頼できるDNSサーバーを指定することが、安定した開発環境を維持するための有効な手段である。

問題が発生した際は、まずWSL2単体でのネットワーク接続を確認し、次にDockerコンテナ、そしてWindowsホスト側へと、レイヤーを追って原因を切り分けるアプローチが推奨される。

参照

Discussion