ぶていのログでぶログ

思い出したが吉日

Windows10/11のWSL2でDocker Engineを使う

最近、私に支給されている会社PCがデスクトップLinuxからWindows*1になったので環境を整えている。 デスクトップLinuxからWindowsになって一番困るのは環境構築である。 しかしながら、最近のWSLはかなりよくできていてデスクトップLinuxと同じような感じで使えるのだが、Docker Engine(not Docker Desktop)についてはインストールしてすぐ使えるというわけではなかったのでセットアップの手順をまとめておく。

要約

  • Windows10
    • Ubuntu 22.04イメージを使う
    • wsl-systemdとnsloginを使う
  • Windows11
    • v0.67.6以降のsystemdを使う

Windows10

この記事を書いた時点ではWindows10と11でWSLの機能が若干違うためセットアップ手順が違うので注意。 まず前提としてWSL2を使用する。 Windows10のWSL2ではsystemdがサポートされていないが、Ubuntu 22.04イメージにはwsl-setupパッケージがインストールされていてその中に含まれるwsl-systemdとnsloginを使うと、なんとsystemdがPID=1で起動する。 systemdが起動すればdocker.serviceが起動するという感じ。

wsl-systemdとnsloginについて少し詳しく。 ソースコード自体はここにある。

github.com

リポジトリの名前からしてUbuntuプロジェクトの一環なのだろうか? wsl-systemdはsystemdをPID=1で動かすためのnamespaceを新しく作ってそこでsystemdを起動するというシンプルな作りになっている。 nsloginはwsl-systemdで作ったnamespaceにアタッチしてプロセスを実行するという処理になっている。 どちらもLinuxの機能で実装されていてかつシンプルな仕組みになっていて関心する。

設定

まずはUbuntu22.04をインストールする。 Microsoft Storeもしくはwingetでインストールできると思う。 wingetなら↓な感じ

> winget install "Ubuntu 22.04 LTS"

# 必要に応じて実行
> ubuntu2204.exe install

wsl-systemdはroot権限で実行する必要があるためsudoが必要になる。 sudo実行時にパスワードを聞かれると少々面倒なので、必要に応じてNOPASSWDをつけておく。

$ sudo visudo -f /etc/sudoer.d/sudo
%sudo ALL=NOPASSWD: ALL

次にsystemdを起動してnsloginする

$ sudo /usr/libexec/wsl-systemd
$ /usr/libexec/nslogin

nsloginするとsystemdがPID=1で見えるはず。

$ ps auxwwff | grep systemd
root           1  0.0  0.0 166200 11284 ?        Ss   11:53   0:00 /lib/systemd/systemd --unit=multi-user.target
-- snip --

systemdが起動したらDocker engineをインストールする。 これは公式ドキュメントを参考にするとよい。

docs.docker.com

ここまでするとDockerが起動しているはずである。

$ sudo docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
  compose: Docker Compose (Docker Inc., v2.10.2)
  scan: Docker Scan (Docker Inc., v0.17.0)

Server:
 Containers: 2
  Running: 0
  Paused: 0
  Stopped: 2
 Images: 15
 Server Version: 20.10.18
 Storage Driver: overlay2
-- snip --

Dockerが起動できるようになったが、Windowsが再起動されるとsystemdもdockerも停止されてしまう。 それは少々手間なので自動実行されるようにする。 以下のようなbatファイルをWindowsのスタートアップフォルダに配置する。 スタートアップフォルダはファイル名を指定して実行(Win+R)して shell:startup と入力して実行すると開かれる。

@echo off

wsl.exe -d Ubuntu-22.04 -- sudo /usr/libexec/wsl-systemd
wsl.exe -d Ubuntu-22.04 -- /usr/libexec/nslogin sudo systemctl start docker.service

exit /b

そしてWSLのコマンドを実行する際にnsloginを使用する。 例えば以下のように実行する。

> wsl.exe -d Ubuntu-22.04 -- /usr/libexec/nslogin

しかしこれは面倒なのでターミナルの起動コマンドに設定しておくと便利。 私はWindwosターミナルを使っているので、以下のように設定している。

おまけ: Ubuntu20.04でもwsl-systemd/nsloginは動く?

結論から書くと動きそう。ただし、すべて動作確認したわけではないのとnsloginにsudoが必要そう。 以下、動かすまでの手順のメモだけ。

# ソースコードからビルドする必要がある
$ sudo apt install -y build-essential libsystemd-dev
$ git clone https://github.com/ubuntu/wsl-setup
$ cd wsl-setup
$ make
$ sudo systemd/wsl-systemd
$ sudo systemd/nslogin/nslogin sudo -u $USER bash --login -i
$ ps auxwwff | grep systemd
root           1  0.0  0.0 170328 12568 ?        Ss   11:28   0:00 /lib/systemd/systemd --unit=multi-user.target
-- snip --

Windows11

Windows11では10ほどめんどくさい手順は不要になっている。 というのもWSLのv0.67.6以降からネイティブでsystemdに対応しているからだ。

forest.watch.impress.co.jp

devblogs.microsoft.com

ただし、上記記事にも書いてあるがMicrosoftStore版のWSLをインストールしないと使えないようである。 wingetでインストールする場合以下のようなコマンドになるはず。

> winget install "Windows Subsystem for Linux Preview

次にWSLで使用するディストリビューションであるがこれはなんでもいいはず…未確認。 私はUbuntu22.04を使用した。 WSLを起動したら /etc/wsl.conf を設定する。このファイルはデフォルトでは存在しないようなので新規に作成する。

$ cat /etc/wsl.conf
[boot]
systemd=true

設定したら一度WSLを再起動すると反映されているはず。

> wsl.exe --shutdown
> wsl.exe
$ ps auxwwff | grep systemd
message+     297  0.0  0.0   8752  4484 ?        Ss   15:53   0:00 @dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
-- snip --

systemdが起動したらDockerを通常通りインストールする。

docs.docker.com

systemdが自動で起動されるため、バッチファイルを用意したりする必要がないのは便利。

まとめ

Windows10と11のWSLでDocker Engineを起動する手順をまとめた。 少し手間がかかるがWSLでもDocker Engineが起動できるのは感動する。 デスクトップやその他のつくりを鑑みても、WindowsをデスクトップLinuxの代わりに使ってもそん色がないと思う。 ほんと、Microsoftがすごい頑張っている…!

*1:4年以上デスクトップLinuxだったのでネガティブな感情があったがWSLにチャレンジしようとポジティブな気持ちで乗り換えた