Files
Anso cfb42af4e0 fix: assorted UI/UX polish fixes (#1670)
* fix(dashboard): replace Stack Health update badge with an icon

The pill badge duplicated space already used by the stack name column.
A CircleArrowUp icon after the name signals an update is available
without competing with the existing ArrowUp/ArrowDown sort indicators
in the same table.

* fix(dashboard): add accessible name to update-available icon

Icon-only indicators need an aria-label directly on the icon; title on
a non-interactive span is not reliably announced by screen readers.

* test(dashboard): cover the update-available icon's accessible name

The icon-only indicator and its aria-label fix had no regression
guard, unlike the equivalent update dot in StackRow.

* refactor(dashboard): compute the update-available label once per row

It was being derived twice (title and aria-label) from the same
row.outdatedServices input.

* fix: drop Community-tier pricing upsells from settings

Community operators no longer see the "See pricing" link in Licensing
or the "Need direct support?" callout in Support. The pricing link now
only shows for an expired paid license needing to renew.

* fix: make Resources images/volumes tables actually scrollable

The tables were wrapped in a Radix ScrollArea sized with max-h-[62vh].
Radix's viewport uses height:100%, which cannot resolve against an
ancestor whose computed height is auto (max-height alone isn't a
definite height), so the viewport silently grew past the visible box
and the extra rows were clipped with no way to reach them. Verified
live: several image rows were permanently unreachable, with no working
internal scrollbar and not enough outer page scroll to compensate.

Switched to an explicit h-[62vh], which the viewport can resolve
correctly, matching every other working ScrollArea in the codebase.
Falls back to h-auto below the md breakpoint so the bespoke mobile
layout keeps shrinking to content and scrolling via the outer page
instead of gaining a fixed-height inner scroll box.

* fix: apply ScrollArea definite-height fix across remaining lists

Radix ScrollArea needs an explicit height, not max-height, or the
viewport collapses and clipped rows become unreachable. Extend the
Resources fix to security, settings, git, and create/import surfaces,
and drop redundant outer wrappers where ModalBody already scrolls.

* fix: migrate Networking tables to Radix ScrollArea

Networks and Findings used native max-h + overflow-auto, which worked
but broke glass scrollbar consistency with Resources and the design
system. Switch them to ScrollArea with a definite height and the same
mobile fallback as the other inventory tables.

* fix: warn Classic bar users that the style is retiring soon

When Appearance Navigation is set to Classic bar, show the same warn
SettingsCallout pattern used for Constrained graphics. Preference is
kept until removal; no alternate style is named in the copy.

* fix: move Channels delivery retries below channel tabs

Put channel configuration first and keep Delivery retries as a shared
footer control under the Discord/Slack/Webhook/Apprise tabs.

* fix: drop redundant More masthead from Smart bar overflow menu

The trigger already reads More, so the dropdown masthead repeated the
same label. Leave titled mastheads on Compact Navigate and Add quick
link menus.

* test: align Smart More E2E with masthead removal

The overflow menu no longer shows a More heading. Assert the menu via
the Logs item and lock that the redundant masthead stays gone.

* fix: consolidate Fleet Map toolbar filters into a single row

Adopt the same retractable search control used on Fleet > Overview and
move the flag filters (missing deps, port conflicts, orphans, shared)
onto the toolbar row right after the Graph/List selector. The node
filter becomes a dropdown instead of individual toggle chips so it
does not clutter the row as fleet size grows.

* fix: move Networking Topology filters onto the search toolbar row

Merge the ownership selector and boolean filter chips (include system,
exposed, drift, missing external, shared) onto the same row as the
stack/network search inputs, matching the Fleet Map toolbar layout.

* fix: default the reclaimable-space banner off

Resources > Docker & Storage's "Show reclaimable-space banner" toggle
now defaults to off instead of on. Also flips the /settings fetch
failure path to fail closed (hide the banner) to match the new
default, instead of failing open.

* fix: raise Compact launcher quick links cap from 5 to 7

* fix: add Discord link to Settings Support Self-serve

Gives users a community chat channel alongside Documentation and
GitHub Issues, using the official Discord mark since lucide-react
has no brand icon for it.

* fix: stop container NET I/O metric row height jump

Give NET I/O more column share than CPU/MEM and keep metric
values on one line with truncate so three-digit rates cannot
grow the strip.

* fix: elevate Doctor tab between Activity and Drift

Make Compose Doctor easier to find in the anatomy strip by placing
it with the ops judgment cluster, ahead of Dossier and inventory tabs.
2026-07-26 03:25:07 -04:00

166 lines
12 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Resources Hub
description: Browse, filter, scan, and clean up Docker images, volumes, and unmanaged containers from a single view.
---
The **Resources** tab shows everything Docker is storing on your host, broken down by ownership, with one-click cleanup and on-demand vulnerability scanning.
<Frame>
<img src="/images/resources/resources-reclaim.png" alt="Resources Hub with the You can reclaim banner, Docker Disk Footprint tiles, Quick Clean panel, and the Images tab populated below" />
</Frame>
## Reclaim hero
Once enabled for a node, an amber banner leads the view whenever there is reclaimable disk space (unused images, stopped containers, or dangling volumes), showing the total amount you can free and a `·`-separated breakdown of what contributes to it (for example, `2 unused images · 10 dangling volumes`). Click **Review & prune** to open a confirmation dialog that lists the exact items that will be removed (capped in the preview with an "and N more" note when the list is long). Confirm only after the plan is ready; Sencho rechecks the list at execute time and skips anything that is no longer eligible.
The hero stays hidden when there is nothing to reclaim, keeping the view focused on the rest of your inventory.
To set the banner aside without pruning, use the **×** in its top-right corner. It stays hidden on that browser until the reclaimable total grows past the amount it held when you dismissed it, so a small, stubborn remainder will not keep reappearing while a genuine new build-up still surfaces.
The banner is off by default and applies per node. To turn it on, open **Settings → Monitoring → Docker & Storage** and switch on **Show reclaimable-space banner**.
<Note>
The banner and the **Review & prune** action are admin-only. Read-only roles still see the rest of the page but cannot trigger destructive operations.
</Note>
## Docker Disk Footprint
The left card under the hero breaks down your Docker disk usage into three tiles:
| Tile | Meaning |
|------|---------|
| **Sencho managed** (green) | Images and volumes used by stacks in your `COMPOSE_DIR` |
| **External** (amber) | Images and volumes used by Docker projects outside Sencho |
| **Reclaimable** (neutral) | Unused images, stopped containers, and dangling volumes safe to delete |
Each tile shows its size and its share of the total footprint as a percentage. The layout itself is fixed (Sencho managed on the left, External and Reclaimable stacked on the right); tile size does not scale with the percentage, so read the numbers rather than the proportions. Click any tile to filter the resource tabs below to that category.
## Quick Clean
The right card under the hero exposes four prune actions. Each tile has a single primary button that targets **Sencho-managed resources only**, so by default the action will not touch external Docker projects.
| Action | What it removes |
|--------|----------------|
| **Prune Unused Images** | Images with no running containers in Sencho stacks |
| **Prune Unused Volumes** | Volumes not attached to any Sencho container |
| **Prune Dead Networks** | Networks not connected to any Sencho container |
| **Purge Unmanaged Containers** | Containers Sencho doesn't recognize (started outside it) |
The first three tiles also show a **More options** menu with a single destructive entry, **All Docker (includes external)**, that broadens the prune to every Docker resource on the host. Use it carefully, since it can affect other Compose projects sharing the same daemon. The **Purge Unmanaged Containers** tile has no menu and always targets unmanaged containers only.
A confirmation dialog appears before any destructive prune. Sencho first builds an itemized plan of exactly which resources will be removed, shows that list in the dialog, and only then enables confirm. The confirm action is bound to that plan: if the daemon state changes before you confirm, Sencho refreshes the plan instead of deleting a different set. While the operation runs, a loading notification keeps you informed; on completion it is replaced with a success or error notification, including how much space was reclaimed.
<Note>
Quick Clean is admin-only. The panel is hidden for users without admin permissions.
</Note>
## Resource tabs
Below the hero, three tabs partition your inventory: **Images**, **Volumes**, and **Unmanaged**. The Unmanaged tab shows a count badge whenever orphan containers are detected.
Network inventory, topology, inspect, and findings live on the dedicated [Networking](/features/networking) page. **Quick Clean** still includes **Prune Dead Networks**.
Each of the first three tabs shares the same toolbar pattern: a collapsible search (click the magnifying glass to open a text filter, matching by name or repository tag) and an **All / Managed / External** filter with a live count on each chip. Sortable columns toggle ascending/descending order when clicked.
A **Scan history** button sits on the right of the Images tab's toolbar when image vulnerability scanning is configured for the node. It takes you to the [Security page](/features/security) History tab so you can review past results without launching a new scan. See [Vulnerability scanning](/features/vulnerability-scanning) for the full workflow.
<Note>
Sencho protects its own image, network, and named volumes from accidental deletion. The matching rows carry a **Sencho** pill alongside the managed status and the delete control is disabled.
</Note>
### Images
Lists all Docker images on the host with their ID, repository tag, size, and status. Click **Repository:Tag**, **Size**, or **Status** to sort.
**Filter chips:** `All`, `Managed`, `External`. Each chip shows the matching count, for example `All 18 · Managed 15 · External 3`.
**Status column** combines two pieces of information per row:
- A usage badge: `In Use` plus one chip per Sencho stack that uses the image (click a chip to open that stack), `In Use` plus `External` when it runs only in another Docker project, or `Unused` when no container references it.
- A severity badge from any image scan: `Clean` (no findings at all), a CVE severity (`LOW`, `MEDIUM`, `HIGH`, `CRITICAL`, or `UNKNOWN`), or `Findings` (no CVEs, but a secret or misconfiguration finding). Click the badge to open the scan results.
**Per-row actions** sit on the right:
- **Inspect** (eye) opens the image detail sheet.
- **Scan** (shield) opens a menu with `Scan (vulnerabilities)` and `Full scan (vulnerabilities + secrets)`. Full scan is available on every tier.
- **Delete** (trash, admin-only) removes the image. Sencho warns before deleting an image that is still in use.
#### Inspect image
Click the eye icon on any image row to open a detail sheet with these sections:
<Frame>
<img src="/images/resources/resources-image-inspect.png" alt="Image inspect sheet showing the Used by, Overview, Config, and Layers sections for a running image" />
</Frame>
- **Used by** lists every Sencho stack that references the image (chips open that stack). Sourced from the Resources inventory, so it stays visible while inspect loads or if inspect fails.
- **Overview** lists the ID (with a copy button), size, creation date, architecture and OS, author, and all repository tags.
- **Config** shows the default `Cmd`, `Entrypoint`, `WorkingDir`, `User`, exposed ports, environment variables, and labels. Env vars and labels are collapsible.
- **Layers** lists the layer history in build order. Each row shows the layer index, size, age, and the build command (`CreatedBy`). Empty layers (metadata-only, zero bytes) are dimmed.
- **Registry tags** (admins) lists remote tag names from a matching configured registry, with a **Load more** button when the registry has additional pages. See [Private registries](/features/private-registries#browse-tags-from-resources) for credential and failure behavior. Vulnerability history and caching use the image digest when available; see [Tags vs digests](/features/vulnerability-scanning#tags-vs-digests).
The inspect sheet is available to all roles. Registry tag browsing is admin-only.
### Volumes
<Frame>
<img src="/images/resources/resources-volumes-tab.png" alt="Volumes tab with the search and filter toolbar above the volume list" />
</Frame>
Lists all Docker volumes with name, driver, mount point, and managed status. Click **Name** or **Driver** to sort.
**Filter chips:** `All`, `Managed`, `External`, each with its count.
Anonymous volumes (Docker-generated 64-character hash names, typical of a container that declares a volume without naming it) show a shortened label with an **anonymous** chip so the table stays readable; hover the name for the full hash.
<Warning>
Deleting a volume is permanent. Any data stored in it will be lost. Always back up important volume data before pruning.
</Warning>
#### Browse volume contents
Click the folder icon on any volume row (admin-only) to open a read-only browser for that volume. The panel shows a directory tree on the left and a file viewer on the right. For an anonymous volume, a band above the tree shows the full 64-character name with a copy button, since the sheet's title and breadcrumb only show the shortened form.
- **Read only.** No edits, no writes, no deletions. The browser launches a short-lived helper container with the volume mounted read-only.
- **Size cap.** Files are read up to 5 MB. Larger files show a truncation banner.
- **Binary files** are displayed as a hex view. Plain text is shown directly.
- **Symlinks** are listed but never followed. Reading a symlink path returns an error.
- **Audit log.** Every file read is recorded in the audit log, including failed reads, with the volume and path. Use this for compliance and incident review.
<Warning>
Volumes commonly contain database files, password hashes, certificates, and other secrets. Treat the volume browser as a high-power admin tool.
</Warning>
### Unmanaged
<Frame>
<img src="/images/resources/resources-unmanaged-tab.png" alt="Unmanaged tab showing the No unmanaged containers success state" />
</Frame>
Lists containers running on the host that are not part of any Sencho-managed stack: containers started with `docker run`, or Compose projects outside your `COMPOSE_DIR`. The tab shows a count badge when any are detected. The running Sencho container itself is excluded from this list so it cannot be purged by accident.
Containers are grouped by their external Compose project. Each group has an **External Project** header with the project name and a container count. Each container row shows:
- A row checkbox for multi-selection.
- The container name (or short ID if unnamed).
- A state pill, for example `running`.
- The image reference, in monospace below the name.
The toolbar above the list provides a **Select all** checkbox and a destructive **Purge Selected (N)** button. The button stays disabled until at least one row is checked, and is admin-only.
When no unmanaged containers are detected, the tab shows a success state with the message "No unmanaged containers" and the subline "All running containers are managed by Sencho."
## Troubleshooting
<AccordionGroup>
<Accordion title="The delete button is greyed out on an image, network, or volume row">
The row carries a **Sencho** pill, which means the resource is the running Sencho instance's own image, attached network, or named volume. Sencho refuses to delete the resources that keep itself running so an admin cannot take the dashboard offline by accident. Bind-mounted host paths are not shown in the Volumes tab and are not affected.
</Accordion>
<Accordion title="I expected to see the Sencho container in the Unmanaged tab and it is not there">
The Unmanaged tab filters the running Sencho container out by design so it cannot be selected and purged. Other containers started outside Sencho (with `docker run` or by a Compose project outside `COMPOSE_DIR`) still appear normally. To inspect the Sencho container itself, use **Host Console** or `docker ps` on the host.
</Accordion>
<Accordion title="The reclaim banner will not go away, or shows a small amount that will not prune">
The banner mirrors what Docker reports as reclaimable on the node, and it counts only the resources a standard prune can actually remove. After a prune, some storage drivers still report a few megabytes as reclaimable that the prune does not free. To stop the banner drawing attention to a stubborn remainder, dismiss it with the **×** in its top-right corner; it stays hidden until the reclaimable total grows past that point. To turn it off for the node entirely, switch off **Show reclaimable-space banner** in **Settings → Monitoring → Docker & Storage**.
</Accordion>
</AccordionGroup>