hidekatsu-izuno 日々の記録

プログラミング、経済政策など伊津野英克が興味あることについて適当に語ります(旧サイト:A.R.N [日記])

WSL2 で Systemd と docker を有効にする

WSL2 はリリース以来とても便利に使っているのだけど、不満がいくつかあった。ひとつは Systemd が使えないこと、もうひとつはそれが理由で docker のサービス起動が厄介なこと。

Docker Desktop for Windows を使うというのが今までのセオリーだったのだけど、起動のたびに通知やらが来てインターフェイスがうざったいのと、最近有償化された(個人利用は無償だけど)こともあって利用を避けていた。

ところが先日 WSL2 用の Ubuntu 22.04 が出ていたので更新してみたところ、標準で systemd が使えるようになったというではないか。systemd が使えるなら docker も問題なく使えるはずでこれは試してみねば、とさっそく設定してみたというのが本日の内容です。

[2022/09/01] Windows 11 だけでなく Windows 10 でも動くようになったので追記した。

1. Ubuntu 22.04 のインストール

Windows ストアにて Ubuntu 22.04 を選択してインストールを行う。Ubuntu 22 からは独自のセットアップ画面が付いたようで、言語などを選択できる。

Windows 10 では文字化けしているせいかもしれないが日本語が選べないので、英語を選択しセットアップをが完了した後、以下のコマンドを発行して日本語化をおこなう。

sudo apt-get install -y language-pack-ja
sudo update-locale LANG=ja_JP.UTF-8

2. /etc/wsl.conf の設定

Ubuntu 22.04 を起動し、sudo vi /etc/wsl.conf を実行し下記内容を記載する。なお、Windows 10 では起動しなくなるのでこの節の内容は決して実行してはならない(飛ばして良い)。

[boot]
command = "/usr/libexec/wsl-systemd"

3. WSL2 を再起動する

wsl --shutdown を実行してもいいけど、単にPCを再起動してしまうのが一番簡単です。 これで systemd が問題なく使えるようになる。記事によっては nslogin が必要との記載があるが、Windows 11 に関しては特に必要はありませんでした。

Windows 10 の場合は、~/.bash_aliases を追加し以下 alias を追加したら再起動してください。

alias sudo='sudo '
alias systemctl='/usr/libexec/nslogin systemctl'

4. WSL2 を自動起動する

今回のエントリの独自要素はここだけ。WSL2はすべてのコンソールを落とし一定時間が経つと自動的に停止するようになっている。単にコマンドラインで使う分には余計なリソースを食わないしこれでよいのだけれど、docker など各種サービスを起動しておきたい場合には困ってしまう。

以前の WSL ではタスクスケジューラで対応できたのだけど、最近の WSL2 ではうまくいかないようで。そこで、Windows Scripting Host を使って非表示のコンソールをひとつ立ち上げることにしてみた。

具体的には下記のスクリプトを shell:Startup 以下に wsl2-startup.wsf などの名前で保存するだけ。(ユーザー名の部分は変えてください)

<job>
<script language="JScript">
var shell = WScript.CreateObject("WScript.Shell");
shell.Run('ubuntu2204.exe', 0);
shell = null;
</script>
</job>

shell.Run の第2引数を 0 にすると非表示のウィンドウを開くため、ログイン時にまるで systemd が自動起動したかのように動作することになる。注意事項としては、スタートアップスクリプトは起動しきるまで多少時間がかかる。tryrun を使ってタスクトレイに出すのも一案。

github.com

Windows 10 の場合は、sudo をパスワードなしで起動できるようにしたうえで、ubuntu2204.exe の部分を下記のように書き換えることで対応できる。

修正前: shell.Run('ubuntu2204.exe', 0);
修正後: shell.Run('ubuntu2204.exe run "sudo /usr/libexec/wsl-systemd && /bin/bash"', 0);

ただし、スクリプトを見ればわかるように sudo を使っているので /etc/sudoers に NOPASSWD 権限の追加が必要です。

%sudo ALL=(ALL:ALL) NOPASSWD: /usr/libexec/wsl-systemd

5. Docker のインストール

ここまでくれば普通の Ubuntu 同様に使えるので、公式サイト記載の手順で docker-ce を通常通りインストールすればほとんど完了です。

docs.docker.com

なお、発生条件は不明ながら、Windows 10 では下記のパッケージが悪さをする場合があるため上記手順よりも前に削除した方がよいかもしれない。

sudo apt purge needrestart

あとは、ユーザーの docker group への追加と iptables の実装を切り替えるだけ。

sudo usermod -aG docker $USER
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo systemctl restart docker.service

docker compose も always restart も問題なく動作します。