Nightly Build / build (push) Successful in 7m32s
The per-user container shipped python+node and little else, so an agent asking for `unzip`, `ffprobe` or even `ps` found nothing and had to `sudo apt-get install` mid-task. That fallback works, but it re-runs on **every container recreate**, inside the task, where it costs latency and can fail — while the image is **one, shared by every container**, so preinstalling costs its size once for the whole box. Anything an agent reaches for repeatedly is therefore cheaper baked in. Added on that rule: jq, ripgrep, zip/unzip, xz-utils, sqlite3, wget, openssh-client, procps, less, file, tzdata, dnsutils, iputils-ping, ffmpeg (+ffprobe), imagemagick, poppler-utils and tesseract — with the ita/fra language packs, matching the app's supported UI locales (eng and osd arrive as hard deps). Deliberately left out: build-essential/python3-dev (~270 MB, only for a pip package with no wheel) and pandoc (~216 MB) are big *and* self-recoverable, so they stay on demand. 687 MB -> 1.3 GB, ffmpeg being most of it. The image tag goes v2 -> v3, which alone would have equipped nobody: a container pins the image it was created from, so `ensure()` would have rebuilt v3 and then happily reused every existing v2 container — the new tools would have reached only users created from here on. `reusable()` now compares `.Config.Image` too, turning a tag bump into a recreate, safe for the same reason the `--user`/`--init` self-heal already is: the container holds no durable state, everything lives in the bind mounts. An unreadable inspect answers true, so a docker hiccup never churns a working container. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>