librelad 0a6ea95b08 Scope app container operations by compose project, not name substring
`docker ps -f name=<app>` is a SUBSTRING match, and instance slugs are
<type>_<id> — so the base app's name is a prefix of every instance of it.
`name=bookstack` also selected bookstack_home, bookstack_test and their -db
containers, which meant start, stop, restart and remove all silently operated on
every instance of an app instead of the one named.

Worst of the four is remove: `libreportal app remove bookstack` ran `docker rm`
against its instances' containers too. Multi-instance made this reachable — the
naming scheme it introduced is exactly what turns the base name into a prefix.

Each app and instance is already its own compose project, named for its
directory, so the project label addresses exactly the containers belonging to
that app. app_install.sh's own post-install check already used this label; the
lifecycle operations did not.

Found while tracing the IP allocation problem: bookstack_work had vanished, and
checking how uninstall selects containers turned this up. To be clear about
attribution — this bug does NOT explain that disappearance. The log shows an
explicit uninstall of bookstack_work, including its own install folder and log,
which container-level over-matching cannot do. I could not attribute that
removal to a specific command and am not going to guess; the instance has been
recreated.

Verified: with the fix, `libreportal app stop bookstack` stops bookstack and
bookstack-db and leaves bookstack_home and bookstack_test running. Before it,
all six went down. All four Bookstack apps and Stoat serve 200 afterwards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 01:41:41 +01:00
..