イメージのバージョンを固定しようとして compose ファイルを探したら、 参照先のディレクトリごと存在しなかった。コンテナは1ヶ月動き続けていた。 消したら二度と同じ構成に戻せない状態だった。
コンテナには、どの compose ファイルから作られたかがラベルで残っている。
$ docker inspect jellyfin --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}'
/data/compose/1/docker-compose.yml
この /data/compose/<id>/ は管理 UI のボリュームの中にある。見に行ったら、
$ docker run --rm -v portainer_data:/d:ro alpine ls /d/compose/
12 14 3 4 9 ← 1 が無い
スタックを UI から削除したときにファイルだけ消え、コンテナは残ったのだと思う。 動いているので誰も気づかない。
docker inspect は必要な情報を全部持っている。まとめて出す。
docker inspect <name> --format '
image : {{.Config.Image}}
network : {{.HostConfig.NetworkMode}}
restart : {{.HostConfig.RestartPolicy.Name}}
user : {{.Config.User}}
runtime : {{.HostConfig.Runtime}}
entrypoint : {{json .Config.Entrypoint}}
cmd : {{json .Config.Cmd}}
--- mounts ---{{range .Mounts}}
{{.Type}} {{if .Name}}{{.Name}}{{else}}{{.Source}}{{end}} -> {{.Destination}} rw={{.RW}}{{end}}
--- env ---{{range .Config.Env}}
{{.}}{{end}}'
これを見ながら書き起こす。今回の例だとこうなった。
services:
jellyfin:
image: jellyfin/jellyfin:10.11.11
container_name: jellyfin
restart: unless-stopped
user: "1000:1000"
network_mode: host
runtime: nvidia # ハードウェアトランスコード用
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
volumes:
- ~/media:/media
- ~/jellyfin/cache:/cache
- ~/jellyfin/config:/config
.Config.Env にはイメージが元から持っている環境変数も全部混ざる。
そのまま compose に書き写すと大量のノイズになる。
PATH=... ← イメージ由来。書かない
LANG=en_US.UTF-8 ← イメージ由来。書かない
JELLYFIN_DATA_DIR=/config ← イメージ由来。書かない
NVIDIA_VISIBLE_DEVICES=all ← これは自分で指定したもの。書く
判別は docker image inspect <image> --format '{{json .Config.Env}}' と
突き合わせる。差分が自分で足したもの。
$ docker compose -p jellyfin -f ~/homelab/jellyfin/docker-compose.yml up -d
$ docker ps --filter name=jellyfin
jellyfin jellyfin/jellyfin:10.11.11 Up 10 seconds (healthy)
設定が bind mount にあるなら、作り直してもデータは失われない。 バージョンと healthy、それとアプリ側の状態(ライブラリが見えるか等)まで確認する。
-p <プロジェクト名> を間違えると、
名前付きボリュームの前置が変わって別のボリュームを掴む。
データが空になったように見える。既存の値を確認してから合わせる。
$ docker inspect <name> --format '{{index .Config.Labels "com.docker.compose.project"}}'
同じことが他にも起きていないか、一度は見ておく価値がある。
for c in $(docker ps --format '{{.Names}}'); do
f=$(docker inspect "$c" --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}')
[ -n "$f" ] && echo "$c: $f"
done
出てきたパスが管理 UI のボリュームの中なら、その中身が実在するかを確かめる。 ホスト上のパスなら、そのファイルがあるか確かめる。