今までWSL1を使っていて、WSL2が安定してきたら、そのうちWSL2を使ってみようかと考えていたのですが、今回必要に迫られてWSL2に移行しました。
WSL1からWSL2への移行と、それにまつわるDockerやX Serverの設定について、徒然なるままに書こうと思います。
移行のきっかけ
WSL1+VcXsrv(X Server)でpuppeteerを動かしていたのですが、Chromiumでエラーが出て動かなくなりました。
Aw, Snap! Something went wrong while displaying this webpage. Error code: SIGABRT
調べたところ、明確な解は得られなかったのですが、どうもWSL1だとChromiumのウィンドウ表示には対応しきれないようでした…。
同じプログラムを、UbuntuをインストールしたPCで実行すると問題なく動いたので、ますますWSL1が怪しく、WSL2に移行すれば動くんじゃないかと、思い切って移行してみました。
結論から言うと、WSL2にするとpuppeteerが動くようになりました!!
WSL1からWSL2への移行手順
下記の記事を参考にしました。
既にWLS1を使っているので
- Linuxカーネル更新プログラムのインストール
- WSL2を既定のバージョンとして設定
wsl --set-default-version 2
- UbuntuのバージョンをWSL2に設定
wsl -l -v
:WSLディストリビューション一覧表示wsl --set-version Ubuntu-18.04 2
:WSL2に設定
のたったこれだけで、WSL1がWSL2に変更されました。
実行時間はかかりますが、想像以上に簡単でした。wsl --set-version Ubuntu-18.04 1
で、WSL2からWSL1に戻すこともできます。
VcXsrv(X Server)の設定
下記の記事を参考にしました。
PowerShellでipconfig
を実行すると、WSL
という新しいIPアドレスが追加されていて、それがWSL2の仮想マシンのIPアドレスになっています。
PS > ipconfig Windows IP 構成 イーサネット アダプター vEthernet (WSL): 接続固有の DNS サフィックス . . . . .: IPv4 アドレス . . . . . . . . . . . .: 192.168.140.241 サブネット マスク . . . . . . . . . .: 255.255.255.240 デフォルト ゲートウェイ . . . . . . .:
WSL1はWindowsの一部なので、IPアドレスはWindowsと同じで、WSL1のDISPLAY
環境変数に指定するIPアドレスはlocalhost
でよかったのですが、WSL2は上記の仮想マシンのIPアドレスにする必要があります。
仮想マシンのIPアドレスは起動時に決まるので、ベタ書きではなく、下記の方法で動的にセットします。
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0
そして、VcXsrvの起動時パラメータに--ac
を設定して起動すると、無事WSL2からVcXsrv(X server)を使ってウィンドウ表示ができるようになります。
「Save configuration」で設定ファイルが保存できるので、次回からは設定ファイルをダブルクリックしてVcXsrvを起動するようにします。
Dockerの設定
今までは、WindowsにDocker Desktopをインストールして、WSL1から使っていました。
Docker DesktopをWSL2に対応するのは、下記の記事を参考にしました。
DockerをWSL2に移行する前に注意
- 従来のDocker Desktopは、Hyper-VでDockerデーモンを実行するVMを立ち上げて、WSL1からそのVMにアクセスする形になっていました。Docker DesktopがWSL2に対応する際、一旦Docker Desktopが、以前のVMを削除してしまうので、Dockerでvolumeを使っていた場合、そのバックアップは移行の前に行っておく必要があります。
Docker DesktopをWSL2に移行する手順は下記のように簡単でした。
- まずは、WSL2のDockerをアンインストールして、再度Dockerをインストール。
- 続いて、Docker Desktopをアップデート。色々聞かれますが、後から設定可能なので適当に回答。
Docker Desktop設定
[Settings] - [General]
「Use then WSL 2 based engine」にチェックを入れると、Docker DesktopがWSL2対応になります。
[Settings] - [Resources] - [WSL INTEGRATION]
上記だけだと、WSL2からDocker DesktopのDockerデーモンにアクセスできないので、「Enable integration with my default WSL distro」にチェックを入れて、どのWSL2のディストリビューションからDockerにアクセスするかのチェックを入れます。
これで、WSL2からDocker Desktopにアクセスできるようになります。
WSL2はどこに作られるのか?
WSL2はHyper-VのVMかと思ったのですが、Hyper-Vマネージャーを見ても、それらしきVMが見当たりません。
前述の通り、PowerShellでipconfig
をすると、WSL2のIPアドレスが出てくるので、どこかにWSL2は存在してはいるのですが…。
WSL2は、Hyper-Vを利用しつつ、従来のHyper-VのVMとは別に、WSL2として独立して存在しているんですね。
Docker DesktopのDockerデーモンはどこに作られるのか?
PowerShellでwsl -l -v
とすると、WSL2のディストリビューション一覧が見れるのですが、その中にdocker-desktopが出てきます。
PS > wsl -l -v NAME STATE VERSION * Ubuntu-18.04 Running 2 docker-desktop-data Running 2 docker-desktop Running 2
なるほど~。Docker DesktopのDockerデーモンは、WSL2のディストリビューションの1つとして起動してるんですね。WSL2のUbuntu上で動いてるのかと思ってました。
WSL2のUbuntuとWSL2のDocker Desktopは別のVMなので、それらをつなぐ設定が、前述の[Settings]-[Resources]-[WSL INTEGRATION]
ということなんですね。
従来のDocker Desktopデーモンを起動する
[Settings]-[General]
で「Use the WSL 2 based engine」のチェックを外すと、従来の、Hyper-VのVMを用いた、Docker DesktopのDockerデーモンが立ち上がります。
互換性のために従来の選択肢も用意されているようです。
WSL2のUbuntuでDockerデーモンを起動する
WSL2はれっきとしたLinuxなので、それだけでもDockerデーモンが動きそう。実際試すとちゃんと動きました。
$ sudo dockerd & $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
しかも、Ubuntuを一度閉じて、再度開いても、Dockerデーモンが残ってます。
$ ps -aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 899 0.0 0.0 67096 4168 ? S 04:04 0:00 sudo dockerd root 906 0.6 0.7 1566784 92612 ? Sl 04:04 0:00 dockerd root 918 0.7 0.4 1429072 52644 ? Ssl 04:04 0:00 containerd --config /var/run/docker/containerd/containeroot...
WSL2は、ウィンドウを閉じても裏で動いているんですね。正にVMです。
となると、たまに再起動したくなるのですが、Linuxのシャットダウンコマンドが使えないので、wsl.exe
からシャットダウンします。
wsl.exe --shutdown
Docker Desktopが無くても、WSL2だけで永続するDockerデーモンが立てられますね。Docker Desktopは容量食うし、開発用途だとDocker Desktopいらないかも。
というわけで、Docker Desktopをアンインストールして、WSL2のUbuntuでDockerデーモンを動かすことにしました。
WSL2のUbuntuでDockerデーモンを自動起動する
しかし、Dockerデーモンを自動実行しようとしても、WSL2ではsystemd
が動かないため、そのままでは無理みたい…。
WSL2でsystemd
が動くようにする方法はいつくかあるのですが、どれも面倒で定番的なのがなさげだったので、とりあえずDockerが必要な時に、手動で実行することにしました。どうしてもWSL2でsystemd
が使いたくなったら、その時考えるとします。
WindowsからWSL2のファイルにアクセスする
WSL1の時は、//mnt/
経由で、WSL1からWindowsのフォルダにアクセスしていたのですが、WSL2では、WSL2からWindowsのフォルダへのアクセスは遅いので推奨されていません。
とは言え、WSL2とWindowsでフォルダを共有できると便利なので、Windowsから\\wsl$
経由でWSL2のフォルダにアクセスします。
Windows Terminal
WSL2のドキュメントにWindows Terminalが出てきたので、ついでにインストールしました。シンプルで設定も楽そうです。
WSLのデフォルトのターミナルは、色が見づらかったのですが、Windows Terminalはカラーテーマを変えられるので見やすくなりますね。
あまり設定をいじるのは好きじゃないんですが、PowerShellの色はやっぱこれでしょ。ということで、PowerShellのテーマを「Campbell Powershell」にしておきました。
感想など
以上で、もろもろのWSL1からWSL2への移行ができました。
最初、WSL2に移行するのはちょっと不安だったのですが、思った以上に簡単でした。WSL1の環境をそのままWSL2に移行できますし、使い心地もWSL1と変わりませんね。
むしろ、本物のLinuxなので、WSL2の方が安定している気がしないでもないです。少なくともpuppeteer、X server関連はWSL2の方が安定して使えます。
Dockerのビルドがイマイチのようでしたら、再度Docker Desktopを使うようにすればいいですしね。
今の所、WSL2に移行して良かったですし、満足しています!