mutmut
August 9, 2026, 8:50am
1
Hello,
With all these great new external integrations and their regular updates, I just realized that the old images were still present on my storage:
Would it be possible to have the same update process as Gladys, meaning that Watchtower does the update and cleanup?
Or another system to automatically reclaim space every night?
Same when you delete an integration (e.g. for me:
freebox tested but not usable because it’s not the right Freebox).
For info, I recovered an average of 10x160MB, so 1.6GB, and I don’t have many integrations (for now ).
Hi @mutmut ,
I had the same issue as you when using Portainer (https://www.portainer.io/ ) as a container manager (sufficient for everyday use, at least). I discovered Dockhand (https://dockhand.pro/ ) thanks to the IT-Connect website (https://www.it-connect.fr/ ), and it offers the advantage, via one of the options (« prune containers »), whose execution can be scheduled, to perform automated cleanups and updates.
I hope this can help
Have a great day,
Jean
I use Arcane, but we need something directly integrated into Gladys to clean images easily
mutmut
August 10, 2026, 10:59am
4
Thanks to both of you, I do know dockhand which I also have, but I’m less of a fan of arcane.
These are solutions (along with portainer) where you have to « tinker » and therefore an integrated automatic tool in Gladys would be necessary for the average person.
I moved the topic to feature requests because it’s good feedback
This is developed here:
master ← claude/integration-nettoyage-images-aqunuy
ouvert 10:48AM - 10 Aug 26 UTC
### Description
Every integration image Gladys pulls stays on the disk forever:… `update` pulls the new image and leaves the previous one, `uninstall` removes the container, the private network, the data folder and the `t_service` row but never the image. Gladys' own upgrade runs Watchtower with `--cleanup`, so the core leaves nothing behind — external integrations were the asymmetry, and users on the forum report reclaiming gigabytes by deleting the images by hand.
**Why not a `prune`.** The manifest requires an explicit tag and integrations ship versioned ones, so the image an update supersedes keeps its tag: it is never *dangling*, and `docker image prune` does not see it. Only `prune -a` would — and Gladys usually shares its Docker daemon with the rest of the user's containers, so sweeping images it does not own is not an option. Gladys knows exactly which images it pulled and which it still needs, so cleanup is done by reference, not by sweeping.
**Two mechanisms**, both best-effort: a cleanup failure is logged, never raised, and never turns a successful update or uninstall into a failed one.
- **Targeted removal**, on the lifecycle events that make an image unnecessary. `update` captures the images of the version being replaced (main + declared sub-containers) *before* rewriting the row, and removes them only **once the new containers have actually started** — dropping them earlier would take away the one thing a broken update can fall back on. `uninstall` removes them **after** the `t_service` row is destroyed, so the in-use check no longer counts the integration being removed. An update that keeps a sub-container image, or a re-pull of the same tag (a `:dev` install), leaves the image in use and therefore untouched.
- **Nightly sweep** (3:30 AM, `EVENTS.EXTERNAL_INTEGRATION.CLEAN_IMAGES` → `cleanImages`), which is what gives an already-bloated install its disk back — targeted removal only keeps a fresh install clean. It considers **only images carrying the `io.gladysassistant.manifest` label**, i.e. images built as Gladys integrations, never anything else on the machine. A multi-tag image is a candidate through each of its tags (removing one reference only untags it); an untagged one — a rebuilt `:dev` install — by its id. Sub-container images (a Mosquitto broker, a Frigate) carry no such label and are deliberately out of the sweep's reach: they are third-party images the user may well run elsewhere, and targeted removal already covers them, where the manifest is what tells us they were ours.
**Two guards stand between a candidate and its deletion:** `getImagesInUse` filters out every image still referenced by an installed integration — its own image or one its manifest declares — so a third-party image shared by two integrations survives the uninstall of one of them; and `removeImage` **never forces**, so Docker itself refuses (HTTP 409) to delete an image a container still references, running or stopped. 404 and 409 are both non-events for the caller, distinguished from a real failure by the boolean the call returns.
### Changes
- `server/lib/system/`: new `system.listImages.js` and `system.removeImage.js`.
- `server/lib/external-integration/`: new `getImagesInUse` (the in-use set), `removeImages` (guarded targeted removal) and `cleanImages` (the labelled sweep); `update` and `uninstall` now call the cleanup.
- `server/config/scheduler-jobs.js`: `daily-cleanup-of-unused-integration-images` at 3:30 AM.
- `docs/specs/external-integrations.md`: new section **B.19 Docker image cleanup** (same diff, as required by the spec-first process).
### Forum
Forum: https://community.gladysassistant.com/t/integration-externe-nettoyage-des-vielles-images/10501
### Checklist
- [x] Tests pass: `cd server && npm run coverage` (Codecov requires 100% coverage on changed lines) and Cypress (`npm run cypress:run`) if the UI changed
- [x] Linter and prettier pass on both front and server (`npm run eslint`, `npm run prettier`)
- [x] No undocumented breaking change
Coverage of every file touched is 100% (statements / branches / functions / lines), via 25 new tests in `system.listImages.test.js`, `system.removeImage.test.js` and `externalIntegration.imageCleanup.test.js`, plus 5 added to the existing `update` / `uninstall` suites. No front change, so no Cypress run.
Note: 23 tests fail identically on a clean `master` checkout in this environment (15 in `store.test.js`, 8 in `gateway.backup`) — outbound-HTTP related, unrelated to this diff.
---
_Generated by [Claude Code](https://claude.ai/code/session_012zFg1ZJerC7KcgxrkApuri)_
## Summary by CodeRabbit
* **New Features**
* External integration images are cleaned up automatically after updates and uninstallations.
* A nightly cleanup removes unused integration images while preserving images still in use.
* Recently pulled images are protected for one hour before cleanup.
* Cleanup safely handles missing, shared, or unavailable images without interrupting normal operations.
* Image cleanup is targeted and does not perform global Docker pruning.
* **Tests**
* Added comprehensive coverage for image discovery, preservation, removal, update cleanup, uninstall cleanup, and failure handling.
This will be live in the next version of Gladys!
I’m closing this post as the feature is available in Gladys Assistant 4.86:
Hi everyone!
Super excited to release Gladys Assistant 4.86.
It’s simple, it’s the biggest version since the start of the project, with 68 PRs merged in one week
It’s just incredible, and it shows the new pace we can keep with AI.
The goal is now clear: catch up with and surpass Home Assistant
I’ll talk about these 68 new features here:
Thanks to all the contributors!!