diff --git a/emhttp/plugins/dynamix.docker.manager/DockerContainers.page b/emhttp/plugins/dynamix.docker.manager/DockerContainers.page index 708ec7abd..32f6672e9 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)__(Container IP)__(Container Port)__(LAN IP:Port)__(Volume Mappings)_ (_(App to Host)_)_(CPU & Memory load)__(Autostart)__(Uptime)_
@@ -183,3 +183,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 772db2c2d..2af612e98 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -49,11 +49,11 @@ $port = file_exists('/sys/class/net/br0') ? 'BR0' : (file_exists('/sys/class/net // Docker configuration file - guaranteed to exist $docker_cfgfile = '/boot/config/docker.cfg'; if (file_exists($docker_cfgfile)) { - exec("grep -Pom2 '_SUBNET_|_{$port}(_[0-9]+)?=' $docker_cfgfile",$cfg); - if (isset($cfg[0]) && $cfg[0]=='_SUBNET_' && empty($cfg[1])) { - # interface has changed, update configuration - exec("sed -ri 's/_(BR0|BOND0|ETH0)(_[0-9]+)?=/_{$port}\\2=/' $docker_cfgfile"); - } + exec("grep -Pom2 '_SUBNET_|_{$port}(_[0-9]+)?=' $docker_cfgfile",$cfg); + if (isset($cfg[0]) && $cfg[0]=='_SUBNET_' && empty($cfg[1])) { + # interface has changed, update configuration + exec("sed -ri 's/_(BR0|BOND0|ETH0)(_[0-9]+)?=/_{$port}\\2=/' $docker_cfgfile"); + } } $defaults = (array)@parse_ini_file("$docroot/plugins/dynamix.docker.manager/default.cfg"); @@ -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) { @@ -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; @@ -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,8 +321,18 @@ class DockerTemplates { // non-templated webui, user specified $tmp['url'] = $webui; } else { - $ip = ($ct['NetworkMode']=='host'||_var($port,'NAT')) ? $host : _var($port,'IP'); + if ($ct['NetworkMode']=='host') { + $ip = $host; + } 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; + } 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'); @@ -338,8 +347,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)); } @@ -897,7 +910,7 @@ class DockerClient { } public function getDockerContainers() { - global $driver; + global $driver, $host; // Return cached values if (is_array($this::$containersCache)) return $this::$containersCache; $this::$containersCache = []; @@ -922,23 +935,43 @@ class DockerClient { $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['Manager'] = $info['Config']['Labels']['net.unraid.docker.managed'] ?? false; $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']; - $nat = true; + } 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']; - $nat = false; } - $ip = $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress']; + } 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) { + if (!isset($info['HostConfig']['PortBindings'][$port])) { + continue; + } [$PrivatePort, $Type] = array_pad(explode('/', $port),2,''); - $c['Ports'][] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : $PrivatePort, 'NAT' => $nat, 'Type' => $Type]; + $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); diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php index 062aecc88..6bca882f0 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerContainers.php @@ -87,11 +87,32 @@ foreach ($containers as $ct) { $icon = $info['icon'] ?: '/plugins/dynamix.docker.manager/images/question.png'; $image = substr($icon,-4)=='.png' ? "" : (substr($icon,0,5)=='icon-' ? "" : ""); $wait = var_split($autostart[array_search($name,$names)]??'',1); - $ports = []; + $networks = []; + $network_ips = []; + foreach($ct['Networks'] as $netName => $netVals) { + $networks[] = $netName; + $network_ips[] = $netVals['IPAddress']; + } + $ports_internal = []; + $ports_external = []; 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')); + 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 (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'] : []; @@ -141,8 +162,10 @@ foreach ($containers as $ct) { break; } echo "
".compress(_($version),12,0)."
"; - echo "{$ct['NetworkMode']}"; - echo "".implode('
',$ports)."
"; + echo " ".implode('
',$networks)."
"; + echo " ".implode('
',$network_ips)."
"; + echo "".implode('
',$ports_internal)."
"; + echo "".implode('
',$ports_external)."
"; echo "".implode('
',$paths)."
"; echo "0%
"; echo "
0 / 0"; @@ -162,3 +185,4 @@ foreach ($images as $image) { } echo "\0".implode($docker)."\0".(pgrep('rc.docker')!==false ? 1:0); ?> + diff --git a/emhttp/plugins/dynamix.docker.manager/include/Helpers.php b/emhttp/plugins/dynamix.docker.manager/include/Helpers.php index f366e76c3..8ae436666 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/Helpers.php +++ b/emhttp/plugins/dynamix.docker.manager/include/Helpers.php @@ -515,9 +515,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');