From 8f05f0d27cf7bfd7c506a5f2ad47b9ae983f9abc Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Thu, 28 May 2026 22:48:06 -0400 Subject: [PATCH] =?UTF-8?q?Docker=20tab:=20full=20inspect=20detail=20?= =?UTF-8?q?=E2=80=94=20icon,=20IP,=20ports,=20paths=20per=20container?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace pill view with per-container rows showing full detail - docker inspect batch call: networks+IPs, port mappings, bind mounts - Container icon from template XML, name links to WebUI if configured - Network IP badges (blue), port mapping badges (yellow) - Bind mount paths shown src→dst, collapsible expand for >3 paths - Large folders (>7 containers) auto-span full width - Status badge: RUNNING/STOPPED/PAUSED/EXITED with colour - Stopped containers dimmed, icons load from template XMLs --- Plugin/unraid/include/docker.php | 113 +++++++-- Plugin/unraid/pages/docker.php | 400 ++++++++++++++++++------------- 2 files changed, 327 insertions(+), 186 deletions(-) diff --git a/Plugin/unraid/include/docker.php b/Plugin/unraid/include/docker.php index 654cbe2..f0a367a 100644 --- a/Plugin/unraid/include/docker.php +++ b/Plugin/unraid/include/docker.php @@ -88,23 +88,90 @@ function vv_dk_write_conf_map(string $raw, string $id, array $map): string { return $raw . "\n# ── Docker Folder Map ────────────────────────────────────────────────────────\n" . $block . "\n"; } -// ── Container inventory ─────────────────────────────────────────────────────── +// ── Container inventory (full inspect) ─────────────────────────────────────── + +function vv_dk_webui(string $name, array $portMap): string { + $template = '/boot/config/plugins/dockerMan/templates-user/my-' . $name . '.xml'; + if (!file_exists($template)) return ''; + $xml = @file_get_contents($template) ?: ''; + if (!preg_match('/(.*?)<\/WebUI>/s', $xml, $m)) return ''; + $url = trim($m[1]); + if (!$url) return ''; + static $localIp = null; + if ($localIp === null) { + $localIp = trim(shell_exec("ip route get 8.8.8.8 2>/dev/null | awk '/src/{for(i=1;i<=NF;i++)if(\$i==\"src\")print \$(i+1)}'") ?: ''); + if (!$localIp) $localIp = gethostbyname(gethostname()); + } + $url = str_replace('[IP]', $localIp, $url); + $url = preg_replace_callback('/\[PORT:(\d+)\]/', fn($pm) => $portMap[$pm[1]] ?? $pm[1], $url); + return $url; +} + +function vv_dk_icon(string $name): string { + $template = '/boot/config/plugins/dockerMan/templates-user/my-' . $name . '.xml'; + if (!file_exists($template)) return ''; + $xml = @file_get_contents($template) ?: ''; + return preg_match('/(.*?)<\/Icon>/s', $xml, $m) ? trim($m[1]) : ''; +} + +function vv_dk_inspect_all(): array { + $ids = trim(shell_exec("docker ps -aq 2>/dev/null") ?: ''); + if (!$ids) return []; + + $idList = implode(' ', array_map('escapeshellarg', explode("\n", $ids))); + $raw = shell_exec("docker inspect $idList 2>/dev/null") ?: '[]'; + $data = json_decode($raw, true) ?: []; -function vv_dk_containers(): array { - $raw = shell_exec("docker ps -a --format '{{.Names}}\t{{.Status}}\t{{.Image}}\t{{.RunningFor}}' 2>/dev/null") ?: ''; $out = []; - foreach (explode("\n", trim($raw)) as $line) { - if (!$line) continue; - [$name, $status, $image, $age] = array_pad(explode("\t", $line, 4), 4, ''); - $name = trim($name); + foreach ($data as $c) { + $name = ltrim($c['Name'] ?? '', '/'); if (!$name) continue; - $running = str_starts_with(trim($status), 'Up'); + $status = $c['State']['Status'] ?? 'unknown'; + $running = $status === 'running'; + $image = $c['Config']['Image'] ?? ''; + + // Networks: name → IP + $networks = []; + foreach ($c['NetworkSettings']['Networks'] ?? [] as $netName => $net) { + $ip = $net['IPAddress'] ?? ''; + if ($ip) $networks[$netName] = $ip; + } + + // Port mappings: hostPort → containerPort/proto + $ports = []; + $portMap = []; // containerPort → hostPort (for WebUI resolution) + foreach ($c['HostConfig']['PortBindings'] ?? [] as $containerPort => $bindings) { + foreach ($bindings ?? [] as $b) { + $hp = $b['HostPort'] ?? ''; + if ($hp) { + $ports[] = $hp . '→' . $containerPort; + [$cp] = explode('/', $containerPort); + $portMap[$cp] = $hp; + } + } + } + + // Bind mounts only + $mounts = []; + foreach ($c['Mounts'] ?? [] as $m) { + if (($m['Type'] ?? '') === 'bind') { + $mounts[] = ['src' => $m['Source'] ?? '', 'dst' => $m['Destination'] ?? '']; + } + } + + $webui = vv_dk_webui($name, $portMap); + $icon = vv_dk_icon($name); + $out[$name] = [ - 'name' => $name, - 'running' => $running, - 'status' => trim($status), - 'image' => trim($image), - 'age' => trim($age), + 'name' => $name, + 'running' => $running, + 'status' => $status, + 'image' => $image, + 'networks' => $networks, + 'ports' => $ports, + 'mounts' => $mounts, + 'webui' => $webui, + 'icon' => $icon, ]; } return $out; @@ -114,12 +181,14 @@ function vv_dk_containers(): array { function vv_dk_all(): array { $jsonData = vv_dk_read_json(); - $containers = vv_dk_containers(); + $containers = vv_dk_inspect_all(); $currentHost= vv_detect_host(); $myId = strtoupper($currentHost); $myRaw = vv_read_conf_raw($currentHost . '.conf'); $confMap = vv_dk_read_conf_map($myRaw, $myId); + $empty = ['name'=>'','running'=>false,'status'=>'','image'=>'','networks'=>[],'ports'=>[],'mounts'=>[],'webui'=>'','icon'=>'']; + // Build folder list enriched with live container data $assigned = []; $folders = []; @@ -127,23 +196,21 @@ function vv_dk_all(): array { $ctrs = []; foreach ($f['containers'] ?? [] as $cname) { $assigned[$cname] = true; - $ctrs[] = array_merge(['name' => $cname, 'running' => false, 'status' => '', 'image' => '', 'age' => ''], - $containers[$cname] ?? []); + $ctrs[] = array_merge($empty, ['name' => $cname], $containers[$cname] ?? []); } usort($ctrs, fn($a, $b) => $b['running'] <=> $a['running'] ?: strcmp($a['name'], $b['name'])); $running = count(array_filter($ctrs, fn($c) => $c['running'])); $folders[] = [ - 'id' => $fid, - 'name' => $f['name'] ?? 'Unnamed', - 'icon' => $f['icon'] ?? '', - 'total' => count($ctrs), - 'running' => $running, - 'containers'=> $ctrs, + 'id' => $fid, + 'name' => $f['name'] ?? 'Unnamed', + 'total' => count($ctrs), + 'running' => $running, + 'containers' => $ctrs, ]; } usort($folders, fn($a, $b) => strcmp($a['name'], $b['name'])); - // Ungrouped: in docker ps but not in any folder + // Ungrouped: running but not in any folder $ungrouped = []; foreach ($containers as $name => $c) { if (isset($assigned[$name])) continue; diff --git a/Plugin/unraid/pages/docker.php b/Plugin/unraid/pages/docker.php index d2e847c..c6150df 100644 --- a/Plugin/unraid/pages/docker.php +++ b/Plugin/unraid/pages/docker.php @@ -1,52 +1,84 @@
Docker - - + + - +
@@ -56,7 +88,6 @@
Loading…
-