🐳

WSLにAlpineを入れDockerの永続化ファイルをBtrfsで圧縮

に公開

概要

WSLはネットワークを共有しているのでDocker用のWSLを起動しておけば他のVMからコンテナを共有して使えることに気付いたのでDocker専用のVMを軽量なAlpine上に建てて共有するようにしました。

またDockerの永続化ファイルが大量にありディスク領域を圧迫していたのでDockerからマウントする領域はBtrfsで透過圧縮して管理するようにしました。

その時の備忘録を残します。

AlpineでDockerを入れる

以下から「Mini root filesystem」のイメージを入手

https://alpinelinux.org/downloads/

D:\WSL\dockerにdockerという名前でインポート

> wsl --import docker D:\WSL\docker alpine-minirootfs-3.22.2-x86_64.tar.gz

wsl起動

> wsl -d docker

ホスト名を設定

cat << EOF > /etc/wsl.conf
[network]
hostname=docker
EOF

パッケージ更新

apk update
apk upgrade

ログインシェルをbashに変更

apk add bash bash-completion shadow
usermod -s /bin/bash root

タイムゾーンを日本に設定

apk add tzdata
install -Dm 644 /usr/share/zoneinfo/Asia/Tokyo /etc/zoneinfo/Asia/Tokyo
echo "export TZ='Asia/Tokyo'" >> /etc/profile.d/timezone.sh
bash -l -c 'date' # JSTになってるか確認
apk del tzdata

docker関連インストール

apk add openrc docker docker-cli-compose

ネットワークをWSLに任せているので/etc/init.d/dockerの依存関係からnetを削除

 depend() {
-	need sysfs cgroups net
+	need sysfs cgroups
 	after firewall
 }

/etc/wsl.confで起動時にinitを起動するように設定

cat << EOF >> /etc/wsl.conf

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

WSLを再起動

wsl -t docker
wsl -d docker

docker手動サービス起動

rc-service docker start

Hello Worldで動作確認

docker container run --rm hello-world

Dockerサービスを自動起動するように設定

rc-update add docker default

WSLを再起動してdockerコマンドが動作すればDockerの準備はOK

ローカル開発用なんでセキュリティは二の次です意識高い人はRootless化とかしたらいいと思う

コンテナのボリューム領域に使うディレクトリをbtrfsで圧縮

現状、DBが複数必要だったりするので永続化ファイルだけで数十GBとかになってディスクが足りなくなったのでボリュームマウントする領域をbtrfsでzstd圧縮するようにしました。
遅くなるので容量に余裕がある人は不要です。

64GBの事前割当領域を確保

fallocate -l 64G /mnt/.btrfs.img

btrfsファイルシステムを作成

apk add btrfs-progs btrfs-compsize
mkfs.btrfs -f /mnt/.btrfs.img

ループバックデバイスに割り当てる

sudo losetup -f /mnt/.btrfs.img && losetup -a

マウント先の作成

mkdir /root/docker

お試しでマウント

mount -o loop,noatime,compress=zstd /dev/loop0 /root/docker

圧縮されるか確認

dd if=/dev/zero of=/root/docker/200MB_file bs=1M count=200 # 200MBのテストファイル作成
compsize /root/docker # Disk Usageで何MBに圧縮されたかわかる

WSLでfstabを有効化

cat << EOF >> /etc/wsl.conf

[automount]
mountFsTab=true
EOF

fstabで自動的にマウントされるようにする

cat << EOF >> /etc/fstab
/mnt/.btrfs.img /root/docker btrfs loop,defaults,noatime,compress=zstd 0 0
EOF

再起動して自動的にマウントされるか確認

mount | grep /root/docker

IPを割り当てたDockerコンテナに別のWSLから疎通出来るか確認

テスト用のDockerファイルの作成場所を作る

mkdir /root/docker/test;cd $_

とりあえずping応答返す為だけのコンテナのcomposeファイル作成

cat << EOF > compose.yml
networks:
  local_network:
    ipam:
      driver: default
      config:
        - subnet: 200.200.200.0/24
services:
  alpine:
    image: alpine
    container_name: alpine
    command: tail -f /dev/null
    restart: unless-stopped
    networks:
      local_network:
        ipv4_address: 200.200.200.100
EOF

起動する

docker-compose up -d

テスト用に別のWSLを用意

wsl --import test D:\WSL\test alpine-minirootfs-3.22.2-x86_64.tar.gz

テスト用のWSLからコンテナにPingが届くか確認

wsl -d test ping 200.200.200.100

確認が終わったらテスト用のWSLは削除

wsl --unregister test

これで他のWSLと共有して使えるDocker専用のWSLが完成しました

メンテナンス

btrfsは断片化すると遅くなるので体感でわかる位劣化したら以下でデフラグする

btrfs filesystem defragment -r /root/docker

たまにエラーが無いかもチェック

btrfs scrub start /root/docker
watch btrfs scrub status $_

実際のところ

現状複数のPostgresコンテナを立てているのでディスク領域を20G位利用するのだが
btrfsでの圧縮のおかげで実際の使用量は4GBまで圧縮されている
コンテナの永続化ファイルがRAWファイルだとかなり圧縮が効くので用途が合えばかなり便利に使えると思う

Discussion