WSLにAlpineを入れDockerの永続化ファイルをBtrfsで圧縮
概要
WSLはネットワークを共有しているのでDocker用のWSLを起動しておけば他のVMからコンテナを共有して使えることに気付いたのでDocker専用のVMを軽量なAlpine上に建てて共有するようにしました。
またDockerの永続化ファイルが大量にありディスク領域を圧迫していたのでDockerからマウントする領域はBtrfsで透過圧縮して管理するようにしました。
その時の備忘録を残します。
AlpineでDockerを入れる
以下から「Mini root filesystem」のイメージを入手
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