Add Docker container discovery with stats, image display, and CPU usage bars
This commit is contained in:
@@ -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]"
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user