Add Docker container discovery with stats, image display, and CPU usage bars
All checks were successful
Build-Publish / build (linux/amd64) (push) Successful in 4s
Build-Publish / build (linux/arm64) (push) Successful in 12s
Build-Publish / create-manifest (push) Successful in 2s
Build-Publish / publish-template (push) Successful in 15s

This commit is contained in:
j
2026-03-08 14:06:23 +13:00
parent d675d282b6
commit 4637e60ec4
4 changed files with 56 additions and 3 deletions

View File

@@ -279,4 +279,31 @@ if command -v virsh &>/dev/null; then
done done
fi fi
# Docker containers
if command -v docker &>/dev/null; then
_sudo docker ps -a --format '{{.Names}}\t{{.State}}\t{{.Image}}\t{{.Status}}' 2>/dev/null | while IFS=$'\t' read -r name state image status_text; do
[ -z "$name" ] && continue
echo "[container:docker-${name}]"
echo "type=docker"
echo "platform=docker"
echo "name=$name"
echo "status=$state"
echo "image=$image"
echo "status_text=$status_text"
if [ "$state" = "running" ]; then
# Get IP from docker inspect
docker_ip=$(_sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$name" 2>/dev/null)
[ -n "$docker_ip" ] && echo "ip=$docker_ip"
# Get memory/cpu stats (one-shot, no stream)
stats=$(_sudo docker stats --no-stream --format '{{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}' "$name" 2>/dev/null)
if [ -n "$stats" ]; then
mem_pct=$(echo "$stats" | cut -f2 | tr -d '%')
cpu_pct=$(echo "$stats" | cut -f3 | tr -d '%')
echo "mem_percent=${mem_pct}"
echo "cpu_percent=${cpu_pct}"
fi
fi
done
fi
echo "[end]" echo "[end]"

View File

@@ -386,6 +386,15 @@ main {
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
} }
.ct-image {
font-size: 0.7rem;
color: #475569;
margin-bottom: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ct-status-label { .ct-status-label {
color: #64748b; color: #64748b;
font-style: italic; font-style: italic;

View File

@@ -264,6 +264,9 @@
<span class="ct-name">{{ ct.get('name', ct.get('id', '?')) }}</span> <span class="ct-name">{{ ct.get('name', ct.get('id', '?')) }}</span>
<span class="ct-type">{{ ct.get('type', '')|upper }}</span> <span class="ct-type">{{ ct.get('type', '')|upper }}</span>
</div> </div>
{% if ct.get('image') %}
<div class="ct-image">{{ ct.get('image') }}</div>
{% endif %}
{% if ct_running %} {% if ct_running %}
<div class="ct-details"> <div class="ct-details">
{% if ct.get('ip') %} {% if ct.get('ip') %}
@@ -272,9 +275,22 @@
{% if ct.get('uptime_seconds') %} {% if ct.get('uptime_seconds') %}
<span class="ct-uptime">{{ ct.get('uptime_seconds', '')|format_uptime }}</span> <span class="ct-uptime">{{ ct.get('uptime_seconds', '')|format_uptime }}</span>
{% endif %} {% endif %}
{% if ct.get('status_text') %}
<span class="ct-uptime">{{ ct.get('status_text') }}</span>
{% endif %}
</div> </div>
{% if ct.get('mem_percent') %} {% if ct.get('mem_percent') or ct.get('cpu_percent') %}
<div class="usage-bars"> <div class="usage-bars">
{% if ct.get('cpu_percent') %}
<div class="usage-row">
<span class="usage-label">CPU</span>
<div class="usage-bar-bg">
<div class="usage-bar-fill" style="width: {{ [ct.get('cpu_percent', '0')|float, 100.0]|min }}%; background: {{ ct.get('cpu_percent', '0')|float|usage_color }};"></div>
</div>
<span class="usage-pct">{{ ct.get('cpu_percent', '0') }}%</span>
</div>
{% endif %}
{% if ct.get('mem_percent') %}
<div class="usage-row"> <div class="usage-row">
<span class="usage-label">RAM</span> <span class="usage-label">RAM</span>
<div class="usage-bar-bg"> <div class="usage-bar-bg">
@@ -282,6 +298,7 @@
</div> </div>
<span class="usage-pct">{{ ct.get('mem_percent', '0') }}%</span> <span class="usage-pct">{{ ct.get('mem_percent', '0') }}%</span>
</div> </div>
{% endif %}
{% if ct.get('disk_percent') %} {% if ct.get('disk_percent') %}
<div class="usage-row"> <div class="usage-row">
<span class="usage-label">DISK</span> <span class="usage-label">DISK</span>

View File

@@ -196,7 +196,7 @@ install_packages
# Some sensor/DMI files need group access # Some sensor/DMI files need group access
if [ "$OS" != "openwrt" ]; then if [ "$OS" != "openwrt" ]; then
# Add infmap to common hardware-access groups if they exist # Add infmap to common hardware-access groups if they exist
for group in i2c sensors; do for group in i2c sensors docker; do
getent group "$group" &>/dev/null && usermod -aG "$group" "$USERNAME" 2>/dev/null || true getent group "$group" &>/dev/null && usermod -aG "$group" "$USERNAME" 2>/dev/null || true
done done
fi fi
@@ -207,7 +207,7 @@ SUDOERS_FILE="/etc/sudoers.d/infmap"
SUDO_CMDS="" SUDO_CMDS=""
# Detect which hypervisor tools are present (check common sbin paths too) # Detect which hypervisor tools are present (check common sbin paths too)
for cmd in pct qm lxc virsh; do for cmd in pct qm lxc virsh docker; do
cmd_path=$(command -v "$cmd" 2>/dev/null) cmd_path=$(command -v "$cmd" 2>/dev/null)
# Also check sbin paths not always in PATH # Also check sbin paths not always in PATH
if [ -z "$cmd_path" ]; then if [ -z "$cmd_path" ]; then