From 61e99a390ebdae51e27954162e1e74c8f439bd98 Mon Sep 17 00:00:00 2001 From: mtongnz Date: Fri, 12 Jan 2024 15:45:04 +1300 Subject: [PATCH 01/13] fix: docker network info display (non dockerman & multiple networks) --- .../include/DockerClient.php | 35 ++++++++++++------- .../include/DockerContainers.php | 14 ++++---- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index cce7b1bbc..66590d152 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -1,7 +1,7 @@ $netVals) { + $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; + $c['Networks'][$netName] = [ 'IPAddress' => $i ]; + } } + $ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null; + $c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ]; $ports = (isset($ports) && is_array($ports)) ? $ports : []; foreach ($ports as $port => $value) { [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); - $c['Ports'][] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : $PrivatePort, 'NAT' => $nat, 'Type' => $Type]; + $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : $PrivatePort, 'NAT' => $nat, 'Type' => $Type]; } + ksort($c['Ports']); $this::$containersCache[] = $c; } array_multisort(array_column($this::$containersCache,'Name'), SORT_NATURAL|SORT_FLAG_CASE, $this::$containersCache); @@ -1016,11 +1027,11 @@ class DockerUtil { // Unprocessable input $strRepo = $image; } - } +} // Add :latest tag to image if it's absent if (empty($strTag)) $strTag = 'latest'; - + return array_map('trim', ['strRepo' => $strRepo, 'strTag' => $strTag]); } diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 9caf1fc20..722322024 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -1,7 +1,7 @@ " : (substr($icon,0,5)=='icon-' ? "" : ""); $wait = var_split($autostart[array_search($name,$names)]??'',1); + $networks = []; + foreach($ct['Networks'] as $netName => $netVals) { + $networks[] = "{$netName}{$netVals['IPAddress']}"; + } $ports = []; foreach ($ct['Ports'] as $port) { - $intern = $running ? ($ct['NetworkMode']=='host' ? $host : _var($port,'IP')) : $null; - $extern = $running ? (_var($port,'NAT') ? $host : $intern) : $null; - $ports[] = sprintf('%s:%s/%s%s:%s', $intern, _var($port,'PrivatePort'), strtoupper(_var($port,'Type')), $extern, _var($port,'PublicPort')); + $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')), _var($port,'PublicPort')); } $paths = []; $ct['Volumes'] = is_array($ct['Volumes']) ? $ct['Volumes'] : []; @@ -136,7 +138,7 @@ foreach ($containers as $ct) { break; } echo "
".compress(_($version),12,0)."
"; - echo "{$ct['NetworkMode']}"; + echo " ".implode(' ',$networks).""; echo "".implode('
',$ports)."
"; echo "".implode('
',$paths)."
"; echo "0%
"; From 3d1b53d0ea91c79338267bb0abc6fedd7564affb Mon Sep 17 00:00:00 2001 From: mtongnz Date: Fri, 12 Jan 2024 15:45:53 +1300 Subject: [PATCH 02/13] style: line up spacing --- emhttp/plugins/dynamix.docker.manager/include/DockerClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 66590d152..cb4ad15e1 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -920,7 +920,7 @@ class DockerClient { $c['BaseImage'] = $ct['Labels']['BASEIMAGE'] ?? false; $c['Icon'] = $info['Config']['Labels']['net.unraid.docker.icon'] ?? false; $c['Url'] = $info['Config']['Labels']['net.unraid.docker.webui'] ?? false; - $c['Shell'] = $info['Config']['Labels']['net.unraid.docker.shell'] ?? false; + $c['Shell'] = $info['Config']['Labels']['net.unraid.docker.shell'] ?? false; $c['Ports'] = []; $c['Networks'] = []; if ($id) $c['NetworkMode'] = $net.str_replace('/',':',DockerUtil::ctMap($id)?:'/???'); From 064cac111097efb12c4001d3f4e1643df2f37938 Mon Sep 17 00:00:00 2001 From: mtongnz Date: Fri, 12 Jan 2024 15:46:43 +1300 Subject: [PATCH 03/13] fix: suppress error on template fetch --- emhttp/plugins/dynamix.docker.manager/include/DockerClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index cb4ad15e1..6842b5c8d 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -255,7 +255,7 @@ class DockerTemplates { $doc = new DOMDocument(); $doc->load($file['path']); if ($name) { - if ($doc->getElementsByTagName('Name')->item(0)->nodeValue !== $name) continue; + if (@$doc->getElementsByTagName('Name')->item(0)->nodeValue !== $name) continue; } $TemplateRepository = DockerUtil::ensureImageTag($doc->getElementsByTagName('Repository')->item(0)->nodeValue??''); if ($TemplateRepository && $TemplateRepository==$Repository) { From 3dda97319df58158ea41b02348475a8752aa78ea Mon Sep 17 00:00:00 2001 From: mtongnz Date: Fri, 12 Jan 2024 15:51:04 +1300 Subject: [PATCH 04/13] fix: don't return template for containers not managed by dockerman --- .../dynamix.docker.manager/include/DockerClient.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 6842b5c8d..1b4a90ce3 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -338,8 +338,12 @@ class DockerTemplates { $tmp['updated'] = var_export($DockerUpdate->getUpdateStatus($image),true); } if (!$com) $tmp['updated'] = 'undef'; - if (empty($tmp['template']) || $reload) $tmp['template'] = $this->getUserTemplate($name); - if ($reload) $DockerUpdate->updateUserTemplate($name); + if ($ct['Manager'] !== 'dockerman') + $tmp['template'] = null; + else if (empty($tmp['template']) || $reload) { + $tmp['template'] = $this->getUserTemplate($name); + if ($reload) $DockerUpdate->updateUserTemplate($name); + } //$this->debug("\n$name"); //foreach ($tmp as $c => $d) $this->debug(sprintf(' %-10s: %s', $c, $d)); } From 083cd984eaeff92cc1c382a45da4be3b3c82e0c3 Mon Sep 17 00:00:00 2001 From: mtongnz Date: Fri, 12 Jan 2024 16:09:52 +1300 Subject: [PATCH 05/13] style: fix bizzare formatting glitches --- .../include/DockerClient.php | 20 +++++++++---------- .../include/DockerContainers.php | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 1b4a90ce3..25a5757f2 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -1,7 +1,7 @@ $strRepo, 'strTag' => $strTag]); } diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 722322024..b36a0c0eb 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -1,7 +1,7 @@ Date: Sat, 6 Apr 2024 13:04:22 +1300 Subject: [PATCH 06/13] Apply suggestions from code review Co-authored-by: FunkeCoder23 <12570656+FunkeCoder23@users.noreply.github.com> --- .../plugins/dynamix.docker.manager/include/DockerClient.php | 5 +++-- .../dynamix.docker.manager/include/DockerContainers.php | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 25a5757f2..34c7a716d 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -924,7 +924,8 @@ class DockerClient { $c['BaseImage'] = $ct['Labels']['BASEIMAGE'] ?? false; $c['Icon'] = $info['Config']['Labels']['net.unraid.docker.icon'] ?? false; $c['Url'] = $info['Config']['Labels']['net.unraid.docker.webui'] ?? false; - $c['Shell'] = $info['Config']['Labels']['net.unraid.docker.shell'] ?? false; + $c['Shell'] = $info['Config']['Labels']['net.unraid.docker.shell'] ?? false; + $c['Manager'] = $info['Config']['Labels']['net.unraid.docker.managed'] ?? false; $c['Ports'] = []; $c['Networks'] = []; if ($id) $c['NetworkMode'] = $net.str_replace('/',':',DockerUtil::ctMap($id)?:'/???'); @@ -950,7 +951,7 @@ class DockerClient { $ports = (isset($ports) && is_array($ports)) ? $ports : []; foreach ($ports as $port => $value) { [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); - $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : $PrivatePort, 'NAT' => $nat, 'Type' => $Type]; + $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : null, 'NAT' => $nat, 'Type' => $Type]; } ksort($c['Ports']); $this::$containersCache[] = $c; diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index b36a0c0eb..7fc16a22a 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -93,7 +93,9 @@ foreach ($containers as $ct) { } $ports = []; foreach ($ct['Ports'] as $port) { - $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')), _var($port,'PublicPort')); + $arrow_style = _var($port,'PublicPort') ? "\"fa fa-arrows-h\"" : ""; + $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')),$arrow_style , _var($port,'PublicPort')); + } $paths = []; $ct['Volumes'] = is_array($ct['Volumes']) ? $ct['Volumes'] : []; From ffabb996fc8ee6b5edc54234b7b038be5260eed4 Mon Sep 17 00:00:00 2001 From: mtongnz Date: Sat, 6 Apr 2024 16:38:02 +1300 Subject: [PATCH 07/13] fix: external ports not showing for non-bridge networks --- .../plugins/dynamix.docker.manager/include/DockerClient.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 34c7a716d..a5fe4a61b 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -932,15 +932,12 @@ class DockerClient { if (isset($driver[$c['NetworkMode']])) { if ($driver[$c['NetworkMode']]=='bridge') { $ports = &$info['HostConfig']['PortBindings']; - $nat = true; } else { $ports = &$info['Config']['ExposedPorts']; - $nat = false; } } else if (!$id) { $c['NetworkMode'] = DockerUtil::ctMap($c['NetworkMode']); $ports = &$info['Config']['ExposedPorts']; - $nat = false; foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) { $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; $c['Networks'][$netName] = [ 'IPAddress' => $i ]; @@ -951,7 +948,8 @@ class DockerClient { $ports = (isset($ports) && is_array($ports)) ? $ports : []; foreach ($ports as $port => $value) { [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); - $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : null, 'NAT' => $nat, 'Type' => $Type]; + $PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null; + $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'Type' => $Type]; } ksort($c['Ports']); $this::$containersCache[] = $c; From 54a6e3dd13b21fa6a58d39bf4ac5989ad86317a0 Mon Sep 17 00:00:00 2001 From: mtongnz Date: Sat, 20 Jul 2024 12:04:30 +1200 Subject: [PATCH 08/13] fix: better display of ip & ports to avoid beginner confusion - from suggestions by @ich777 --- .../dynamix.docker.manager/DockerContainers.page | 4 ++-- .../include/DockerContainers.php | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 39e2d00d5..0eb3bb4ca 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -31,8 +31,8 @@ $cpus = cpu_list(); "> - - + +
_(Application)__(Version)__(Network)__(Port Mappings)_ (_(App to Host)_)_(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
_(Application)__(Version)__(Network)__(IP)__(Port Mappings)__(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 7fc16a22a..df60fe26e 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -88,13 +88,18 @@ foreach ($containers as $ct) { $image = substr($icon,-4)=='.png' ? "" : (substr($icon,0,5)=='icon-' ? "" : ""); $wait = var_split($autostart[array_search($name,$names)]??'',1); $networks = []; + $network_ips = []; foreach($ct['Networks'] as $netName => $netVals) { - $networks[] = "{$netName}{$netVals['IPAddress']}"; + $networks[] = $netName; + $network_ips[] = $netVals['IPAddress']; } $ports = []; foreach ($ct['Ports'] as $port) { $arrow_style = _var($port,'PublicPort') ? "\"fa fa-arrows-h\"" : ""; - $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')),$arrow_style , _var($port,'PublicPort')); + if (_var($port,'PublicPort')) + $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')),$arrow_style , _var($port,'PublicPort')); + else + $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')),$arrow_style , "   (internal)"); } $paths = []; @@ -140,7 +145,8 @@ foreach ($containers as $ct) { break; } echo "
".compress(_($version),12,0)."
"; - echo " ".implode(' ',$networks).""; + echo " ".implode('
',$networks)."
"; + echo " ".implode('
',$network_ips)."
"; echo "".implode('
',$ports)."
"; echo "".implode('
',$paths)."
"; echo "0%
"; From 4b3e8f2d46857afd8a04cbb8a5a74715434f88bb Mon Sep 17 00:00:00 2001 From: mtongnz Date: Sat, 20 Jul 2024 13:23:56 +1200 Subject: [PATCH 09/13] fix: handle webUI link generation correctly --- .../plugins/dynamix.docker.manager/include/DockerClient.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index a5fe4a61b..f93d0313c 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -307,9 +307,8 @@ class DockerTemplates { $tmp['paused'] = $ct['Paused']; $tmp['autostart'] = in_array($name,$autoStart); $tmp['cpuset'] = $ct['CPUset']; - $tmp['url'] = $tmp['url'] ?? ''; + $tmp['url'] = $ct['Url'] ?? $tmp['url'] ?? ''; // read docker label for WebUI & Icon - if (isset($ct['Url']) && !$tmp['url']) $tmp['url'] = $ct['Url']; if (isset($ct['Icon'])) $tmp['icon'] = $ct['Icon']; if (isset($ct['Shell'])) $tmp['shell'] = $ct['Shell']; if (!$communityApplications) { @@ -322,7 +321,7 @@ class DockerTemplates { // non-templated webui, user specified $tmp['url'] = $webui; } else { - $ip = ($ct['NetworkMode']=='host'||_var($port,'NAT')) ? $host : _var($port,'IP'); + $ip = ($ct['NetworkMode']=='host'||!is_null(_var($port,'PublicPort'))) ? $host : _var($port,'IP'); $tmp['url'] = $ip ? (strpos($tmp['url'],$ip)!==false ? $tmp['url'] : $this->getControlURL($ct, $ip, $tmp['url'])) : $tmp['url']; } if ( ($tmp['shell'] ?? false) == false ) From 27047c883254b38bcca3b26df9228447b6fe91c9 Mon Sep 17 00:00:00 2001 From: mtongnz Date: Sun, 28 Jul 2024 11:18:31 +1200 Subject: [PATCH 10/13] fix: improve IP & port display further as per suggestions --- .../DockerContainers.page | 2 +- .../include/DockerClient.php | 5 ++++- .../include/DockerContainers.php | 17 +++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 0eb3bb4ca..19e524d9a 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -31,7 +31,7 @@ $cpus = cpu_list(); "> - +
_(Application)__(Version)__(Network)__(IP)__(Port Mappings)__(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
_(Application)__(Version)__(Network)__(Container IP)__(Container Port)__(External IP:Port)__(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index f93d0313c..0aef6fc1b 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -948,7 +948,10 @@ class DockerClient { foreach ($ports as $port => $value) { [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); $PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null; - $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'Type' => $Type]; + $nat = ($driver[$c['NetworkMode']]=='bridge'); + if (array_key_exists($PrivatePort, $c['Ports']) && $Type != $c['Ports'][$PrivatePort]['Type']) + $Type = $c['Ports'][$PrivatePort]['Type'] . '/' . $Type; + $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'NAT' => $nat, 'Type' => $Type, 'Driver' => $driver[$c['NetworkMode']]]; } ksort($c['Ports']); $this::$containersCache[] = $c; diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index df60fe26e..1a28ab5f0 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -93,14 +93,14 @@ foreach ($containers as $ct) { $networks[] = $netName; $network_ips[] = $netVals['IPAddress']; } - $ports = []; + $ports_internal = []; + $ports_external = []; foreach ($ct['Ports'] as $port) { - $arrow_style = _var($port,'PublicPort') ? "\"fa fa-arrows-h\"" : ""; - if (_var($port,'PublicPort')) - $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')),$arrow_style , _var($port,'PublicPort')); - else - $ports[] = sprintf('%s:%s%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')),$arrow_style , "   (internal)"); - + if (_var($port,'PublicPort') && _var($port,'Driver') == 'bridge') + $ports_external[] = sprintf('%s:%s', $host, strtoupper(_var($port,'PublicPort'))); + if (_var($port,'Driver') == 'ipvlan' || _var($port,'Driver') == 'host') + $ports_external[] = sprintf('%s:%s', _var($port,'IP'), strtoupper(_var($port,'PrivatePort'))); + $ports_internal[] = sprintf('%s:%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type'))); } $paths = []; $ct['Volumes'] = is_array($ct['Volumes']) ? $ct['Volumes'] : []; @@ -147,7 +147,8 @@ foreach ($containers as $ct) { echo "
".compress(_($version),12,0)."
"; echo " ".implode('
',$networks)."
"; echo " ".implode('
',$network_ips)."
"; - echo "".implode('
',$ports)."
"; + echo "".implode('
',$ports_internal)."
"; + echo "".implode('
',$ports_external)."
"; echo "".implode('
',$paths)."
"; echo "0%
"; echo "
0 / 0"; From 9c2aa45751a367b1160bc4437e45af8d77229d91 Mon Sep 17 00:00:00 2001 From: Christoph Hummer Date: Sat, 3 Aug 2024 07:39:00 +0200 Subject: [PATCH 11/13] Minor improvements (#1) * few changes, please test * Change weird formatting * Another formatting change * Fix for `container:` networks * Hide IPs/Ports when container is not running * WebUI fix - generate WebUI links correctly - don't show WebUI from containers which use a `container:` network --- .../DockerContainers.page | 1 + .../include/DockerClient.php | 65 ++++++++++++------- .../include/DockerContainers.php | 19 +++++- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 19e524d9a..e0bfb05c6 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -182,3 +182,4 @@ window.onunload = function(){ dockerload.stop(); } + diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 0aef6fc1b..7d777ec78 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -293,7 +293,7 @@ class DockerTemplates { } public function getAllInfo($reload=false,$com=true,$communityApplications=false) { - global $dockerManPaths, $host; + global $driver, $dockerManPaths, $host; $DockerClient = new DockerClient(); $DockerUpdate = new DockerUpdate(); //$DockerUpdate->verbose = $this->verbose; @@ -321,8 +321,18 @@ class DockerTemplates { // non-templated webui, user specified $tmp['url'] = $webui; } else { - $ip = ($ct['NetworkMode']=='host'||!is_null(_var($port,'PublicPort'))) ? $host : _var($port,'IP'); + if ($ct['NetworkMode']=='host') { + $ip = $host; + } elseif ($driver[$ct['NetworkMode']]=='ipvlan' || $driver[$ct['NetworkMode']]=='macvlan') { + $ip = reset($ct['Networks'])['IPAddress']; + } elseif (!is_null(_var($port,'PublicPort'))) { + $ip = $host; + } else { + $ip = _var($port,'IP'); + } $tmp['url'] = $ip ? (strpos($tmp['url'],$ip)!==false ? $tmp['url'] : $this->getControlURL($ct, $ip, $tmp['url'])) : $tmp['url']; + if (strpos($ct['NetworkMode'], 'container:') === 0) + $tmp['url'] = ''; } if ( ($tmp['shell'] ?? false) == false ) $tmp['shell'] = $this->getTemplateValue($image, 'Shell'); @@ -928,32 +938,38 @@ class DockerClient { $c['Ports'] = []; $c['Networks'] = []; if ($id) $c['NetworkMode'] = $net.str_replace('/',':',DockerUtil::ctMap($id)?:'/???'); - if (isset($driver[$c['NetworkMode']])) { - if ($driver[$c['NetworkMode']]=='bridge') { - $ports = &$info['HostConfig']['PortBindings']; - } else { + if ($info['State']['Running']) { + if (isset($driver[$c['NetworkMode']])) { + if ($driver[$c['NetworkMode']]=='bridge') { + $ports = &$info['HostConfig']['PortBindings']; + } elseif ($driver[$c['NetworkMode']]=='host') { + $c['Ports']['host'] = ['host' => '']; + } elseif ($driver[$c['NetworkMode']]=='ipvlan' || $driver[$c['NetworkMode']]=='macvlan') { + $c['Ports']['vlan'] = ['vlan' => '']; + } else { + $ports = &$info['Config']['ExposedPorts']; + } + } else if (!$id) { + $c['NetworkMode'] = DockerUtil::ctMap($c['NetworkMode']); $ports = &$info['Config']['ExposedPorts']; + foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) { + $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; + $c['Networks'][$netName] = [ 'IPAddress' => $i ]; + } } - } else if (!$id) { - $c['NetworkMode'] = DockerUtil::ctMap($c['NetworkMode']); - $ports = &$info['Config']['ExposedPorts']; - foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) { - $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; - $c['Networks'][$netName] = [ 'IPAddress' => $i ]; + $ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null; + $c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ]; + $ports = (isset($ports) && is_array($ports)) ? $ports : []; + foreach ($ports as $port => $value) { + [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); + $PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null; + $nat = ($driver[$c['NetworkMode']]=='bridge'); + if (array_key_exists($PrivatePort, $c['Ports']) && $Type != $c['Ports'][$PrivatePort]['Type']) + $Type = $c['Ports'][$PrivatePort]['Type'] . '/' . $Type; + $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'NAT' => $nat, 'Type' => $Type, 'Driver' => $driver[$c['NetworkMode']]]; } + ksort($c['Ports']); } - $ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null; - $c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ]; - $ports = (isset($ports) && is_array($ports)) ? $ports : []; - foreach ($ports as $port => $value) { - [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); - $PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null; - $nat = ($driver[$c['NetworkMode']]=='bridge'); - if (array_key_exists($PrivatePort, $c['Ports']) && $Type != $c['Ports'][$PrivatePort]['Type']) - $Type = $c['Ports'][$PrivatePort]['Type'] . '/' . $Type; - $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'NAT' => $nat, 'Type' => $Type, 'Driver' => $driver[$c['NetworkMode']]]; - } - ksort($c['Ports']); $this::$containersCache[] = $c; } array_multisort(array_column($this::$containersCache,'Name'), SORT_NATURAL|SORT_FLAG_CASE, $this::$containersCache); @@ -1101,3 +1117,4 @@ class DockerUtil { } } ?> + diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 1a28ab5f0..3e67cb5d2 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -96,11 +96,23 @@ foreach ($containers as $ct) { $ports_internal = []; $ports_external = []; foreach ($ct['Ports'] as $port) { + if (strpos($ct['NetworkMode'], 'container:') === 0) + break; if (_var($port,'PublicPort') && _var($port,'Driver') == 'bridge') $ports_external[] = sprintf('%s:%s', $host, strtoupper(_var($port,'PublicPort'))); - if (_var($port,'Driver') == 'ipvlan' || _var($port,'Driver') == 'host') - $ports_external[] = sprintf('%s:%s', _var($port,'IP'), strtoupper(_var($port,'PrivatePort'))); - $ports_internal[] = sprintf('%s:%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type'))); + if (isset($ct['Networks']['host'])) { + $ports_external[] = sprintf('%s', $netVals['IPAddress']); + $ports_internal[] = sprintf('%s', 'all'); + break; + } + if (isset($ct['Ports']['vlan'])) { + $ports_external[] = sprintf('%s', $netVals['IPAddress']); + $ports_internal[] = sprintf('%s', 'all'); + break; + } + if ((!isset($ct['Networks']['host'])) || (!isset($ct['Networks']['vlan']))) { + $ports_internal[] = sprintf('%s:%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type'))); + } } $paths = []; $ct['Volumes'] = is_array($ct['Volumes']) ? $ct['Volumes'] : []; @@ -168,3 +180,4 @@ foreach ($images as $image) { } echo "\0".implode($docker)."\0".(pgrep('rc.docker')!==false ? 1:0); ?> + From 8cabad6f0dd3953ded5057514652dfd910d7b5fa Mon Sep 17 00:00:00 2001 From: Christoph Hummer Date: Thu, 8 Aug 2024 06:58:58 +0200 Subject: [PATCH 12/13] Changes (#2) * Changes - Revert commit #ed5fe721d9cdfeb65148a5f12eebdf35729e1dfb - Fix php errors * Update DockerContainers.page - Change `External IP:Port` to `LAN IP:Port` --- .../DockerContainers.page | 2 +- .../include/DockerClient.php | 62 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index e0bfb05c6..9a8b8c44e 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page @@ -31,7 +31,7 @@ $cpus = cpu_list(); "> - +
_(Application)__(Version)__(Network)__(Container IP)__(Container Port)__(External IP:Port)__(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
_(Application)__(Version)__(Network)__(Container IP)__(Container Port)__(LAN IP:Port)__(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 7d777ec78..f7fcabb99 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -323,10 +323,10 @@ class DockerTemplates { } else { if ($ct['NetworkMode']=='host') { $ip = $host; - } elseif ($driver[$ct['NetworkMode']]=='ipvlan' || $driver[$ct['NetworkMode']]=='macvlan') { + } elseif (isset($driver[$ct['NetworkMode']]) && ($driver[$ct['NetworkMode']] == 'ipvlan' || $driver[$ct['NetworkMode']] == 'macvlan')) { $ip = reset($ct['Networks'])['IPAddress']; } elseif (!is_null(_var($port,'PublicPort'))) { - $ip = $host; + $ip = $host; } else { $ip = _var($port,'IP'); } @@ -938,38 +938,39 @@ class DockerClient { $c['Ports'] = []; $c['Networks'] = []; if ($id) $c['NetworkMode'] = $net.str_replace('/',':',DockerUtil::ctMap($id)?:'/???'); - if ($info['State']['Running']) { - if (isset($driver[$c['NetworkMode']])) { - if ($driver[$c['NetworkMode']]=='bridge') { - $ports = &$info['HostConfig']['PortBindings']; - } elseif ($driver[$c['NetworkMode']]=='host') { - $c['Ports']['host'] = ['host' => '']; - } elseif ($driver[$c['NetworkMode']]=='ipvlan' || $driver[$c['NetworkMode']]=='macvlan') { - $c['Ports']['vlan'] = ['vlan' => '']; - } else { - $ports = &$info['Config']['ExposedPorts']; - } - } else if (!$id) { - $c['NetworkMode'] = DockerUtil::ctMap($c['NetworkMode']); + if (isset($driver[$c['NetworkMode']])) { + if ($driver[$c['NetworkMode']]=='bridge') { + $ports = &$info['HostConfig']['PortBindings']; + } elseif ($driver[$c['NetworkMode']]=='host') { + $c['Ports']['host'] = ['host' => '']; + } elseif ($driver[$c['NetworkMode']]=='ipvlan' || $driver[$c['NetworkMode']]=='macvlan') { + $c['Ports']['vlan'] = ['vlan' => '']; + } else { $ports = &$info['Config']['ExposedPorts']; - foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) { - $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; - $c['Networks'][$netName] = [ 'IPAddress' => $i ]; - } } - $ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null; - $c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ]; - $ports = (isset($ports) && is_array($ports)) ? $ports : []; - foreach ($ports as $port => $value) { - [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); - $PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null; - $nat = ($driver[$c['NetworkMode']]=='bridge'); - if (array_key_exists($PrivatePort, $c['Ports']) && $Type != $c['Ports'][$PrivatePort]['Type']) - $Type = $c['Ports'][$PrivatePort]['Type'] . '/' . $Type; - $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'NAT' => $nat, 'Type' => $Type, 'Driver' => $driver[$c['NetworkMode']]]; + } else if (!$id) { + $c['NetworkMode'] = DockerUtil::ctMap($c['NetworkMode']); + $ports = &$info['Config']['ExposedPorts']; + foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) { + $i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress']; + $c['Networks'][$netName] = [ 'IPAddress' => $i ]; } - ksort($c['Ports']); } + $ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null; + $c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ]; + $ports = (isset($ports) && is_array($ports)) ? $ports : []; + foreach ($ports as $port => $value) { + if (!isset($info['HostConfig']['PortBindings'][$port])) { + continue; + } + [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); + $PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null; + $nat = ($driver[$c['NetworkMode']]=='bridge'); + if (array_key_exists($PrivatePort, $c['Ports']) && $Type != $c['Ports'][$PrivatePort]['Type']) + $Type = $c['Ports'][$PrivatePort]['Type'] . '/' . $Type; + $c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'NAT' => $nat, 'Type' => $Type, 'Driver' => $driver[$c['NetworkMode']]]; + } + ksort($c['Ports']); $this::$containersCache[] = $c; } array_multisort(array_column($this::$containersCache,'Name'), SORT_NATURAL|SORT_FLAG_CASE, $this::$containersCache); @@ -1117,4 +1118,3 @@ class DockerUtil { } } ?> - From 17909f889e3c13f955a63c3ea1656626cf77f093 Mon Sep 17 00:00:00 2001 From: Christoph Hummer Date: Thu, 8 Aug 2024 10:32:38 +0200 Subject: [PATCH 13/13] Fix PHP Warning (#3) - Fix PHP Warnings on Add Container page --- .../dynamix.docker.manager/include/Helpers.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/emhttp/plugins/dynamix.docker.manager/include/Helpers.php b/emhttp/plugins/dynamix.docker.manager/include/Helpers.php index 3064d9066..667e85868 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/Helpers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/Helpers.php @@ -501,9 +501,15 @@ function getAllocations() { $nat = $ip = false; $list['Name'] = $ct['Name']; foreach ($ct['Ports'] as $tmp) { - $nat = $tmp['NAT']; - $ip = $tmp['IP']; - $port[] = $tmp['PublicPort']; + if (isset($tmp['NAT'])) { + $nat = $tmp['NAT']; + } + if (isset($tmp['IP'])) { + $ip = $tmp['IP']; + } + if (isset($tmp['PublicPort'])) { + $port[] = $tmp['PublicPort']; + } } sort($port); $ip = $ct['NetworkMode']=='host'||$nat ? $host : ($ip ?: DockerUtil::myIP($ct['Name']) ?: '0.0.0.0');