homelab notes ポート開放できない家の自宅サーバー

Docker の名前とサイズは素直ではない

ボリューム名を1文字間違えると、エラーではなく空のボリュームが新規作成される。 イメージのサイズは表示するコマンドによって3通りの数字が出る。 どちらも同じ日に踏んだ。

ボリューム名を間違えると黙って新しいものが作られる

バックアップ対象の容量を測ろうとして、こう書いた。

$ docker run --rm -v ollama_data:/d:ro alpine du -sh /d
4.0K    /d

13GB あるはずのモデルが 4KB。中身が消えたのかと思ったが、そうではなかった。

-v <名前>:/path は、その名前のボリュームが無ければ新規作成する。 「そんなボリュームは無い」とは言ってくれない。 測ったつもりで、空のボリュームを作ってその中身を測っていた。

正しい名前は ollama_ollama_data だった。 compose で作られたボリュームにはプロジェクト名が前置される

volumes:
  ollama_data:          # compose ファイルでの書き方
                        # 実体は <プロジェクト名>_ollama_data

推測せず、コンテナに聞くのが確実。

$ docker inspect ollama --format '{{range .Mounts}}{{.Name}} -> {{.Destination}}{{end}}'
ollama_ollama_data -> /root/.ollama

同じミスを2回やった。1回目は4つまとめて空ボリュームを作った。 docker volume ls -f dangling=true に身に覚えのないものが並んでいたら、これを疑う。

イメージのサイズが3通り出る

ローカル LLM のイメージが大きいので調べたら、数字が食い違った。

コマンド数字意味
docker images8.35GBcontainerd スナップショットの実占有
docker history の合計5.01GB展開後のレイヤー合計(コンテナ内の du と一致)
docker image inspect .Size3.34GB圧縮済みレイヤー合計 ≒ 実ダウンロード量

原因は containerd スナップショッター(overlayfs)を使っていること。 docker images の表示が展開後より大きく出る。

$ docker info | grep -iE 'storage driver|snapshotter'
 Storage Driver: overlayfs
  driver-type: io.containerd.snapshotter.v1
「ダウンロードにどれくらいかかるか」を知りたいなら inspect .Size docker images の数字で見積もると2倍以上ずれる。 実際、8.35GB だと思って身構えたら 3.3GB だった(それでも回線が細いと30分かかる)。

何がそんなに大きいのか

中身を見ると理由がはっきりする。

$ docker run --rm --entrypoint sh <image> -c 'du -sh /usr/lib/ollama/*' | sort -rh
2.2G    /usr/lib/ollama/mlx_cuda_v13
1.2G    /usr/lib/ollama/cuda_v12
807M    /usr/lib/ollama/cuda_v13
49M     /usr/lib/ollama/vulkan
        + CPU 命令セット別ビルド 14種(haswell / skylakex / zen4 / …)

「どのマシンでも動く」ために GPU バックエンドを全部同梱している。 実際に使うのは1つだけで、残りは死に荷物。とはいえイメージ側では削れないので、 容量に余裕がないマシンでは覚悟しておく。

おまけ: 消してはいけないイメージ

docker image prune -a は使わない。 常駐していないがスクリプトが都度 docker run するイメージalpinerestic/restic など)まで消える。 次にバックアップが走るとき、静かに再ダウンロードが始まる。 消すときはイメージ名を明示する。