WSLでネットワーク不調時に試すこと

WSLで起動したディストリビューションからネットワーク接続ができなくなることが偶に発生します。

/ # apk update
fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz
WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.19/main: temporary error (try again later)
fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/community/x86_64/APKINDEX.tar.gz
WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.19/community: temporary error (try again later)
4 unavailable, 0 stale; 15 distinct packages available

このような場合、ホストマシンのネットワークアダプターを一旦無効化し、再度有効化すると解決する場合があります。後述するresolv.confの書き換えの前にまず試してみると良いでしょう。

ホストマシンのネットワーク接続が問題なく行えていて、IPアドレス直打ちであればWSLから外のネットワークに接続できる場合、原因はおよそWSL内からDNSの名前解決ができないことによるようです。

解決策としてwsl.confにてresolv.confの自動生成を抑制するよう設定し、/etc/resolv.confnameserver指定をパブリックDNSサーバーに決め打ちで指定するという方法がよく見つかります。

しかし、この方法では自宅内ではLAN内で稼働する機器向けのDNSサーバーを参照し、他のネットワーク接続時はデフォルトのDNSサーバーを参照するという使い方がとても面倒になります。できれば本来の動作のまま使えることを期待したいのです。

今回の解決方法となるネットワークアダプターの操作は、Windows 10ではネットワーク接続画面から行います。

ホストマシンのネットワークアダプターを無効化すると、付随してvEthernet(イーサネット)vEthernet(WSL)の2つのアダプターが削除されます。この2つのアダプターはホストマシンのネットワークアダプターを有効化すると再作成されます。

ネットワーク接続

vEthernet系のアダプターの再作成により、DNS問い合わせエラーによるWSLのネットワーク不調は解決すると思います。

この方法で解決できなかった場合は、resolv.confの書き換えなどの手段を検討してください。

警告
初稿時点ではWindows 11でWSLのネットワーク不調に遭遇していないため、Windows 11で同様に問題が解決するかは確認できていません。
情報

Windows 11では設定アプリのネットワークとインターネットネットワークの詳細設定ハードウェアと接続のプロパティからvEthernet (WSL (Hyper-V firewall))という名前のネットワークアダプターが確認できますが、ネットワークの詳細設定画面からのネットワークアダプター無効化→有効化操作ではvEthernetアダプターが再作成されたようには見えませんでした。

なお、Windows 11のネットワーク接続画面では、vEthernetアダプターが表示されないようになっていました。

情報

2024/4/3追記

WSL 2.2.1からDNSトンネリング機能がデフォルトで有効になり、DNS問い合わせエラーによるネットワーク接続の不調が解消されるようです。

Microsoft、WSL 2.2.1でDNSトンネリングをデフォルトで有効に

2024/4/3時点ではMicrosoft Storeから取得可能なバージョンはWSL 2.1.5ですが、WSL 2.2.1が利用可能になればまず試すことは「wsl --updateを実行すること」になりそうです。

WSL2のAlpine LinuxでDockerを使う

以前WSL2にAlpine Linuxをインストールする手順を紹介しましたが、この環境にDockerを導入してみます。

WSL2でDockerを使用する方法については既に幾つものWebサイトで解説されていますので、後述の自動起動に関する手順など参考にさせていただきました。

情報
2023年7月頃にOpenRCによるdockerdの自動起動に失敗するようになってしまったため、本記事では暫定対応を含めた手順を紹介します。

dockerと関連パッケージ導入

docker-ceとdocker composeの他に、自動起動するためのOpenRCを導入します。

apk add openrc docker docker-cli-compose
openrc sysinit
touch /run/openrc/softlevel
rc-update add docker

一般ユーザー用設定

一般ユーザー権限でdockerを使用できるようにするためには、対象ユーザーをdockerグループに所属させる必要があります。

警告
一般ユーザーがdockerを使用できることは、コンテナを介してホストに対してroot権限を使用できてしまうことを意味します。 基本的には安易に設定しないようにしてください。
addgroup <ユーザー名> docker

自動起動失敗回避

2023年7月頃のdocker-openrcパッケージ更新によりOpenRC経由でのdockerdの起動が失敗してしまうようになりました。

これはAlpine Linuxのissueによるとdockerが生成したネットワークがnetworkingサービスの再起動時に壊れてしまうことに対応するため、dockerとnetworkingに依存関係を設定したことに起因するようです。

WSL2にAlpine Linuxのminirootfsをインポートした環境ではnetworkingサービスは使用されず、設定ファイルが存在しないためnetworkingの起動に失敗します。そのため、dockerの起動前提を満たせないことになりdockerサービスの起動に失敗してしまいます。

暫定対応として、dockerサービスの起動定義ファイル(/etc/init.d/docker)を、依存関係が追加されたときのコミットを参照して以前の状態に手動で戻します。

/etc/init.d/dockerdepend内のnetを削除します。

 depend() {
-	need sysfs cgroups net
+	need sysfs cgroups
 	after firewall
 }

これで、OpenRCからdockerが起動できるようになります。

自動起動設定

Windowsから以下のコマンドを実行することでOpenRCが起動し、OpenRCによってdockerサービスが起動します。

wsl -d Alpine -u root --exec /sbin/openrc sysinit

この方法では、タスクスケジューラーなどでWindowsログイン時に上記コマンドを実行してあげる運用が考えられます。

また、Microsoft Store版WSLではディストリビューション起動時にコマンドを自動実行する機能が追加されています。

情報
コマンド自動実行機能はWindows 11のinbox版WSLで追加された機能ですが、Store版WSL正式リリースによりWindows 10にバックポートされた形になります。

今更ながら WSL2 の Alpine で Docker 環境構築という記事に/etc/wsl.conf[boot]セクションに起動コマンドを設定する方法について書かれていました。通常はこちらの手順で自動起動するのが使い勝手が良いと思います。

WSL2にAlpine Linuxをインストールする

WSL2にAlpine Linuxをインストールして、一般ユーザーでログインできるように設定します。

WSL2の有効化

2022/11にMicrosoft StoreのWSLが正式版になったので、Windowsインボックス版ではなくStore版を使います。Store版ではWindows 10でもWindows 11のインボックス版以降に追加された機能が使用可能になります。

インストールは、管理者権限のコマンドプロンプトから下記コマンドで行えます。(参考: WSL を使用して Windows に Linux をインストールする)

wsl --install

Microsoftのサイトに書かれていますが、上記コマンドを実行すると既定のディストリビューションとしてUbuntuがインストールされます。Alpine Linuxだけ使えれば充分という場合はMicrosoft Storeから直接Windows Subsystem for Linuxをインストールするのが良いかもしれません。

Alpine Linuxのインストール

この手順では、Alpine LinuxのDownloadsページより入手可能なMini root filesystemのアーカイブファイルを使用します。各種CPUアーキテクチャ用のファイルが用意されていますが、WSL2での使用を目的とするならまず間違いなくx86_64を選択することになるでしょう。自分の環境に合ったアーカイブファイルをダウンロードしてください。

ダウンロードしたMini root filesystemのアーカイブファイルを次のコマンドでインポートします。

wsl --import Alpine C:\wsl\alpine alpine-minirootfs-3.18.0-x86_64.tar.gz --version 2

このコマンド例では次のような指定をしています。

  • WSLでのディストリビューション名 Alpine
  • インポート先ディレクトリ C:\wsl\alpine
  • Mini root filesystemのアーカイブファイル alpine-minirootfs-3.18.0-x86_64.tar.gz
  • 使用するWSLのバージョン 2

Alpine Linux起動

Windowsターミナルを使用している場合は、プロファイルが自動的に作成されます。

コマンドプロンプトでは次のコマンドで起動できます。

wsl -d Alpine

Alpine Linuxが起動し、画面がashに切り替わります。

既存パッケージの更新

apk update
apk upgrade

apk updateでパッケージリストを更新し、apk upgradeで更新されたパッケージをインストールします。

通常使用でも、定期的に実行するのが望ましいです。

suを使用可能にする

passwd
apk add busybox-suid

一般ユーザからrootにスイッチする場合、rootにパスワードが設定されて入る必要があります。デフォルトではrootのパスワードは設定されていないので、ここで設定しておきます。

suコマンド自体は最初からbusyboxのシンボリックリンクとして用意されていますが、busyboxにはsuidの設定がないため、一般ユーザが呼び出しても権限不足となりsuコマンドが失敗します。busybox-suidはsuidが必要になるコマンドをbusyboxに代わって提供します。

一般ユーザー作成

adduser <ユーザー名>

デフォルトユーザー設定

/etc/wsl.confを作成して、以下の内容を書き込みます。

[user]
default = <ユーザー名>

次回Alpine Linux起動時から反映されます。