最近、私に支給されている会社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について少し詳しく。 ソースコード自体はここにある。
リポジトリの名前からして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をインストールする。 これは公式ドキュメントを参考にするとよい。
ここまですると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に対応しているからだ。
ただし、上記記事にも書いてあるが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を通常通りインストールする。
systemdが自動で起動されるため、バッチファイルを用意したりする必要がないのは便利。
まとめ
Windows10と11のWSLでDocker Engineを起動する手順をまとめた。 少し手間がかかるがWSLでもDocker Engineが起動できるのは感動する。 デスクトップやその他のつくりを鑑みても、WindowsをデスクトップLinuxの代わりに使ってもそん色がないと思う。 ほんと、Microsoftがすごい頑張っている…!
*1:4年以上デスクトップLinuxだったのでネガティブな感情があったがWSLにチャレンジしようとポジティブな気持ちで乗り換えた