📝

今更ながら WSL2 の Alpine で Docker 環境構築

2022/06/23に公開
1

Windows 11 Pro (21H2) で作業した備忘録になります.所々おかしなところがあるかもしれません.

WSL2 の環境構築

1. WSL2 のインストール

試していないのですが,wsl --install で環境構築ができるようですが,個人的にイメージの保存場所が好ましくないので,Manual installation steps for older versions of WSL | Microsoft Docs の手順で行います.

  1. Win+x」 のショートカットキーで表示されるメニューから設定をクリックします.
  2. 「アプリ」→「オプション機能」→「Windows のその他の機能」から Windows の機能 を開きます.
  3. Linux 用 Windows サブシステム」,「仮想マシン プラットフォーム」にチェックを入れて, OK をクリックします.再起動を促されるので指示に従います.
  4. 管理者権限PowerShell を開き,wsl --updateカーネルをインストールします.
  5. wsl --status で状態を確認します.既定のバージョンが 2 になっていないときは,wsl --set-default-version 2 で変更します.
wsl-status
既定の配布: Ubuntu
既定のバージョン: 2

Linux 用 Windows サブシステムの最終更新日: 2022/03/28
WSL の自動更新が有効になっています。

カーネル バージョン: 5.10.102.1

2. Alpine Linux のインストール

  1. downloads | Alpine Linux から alpine-minirootfs-3.16.0-x86_64.tar.gz をダウンロードして,D:\wsl\distors に保存する.

  2. 'Windows Terminal' を起動して.PowerShell を立ち上げます.

プロンプト(PS D:\wsl\distors>)は省略しています.

cd D:\wsl\distors
wsl --import Alpine D:\wsl\Alpine .\alpine-minirootfs-3.16.0-x86_64.tar.gz
wsl -l -v           # Alpine が表示
wsl -d Alpine       # Alpine の実行
exit                # exit で シェルを終了して,Alpine 環境から抜ける
wsl -t Alpine       # Alpine を終了
  1. Windows Terminal を再起動すると,メニューに Alpine が追加されるので,そこから Alpine を起動する.
プロキシ環境

apk は --no-cache を付けて,容量を削減します.

echo $SHELL # シェルの確認 (ash が使用されています)

# システムの更新
apk update
apk upgrade --no-cache

# 必要そうなパッケージのインストール
apk add --no-cache tzdata sudo curl git
apk info # インストールされたパッケージを確認

# タイムゾーンの設定
install -Dm 644 /usr/share/zoneinfo/Asia/Tokyo /etc/zoneinfo/Asia/Tokyo
export TZ='Asia/Tokyo'
echo "export TZ='$TZ'" >> /etc/profile.d/timezone.sh
apk del tzdata

# sudo の設定
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel

# 作業ユーザ=の追加,bash を使用
apk add --no-cache bash bash-completion
adduser ignorant -s /bin/bash # ignorant はユーザ名,適宜変更
adduser ignorant wheel        # ignorant はユーザ名,適宜変更
 
# docker 関連のインストール
apk add --no-cache docker openrc
addgroup ignorant docker      # ignorant はユーザ名,適宜変更

# wsl.conf の設定
cat <<EOF > /etc/wsl.conf
[user]
default=ignorant

[interop]
appendWindowsPath=false

[boot]
command = "/usr/bin/env -i /usr/bin/unshare --pid --mount-proc --fork --propagation private -- sh -c 'exec /sbin/init'"
EOF

# シェルの終了
exit

PowerShell から wsl -t Alpine と入力して,Alpine を終了します.
Windows Terminal から Alpine を起動して,作成したユーザーになっているのを確認します.

3. OpenRC,Docker の設定

WSL2 init: emerging OpenRC :: ~/wsl.dev — Get your Linux On を参考にしています.wsl.conf[boot] の設定もここからです.

  1. Docker の動作確認
# root ユーザになる
sudo -i # (sudo su -) 

# docker の起動
rc-service docker start
rc-status

# runlevel default に登録
rc-update add docker default
rc-update show default

# 不要な仮想コンソールを減らす
vi /etc/inittab # tty3 から tty6 をコメントアウト

# root から抜ける
exit
# シェルの終了
exit

PowerShell から wsl -t Alpine と入力して,Alpine を終了します.
Windows Terminal から Alpine を起動します.

このままでも,docker container run --rm hello-world は動作しましたが,/sbin/initPID 1 で起動します.
上記サイトのスクリプトだと正常に動作しなかったので,少し変更しています(Alpine なので).

sudo -i # root ユーザになる
echo '%wheel ALL=(ALL) NOPASSWD: /usr/bin/nsenter' >> /etc/sudoers.d/wheel
vi /etc/profile.d/wsl-init.sh
wsl-init.sh
#!/bin/bash

# Get PID of /sbin/init
sleep 1
pid="$(ps -o pid,args | awk '$2 ~ /\/sbin\/init/ {print $1}')"

# Run WSL service script
if [ "$pid" -ne 1 ]; then
  # Export ENV variables
  if [ "$USER" != "root" ]; then
    [ -f "$HOME/.openrc.env" ] && rm "$HOME/.openrc.env"
    export > "$HOME/.openrc.env"
  fi

  echo "Entering /sbin/init PID: $pid"
  exec sudo /usr/bin/nsenter -p -m -t "${pid}" -- su - "$USER"
fi

# Import ENV variables
if [ -f "$HOME/.openrc.env" ]; then
  set -a
  source "$HOME/.openrc.env"
  set +a
  rm "$HOME/.openrc.env"
fi

PowerShell から wsl -t Alpine と入力して,Alpine を終了します.
Windows Terminal から Alpine を起動して,Docker の動作を確認します.

# /sbin/init の PID が 1 になっているのを確認
ps -ef

# docker のサービスが動作が動作しているのを確認
rc-status

# docker の動作確認
docker info
docker container run --rm hello-world
docker image ls
docker image rm hello-world:latest

ただし,docker info に下記の WARNING が表示されましたが,検索すれば問題ないらしいです.

WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support

気になる方は下記のオプションを追加して,カーネルを再構築します.

.config
-*- Enable the block layer  --->
    [*]   Block layer bio throttling support

PowerShell から wsl -t Alpine と入力して,Alpine を終了します.
現在の状態をすぐに復元できるように保存します.

PowerShell 上で作業します.

cd D:\wsl\sources
wsl --export Alpine Alpine_20220623.tar
プロキシ環境

4. Windows Terminal のアイコンを変更

ペンギンさんばかりだと,視認し辛いので,GitHub - TheFern2/windows-terminal-icons: A sane option for icons for windows terminal profile icons から alpine.png をダウンロードして設定しています.
保存場所はどこでも良いのですが,D:\wsl\Alpine と同じ場所にします.

5. カーネルの再構築

WARNING が気になるので,カーネルを再構築します.使い捨て環境を Ubuntu 22.04 で構築し,そこで作業します.

  1. Downloading distributions から Ubuntu 22.04 LTS をダウンロードします.
  2. Ubuntu2204-220620.AppxBundleUbuntu2204-220620.zip に変更して展開します(私は,面倒くさいので 7zip でそのまま解凍します ).同様に Ubuntu_2204.0.10.0_x64.appx も解凍します.
  3. 解凍した Ubuntu_2204.0.10.0_x64install.tar.gz があるので ubuntu2204-ms.tar.gz に変更して,D:\wsl\distors にコピーします.
  4. wsl --import Jammy D:\wsl\Jammy .\ubuntu2204-ms.tar.gz でインポートします.
  5. Windows Terminal から Jammy を起動します.
# カレントディレクトリを $HOME に移動
cd

# システムのアップデート
apt update; apt upgrade
apt autoremove

# カーネルのビルドの必要なパッケージの取得
apt install build-essential flex bison libssl-dev libelf-dev libncurses5-dev dwarves
# dwarves: (BTF: .tmp_vmlinux.btf: pahole (pahole) is not available)の対処

# カーネルソースの取得
mkdir -p ~/git/src && cd $_
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git

# カーネルの構築
cd WSL2-Linux-Kernel
git tag -l | grep 5.10
uname-r
git switch -d linux-msft-wsl-5.10.102.1 # カーネルのバージョンを合わせる?

export KCONFIG_CONFIG=Microsoft/config-wsl
make menuconfig
make -j$(nproc)
cp ./arch/x86_64/boot/bzImage /mnt/d/wsl/

make menuconfig で下記のオプションを有効にします.

.config
-*- Enable the block layer  --->
    [*]   Block layer bio throttling support

D:\wsl に構築したカーネル bzImage をコピーして, %USERPROFILE%\.wslconfig でカーネルを指定します.

%USERPROFILE% の場所は,おそらく C:\Users\ユーザ名 ですが,エクスプローラーのアドレスバーに %USERPROFILE% と入力するとその場所が開きます.
.wslconfig を下記の内容で作成します.カーネルの場所は適宜変更します.また,\\\ のように重ねます.

.wslconfig
[wsl2]
kernel=D:\\wsl\\bzImage

PowerShell から wsl -t shutdown ですべての仮想マシンを終了します.
Windows Terminal から Alpine を起動して,docker infoWARNING が出ないことを確認します.

# カーネルが更新されているか確認
uname -a -v
# **WARNING** が出ないことを確認
docker info

カーネルをビルドした Jammy は必要ないので,PowerShell から wsl --unregister Jammy で削除します.ただし,フォルダまで削除してくれないので,D:\wsl\Jammy を削除します.

6. さいごに

現在の ext4.vhdx は,358 MB でした.

docker container run --rm hello-world のチェックしかしていないので不具合があるかもしれません. 試して見る方は,ご了承願います.

補足

(2022-06-26) 追記

Tips by Linux distribution にあるように,libgcc,libstdc++ を入れないと VS Code の Remote - Containers でエラーがでます.

sudo apk add --no-cache libgcc libstdc++
  • プロキシ環境の方は sudo -E のように sudo に -E を付けます.
sudo -E apk add --no-cache libgcc libstdc++

Discussion

ignorantignorant

久々に、Alpine を更新したら Docker デーモンが起動しませんでした。

WSL2のAlpine LinuxでDockerを使う - 進捗ダメです によると、2023年7月頃みたいです。

Configure Networking - Alpine Linux にあるように、/etc/network/interfaces

/etc/network/interfaces
auto lo
iface lo inet loopback

を追加して、Alpine を停止(wsl -t Alpine) して、再度 Alpine を立ち上げると無事に、Docker デーモンが起動してくれました。