🤖

images.linuxcontainers.orgを利用して手軽に色々なWSL2ディストリビューションを作る

2024/11/21に公開

(追記 2024-11-22)cloud-initを使ったプロビジョニング方法について追記

WSL2ディストリビューションに関して、
Microsoft Storeからインストールできるものや、あるいは
wsl --list --onlineで表示されるリスト以外のディストリビューションをインストールしたくなったり、
あるいは同じ種類のディストリビューションを複数個インストールしたくなったりすることがある(目的別にUbuntu24.04を2つ並用する、とか)。

というときの選択肢を探ってみる。

方法

https://learn.microsoft.com/ja-jp/windows/wsl/use-custom-distro

に記載されているように、wsl --importコマンドでLinuxのコンテナの中身を含むtarファイルを取り込むことで任意のLinuxディストリビューションをWSL2に登録することができる。

上記のリンク先の解説ではDockerコンテナを使っているが、
linuxcontainers.orgで公開されているイメージ:

https://images.linuxcontainers.org/

をそのままwsl --importコマンドで取り込むことができ、即座に対応するWSL2ディストリビューションを作ることができる。

公開されているイメージは

  • ubuntu
  • debian
  • fedora
  • archlinux
  • alpine
  • almalinux
  • rockylinux
  • amazonlinux
  • (その他数え切れないくらい多数)

といった感じで、かなり多くの選択肢がある。
(もちろん無いものもあるにはあるが)

所望のイメージのページに行き、rootfs.tar.xzをダウンロードし、

powershell
wsl --import <登録するディストリビューション名> <仮想ディスクなどの保存場所のパス> <rootfs.tar.xzの保存パス>

のようにして、wsl --importの第3引数でダウンロードしたrootfs.tar.xzを指定して取り込むと、所望のWSL2ディストリビューションをインポート出来る。

手元ではとりあえずubuntu-24.10(oracular), fedora41, amazonlinux2023, archlinuxあたりをインポートしてみたが、どれも問題なく起動した。

(発展)cloud-initによるディストリビューションのセットアップ・プロビジョニング

全部のイメージがそうかまでは確認できていないが、見た範囲ではどのディストリビューションでもユーザーがrootしか存在しないため、
実用的にはユーザーの作成などを行う必要がある。
また、パッケージ・ライブラリの追加や設定ファイルの記入なども一般には必要になる。

ここで、WSL2ではcloud-init:

https://cloudinit.readthedocs.io/en/latest/reference/datasources/wsl.html

https://cloudinit.readthedocs.io/en/latest/tutorial/wsl.html

https://documentation.ubuntu.com/wsl/en/latest/tutorials/cloud-init/

が使えるため、cloud-initを使うことでWSL2の初期設定を自動化し、再現性の高いものにできる。

user-dataファイルの記入と配置

WSL2でcloud-initを実行するにあたり、事前に<WSL2ディストリビューション名>.user-dataという名前のyamlファイルを作成し、
Windows上の%USERPROFILE%\.cloud-init(%USERPROFILE%はWindowsにおけるホームディレクトリのようなもの)に格納しておく必要がある。

記入にあたり、詳細にはリファレンス:

https://cloudinit.readthedocs.io/en/latest/reference/modules.html#modules

および、設定例:

https://cloudinit.readthedocs.io/en/latest/reference/examples.html#yaml-examples

などを参考に作っていけば良い。

手元では↓のようなuser-dataを作成して動作確認した:

%USERPROFILE%/.cloud-init/<WSL2ディストリビューション名>.user-data
#cloud-config

# タイムゾーンとlocaleを設定↓
timezone: Asia/Tokyo
locale: en_US.utf8

# `wsl-usser`というUID=1000のユーザーを作成し、パスワード無しでsudoを使える設定にしておく
users:
- name: wsl-user
  groups: [adm, sudo, wheel]
  sudo:
    - ALL=(ALL) NOPASSWD:ALL
  uid: 1000
  # ↓深い意味は無いが、例としてデフォルトのシェルを後でインストールするfishに設定する
  shell: /usr/bin/fish

# ↓aptやdnf, pacmanなどでインストールするパッケージ名を指定
packages:
- tmux
- fish
- htop
- fzf
- ripgrep

# ↓自動でファイルを作成したり追記したりできる
write_files:
# /etc/wsl.confを記述することにより、systemdの有効化と、ログイン時のデフォルトユーザーをcloud-initで作成するものに設定している
- path: /etc/wsl.conf
  append: true
  content: |
    [boot]
    systemd=true
    [user]
    default=wsl-user

# ↓この例では意味のあることはしていないが、shellで実行できる操作を順次記述していける
runcmd:
- echo "cloud-init" >> /tmp/sample.txt

上記の内容で、執筆時点でのUbuntu-24.10, Fedora41, archlinuxで動作することを確認している。

※package名は同じものでもディストリビューションによって名称が違う、あるいはパッケージによって存在したりしなかったりする、ということがありうるので、常に異なるディストリビューションで使い回せるとは限らない。(が、差分を小さくできるのも事実だと思われる)

wsl2でのcloud-initの実行

記事の方法で記載したようなやり方でwsl.exe --importにより、適当なWSL2ディストリビューションを作成する。
ここで、インポートするイメージは"cloud"とついているものだと(全てではないようだが)多くのものが初めからcloud-initがインストール済みの状態になっており、オススメ。
もし入っていなければ、後で(詳細は未検証だが)おそらくはaptとかdnfなど適当なパッケージマネージャーでインストールしておけば良いと思われる。

次に作成したディストリビューションを起動する。例えば、

wsl.exe -d <WSL2ディストリビューション名> --cd ~

などとすると作成したディストリビューションに入ることができる。

その後、以下のようなスクリプトを作成し、実行する:

cloud-init.sh
#!/bin/bash

cloud-init init --local
cloud-init init
cloud-init modules --mode=config
cloud-init modules --mode=final
# wsl内のrootユーザーで実行
chmod +x /path/to/cloud-init.sh
/path/to/cloud-init.sh

こうすると、Windows側の%USERPROFILE%\.cloud-init\<ディストリビューション名>.user-dataの内容を元にプロビジョニングが実行される。
(ターミナル上でcloud-initの処理が実行されるのが確認できる)

最後に、wsl2をシャットダウン・再起動すればOK。

(WSL公式のUbuntu-24.04の場合)

https://cloudinit.readthedocs.io/en/latest/tutorial/wsl.html

にWSL公式版のUbuntu-24.04版での実行例が記述されているが、ここではwsl2でのcloud-initの実行で記載されている手順は書かれておらず、実際、%USERPROFILE%\.cloud-init\<ディストリビューション名>.user-dataを置いておきさえすれば、初回起動時に勝手にcloud-initが実行される。
すなわち、手順が減ってより楽にプロビジョニングの実行ができて便利である。

WSL公式版のUbuntu-24.04、というのはMicrosoft Storeからインストールしたもの(おそらく、cliでwsl --installでいれたUbuntuでも良いはず)、
および、Ubuntu image server:

https://cloud-images.ubuntu.com/wsl/

noble以下に置いてあるubuntu-noble-wsl-amd64-ubuntu24.04lts.rootfs.tar.gzを使って、

wsl.exe --import <wsl2ディストリビューション名> <インストールパス> <↑でダウンロードしたrootfs.tar.gzファイル>

のようにして作成したもの、のいずれかが該当する。

そのため、24.04以降のUbuntu LTS版を用途ごとに複数立ち上げたい、といった場合であれば、↑のUbuntu image serverで公開されているイメージを使ってwsl --importする方が便利かもしれない。

(ToDo)deprecatedなコマンドの移行

https://cloudinit.readthedocs.io/en/latest/reference/cli.html#single

によると、cloud-init initおよびcloud-init modulesの両コマンドはdeprecated扱いとなっており、将来的に動かなくなる可能性がある。
そのため、将来的にはこの記事で紹介した内容はアップデートを行う必要がでてくると思われる。
(修正方法は未調査)

参考

(検証環境)

  • Windows11(x86_64)
    • バージョン23H2 (OSビルド22631.4460)
  • wslバージョン:
wsl --version
WSL バージョン: 2.3.26.0
カーネル バージョン: 5.15.167.4-1
WSLg バージョン: 1.0.65
MSRDC バージョン: 1.2.5620
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26100.1-240331-1435.ge-release
Windows バージョン: 10.0.22631.4460

参考1 昔書いた記事(Dockerfileを使うやり方)

https://zenn.dev/junkor/articles/e2b8d7815bd44a

Dockerfileを使ってイメージ内容を自由にカスタマイズできる、という記事。
極めて高い自由度がメリットだが、一方で、Dockerで使われるベースイメージは一般にごく最低限のパッケージしか入っていないため、WSL2のような開発や普段使い?するためには色々と不足や差分があり、カスタマイズ(Dockerfileの記入)が大変なところがあった。
(あと、docker exportなどを行うのが面倒)

images.linuxcontainers.org で公開されているイメージはそのままwsl --importすることができ、
dockerイメージよりは最低限使いそうなパッケージが入っていることが多そう?なので、より手軽に色々なディストリビューションを導入できると思われる。

参考2 distod

https://github.com/nullpo-head/wsl-distrod

WSL2でsystemdを使えるようにする他、
WSL2にlinuxcontainers.orgで入手できるあらゆるイメージをWSL2にインストールできるツールらしい。
(まだwsl2で満足にsystemdが使えなかったときに、systemdを使う手段として使われていた気がする。)

前者の機能のためにこのツールを存在を知ったが、今回の記事の内容は後者の方の機能に着想を得ている。

(その他参考リンク)

https://zenn.dev/s_ryuuki/articles/46c6d9d8d34404

https://qiita.com/yo-yamada/items/ed44bc72260ad5787d84

https://cloudinit.readthedocs.io/en/latest/reference/cli.html

GitHubで編集を提案

Discussion