今あえて WSL1 を使う意義 + WSL1 で Docker を使う的なやつ
WSL1
WSL1 は Windows で Linux 向けのバイナリを動かすための仕組み。Linux システムコールを Windows システムコールに変換することで動いてる闇の技術。ざっくり言えば Wine の逆バージョン的なものだと思っている。その仕組み上、Linux との完全な互換性はない。
WSL1 のメリット
- メモリの消費量が少ない(実行しているプロセスの分だけ消費)
- ホストのネットワークスタックをそのまま使う(VPNとの相性が良い)
WSL1 のデメリット
- ファイル I/O が遅い(npm等を実行するときに感じやすい)
- Linux カーネルに依存する機能が使えない (Docker Engineの実行などができない)
WSL2
WSL2 は Windows で Linux を動かすための仕組み。軽量仮想マシン上で Linux カーネルが動作しているので、当然ながら Linux との互換性は高い。
WSL2 のメリット
- Linux とのほぼ完全な互換性 (Docker Engine等も実行できる)
- (WSL1と比較して)ファイル I/O が高速
WSL2 のデメリット
- (WSL1と比較して)メモリ消費量が大きい (メモリの少ない PC だと厳しい)
- ネットワーク的にはホストと別マシンになってしまう (VPNソフトウェアによってはホストとWSL2仮想マシン間の通信を遮断してしまう)
※もっとも、ここで挙げた WSL2 のデメリットはそう遠くない時期に解消されそうなので、ここに書き残した情報は意味がなくなるかもしれない。
WSL2 から WLS1 に変換する
方法 1: 既存の環境をダウングレードする
-
wsl -l -v
でディストリビューションの名前を調べる -
wsl --set-version <ディストロ名> 1
を実行する
逆の変換もいつでもできる。
方法 2: 既存の環境を複製して WSL1 にする
-
wsl --export <ディストロ名> <ファイル名>
で環境をエクスポートする -
wsl --import <ディストロ名('-WSL1'をつける等名前を変える)> <インストール先> <ファイル名> --version 1
でインポートする
WSL1 から Docker を使う
WSL1 だと Docker が使えないと思いがちだが、実際には使うことができる。先述した通り WSL1 の中で Docker Engine を動かすことはできないが、WSL2 上で動いている Docker Engine を WSL1 から操作することはできる。
Docker Desktop で TCP ソケットを有効にする
docker
コマンドはデフォルトでは unix:///var/run/docker.sock
にアクセスすることで Docker Engine を操作しているが、UNIX ソケットの代わりに TCP でも操作することができる。
TCP 経由で Docker Engine をコントロールできるようにするには、「Expose daemon on tcp://localhost:2375 without TLS」を有効にする。
WSL1 から Docker Desktop の Docker Engine を使うようにする
以下のコマンドをWSL1のシェルで実行すれば良い。
$ docker context create remote --docker 'host=tcp://localhost:2375'
$ docker context use remote
この設定は VS Code の Remote 拡張機能で WSL1 ディストリビューションに接続しているときの Docker 拡張機能にも反映される。
おまけ: Rancher Desktop で TCP ソケットを有効にする
Rancher Desktop には TCP ソケットを有効にする設定はない。そのため、UNIX ソケットを TCP ソケットに変換するコンテナを走らせることで代替する。
まず以下のコマンドで rancher-desktop の内部シェルにアクセスする。
> wsl -d rancher-desktop
次にソケット変換のコンテナを起動する。
# docker container run -dt --name expose-docker-on-2375 --network=host -v /var/run/docker.sock:/var/run/docker.sock --restart=always rancher/socat-docker
これでDocker Desktop で「Expose daemon on tcp://localhost:2375 without TLS」を有効にしたのと同じ効果が得られたので、あとは同様にやれば良い。