🐧

scratch イメージから作る WSL ディストリビューション

に公開

こんにちは、Fairy Devices の熊谷です。

Windows Subsystem for Linux (WSL) 内の Linux ディストリビューションは、 Microsoft Store を介さずとも、ルートファイルシステムを tar アーカイブ形式でインポートすることで利用できることをご存知でしょうか?
この方法を使うことで、必要最小限のリソースで動作する、軽量でセキュアな WSL 環境を手に入れることもできます。例えば、自社向けにセキュリティ保護された環境[1] を配布することで、一貫したセキュリティレベルでの管理が実現できたりします。

この記事では、以下の Microsoft のドキュメントを参考に、Docker の scratch イメージから WSL 用のカスタムディストリビューションを構築する手順を解説します。

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

scratch とは?

全ての Dockerfile は UbuntuAlpine のようなベースイメージから作成されます。
これらのディストリビューションにはシェルやパッケージマネージャー、各種ライブラリなどが含まれており、ユーザーが使いやすいように必要なものをまとめて提供しています。
一方で scratch は明示的に何も含まれておらず、超最低限のイメージを作るのに適しています。
アプリケーションの実行に必要なコンポーネントに限定することで、軽量かつセキュアなイメージを作成するのに向いています。

scratch をベースに作成したイメージは、Docker コンテナとしてだけでなく、WSL でも動かすことができます

この記事のゴール

この記事では、cowsay ライクなコマンドである Ferris Says を実行するカスタムディストリビューションの作成を目指します。

https://github.com/rust-lang/ferris-says

Docker の scratch イメージから WSL カスタムディストリビューションを作成する流れは以下の通りです。

  1. Docker イメージの作成: Dockerfile を使って、scratch イメージをベースに必要最小限のファイル(Ferris Says の実行ファイル、共有ライブラリ、WSL 設定ファイル)を追加します。
  2. rootfs をエクスポート: 構築した Docker イメージから rootfs を tar アーカイブ形式でエクスポートします。
  3. WSL へインストール: エクスポートした tar アーカイブを WSL にインストールし、新しいカスタムディストリビューションとして登録します。

1. Docker イメージの作成

マルチステージビルドを利用して必要なファイルを集めて、実行環境へコピーします。

Ferris Says は cargo install でインストールします。
インストールされた fsays コマンドの依存ライブラリを ldd コマンドで調べ、これらも実行環境へコピーします。

$ ldd /usr/local/cargo/bin/fsays
        linux-vdso.so.1 (0x00007ffddf355000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007bf53a200000)
        /lib64/ld-linux-x86-64.so.2 (0x00007bf53a8cc000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007bf53a5d2000)

次に、WSL 構成ファイルを用意します。前述したドキュメントによると以下の 2 ファイル要るようです。

  • /etc/wsl-distribution.conf: WSL を使用して初めて起動したときに Linux ディストリビューションを構成する方法を制御するディストリビューション 保守管理者によって作成されたファイル。
  • /etc/wsl.conf: ユーザーに固有のグローバル システム設定を含み、ディストリビューションの起動方法を制御するファイル。

WSL 配布構成ファイル

ここでは、ディストリビューション名を設定するのが主な目的です。
シェルすらない環境のため、Windows Terminal のプロファイルに追加されないように不要な設定は無効にします。

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

wsl-distribution.conf
[oobe]
defaultName = ferris-says

[shortcut]
enabled = false

[windowsterminal]
enabled = false

WSL 構成ファイル

wsl.conf ファイルは、ディストリビューションごとに設定を構成します。
これらの設定はデフォルトでは true ですが、この記事では不要なため false に変更します。

https://learn.microsoft.com/ja-jp/windows/wsl/wsl-config#what-is-the-difference-between-wslconf-and-wslconfig

wsl.conf
[boot]
systemd = false

[automount]
enabled = false
mountFsTab = false

[network]
generateHosts = false
generateResolvConf = false

[interop]
enabled = false
appendWindowsPath = false

Dockerfile

一連の処理をまとめた Dockerfile が以下です。

Dockerfile
################################################################################
## Ferris Says ビルド用
FROM rust:latest AS builder

## Ferris Says のバイナリをインストール -> /usr/local/cargo/bin/fsays
RUN cargo install fsays

################################################################################
## 依存パッケージダウンロード用
FROM ubuntu:24.04 AS base

## 依存ライブラリのパッケージを明示的にインストール
RUN apt-get update && apt-get install -y --no-install-recommends \
    libc6     \
    libgcc-s1 \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

## プロセス生成時に使用される passwd を作成
RUN echo "root:x:0:0::/:" > /tmp/passwd

################################################################################
## 実行環境
FROM scratch

## fsays
COPY --from=builder /usr/local/cargo/bin/fsays /usr/bin/fsays

## 依存ライブラリ(ld, libc, libgcc_s)
COPY --from=base /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
COPY --from=base /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=base /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6
COPY --from=base /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libgcc_s.so.1

## WSL settings
COPY ./wsl.conf /etc/wsl.conf
COPY ./wsl-distribution.conf /etc/wsl-distribution.conf
COPY --from=base /tmp/passwd /etc/passwd

これらのファイル(Dockerfile, wsl.conf, wsl-distribution.conf)を用意し、以下のコマンドで Docker イメージをビルドします。

$ docker image build -t ferris-says .

$ docker image ls ferris-says
REPOSITORY    TAG       IMAGE ID       CREATED      SIZE
ferris-says   latest    cc80e003fe40   2 days ago   6.26MB

2. rootfs をエクスポート

ビルドした Docker イメージから、WSL で利用できる tar アーカイブ形式の rootfs をエクスポートします。

$ docker container create -t --name wsl_export ferris-says fsays
$ docker container export wsl_export | gzip > ferris-says.wsl
$ docker container rm wsl_export

これで ferris-says.wsl というファイルが作成されます。

……おや? 拡張子が .wsl になっていますね。
これは、実体は .tar.gz ですが、名前だけ変えています。
こうすることで、Windows がこのファイルを WSL ディストリビューションとして認識し、エクスプローラーからダブルクリックするだけでインストールしてくれるようになります。

3. WSL へインストール

最後に、作成した tar アーカイブを WSL にディストリビューションとしてインストールします。
前のセクションで説明したように、.wsl 拡張子のファイルをダブルクリックしてインストールすることも可能ですが、ここではコマンドによるインストール例を示します。
PowerShell またはコマンドプロンプトを開き、以下のコマンドを実行します。

> wsl.exe --install --from-file ferris-says.wsl --no-launch

これで、ferris-says という名前の新しいディストリビューションが登録されました!
wsl.exe --list でインストールされているディストリビューションの一覧を確認できます。

カスタムディストリビューションの起動

インストールが完了したら、以下のコマンドで新しいカスタムディストリビューションを起動してみましょう。
--distribution, -d オプションでディストリビューションを指定します。
--exec, -e オプションは、既定のシェルを使用せずに指定されたコマンドを直接実行します。

> wsl.exe -d ferris-says -e fsays "タラバガニはヤドカリの仲間"
 ____________________________
< タラバガニはヤドカリの仲間 >
 ----------------------------
        \
         \
            _~^~^~_
        \) /  o o  \ (/
          '_   -   _'
          / '-----' \

おわりに

本記事では、Docker の scratch イメージから WSL カスタムディストリビューションを構築する基本的な手順を解説しました。

この環境はとても最小限であり、シェルやパッケージマネージャーは含まれていません。
しかし、用途によっては、パッケージマネージャーを導入したり、特定の開発環境に特化したツールを追加したりして、さらにカスタマイズを進めるのも良いでしょう。
あなただけのカスタムディストリビューションを作ってみてはいかがでしょうか。

脚注
  1. https://learn.microsoft.com/ja-jp/windows/wsl/enterprise ↩︎

  2. https://learn.microsoft.com/ja-jp/windows/wsl/build-custom-distro#configuration-file-recommendations ↩︎

  3. https://github.com/microsoft/WSL ↩︎

フェアリーデバイセズ公式

Discussion