feat: configurable unused images threshold with dashboard warning

- Add image_prune_threshold_mb setting (default 1024 MB)
- Add GET /api/docker/unused-images endpoint returning unused image count, size, and threshold status
- Dashboard shows amber warning banner when unused project images exceed threshold
- Banner links to settings page for pruning, shows count and human-readable size (MB/GB)
- Threshold configurable in Docker Image Cleanup section of settings
- DB migration + schema for image_prune_threshold_mb
This commit is contained in:
2026-04-05 14:34:48 +03:00
parent 0ddad87a9a
commit b0816502bf
12 changed files with 137 additions and 2 deletions
+24
View File
@@ -11,6 +11,9 @@
let projects = $state<Project[]>([]);
let instancesByProject = $state<Record<string, Instance[]>>({});
let staleContainers = $state<StaleContainer[]>([]);
let unusedImagesMB = $state(0);
let unusedImagesCount = $state(0);
let unusedImagesExceeded = $state(false);
let loading = $state(true);
let error = $state('');
@@ -43,6 +46,13 @@
}
instancesByProject = mapped;
staleContainers = staleResult;
try {
const imgStats = await api.getUnusedImageStats();
unusedImagesMB = imgStats.total_size_mb;
unusedImagesCount = imgStats.count;
unusedImagesExceeded = imgStats.exceeded;
} catch { /* non-critical */ }
} catch (e) {
error = e instanceof Error ? e.message : $t('dashboard.loadFailed');
} finally {
@@ -125,6 +135,20 @@
</a>
</div>
<!-- Unused images warning -->
{#if unusedImagesExceeded}
<a href="/settings" class="flex items-center gap-3 rounded-xl border border-amber-300 bg-amber-50 dark:border-amber-700 dark:bg-amber-950/30 p-4 transition-colors hover:bg-amber-100 dark:hover:bg-amber-950/50">
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-amber-100 dark:bg-amber-900/50 text-amber-600">
<IconAlert size={20} />
</div>
<div class="flex-1">
<p class="text-sm font-medium text-amber-800 dark:text-amber-300">{$t('dashboard.unusedImagesWarning')}</p>
<p class="text-xs text-amber-700 dark:text-amber-400">{unusedImagesCount} {$t('dashboard.unusedImages')} &middot; {unusedImagesMB >= 1024 ? (unusedImagesMB / 1024).toFixed(1) + ' GB' : unusedImagesMB + ' MB'}</p>
</div>
<span class="text-xs font-medium text-amber-600 dark:text-amber-400">{$t('settings.pruneImages')} &rarr;</span>
</a>
{/if}
<!-- System health summary -->
<SystemHealthCard />