ignore_user_abort(true); require_once("/usr/local/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php"); $DockerClient = new DockerClient(); $DockerUpdate = new DockerUpdate(); $DockerTemplates = new DockerTemplates(); # ███████╗██╗ ██╗███╗ ██╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗███████╗ # ██╔════╝██║ ██║████╗ ██║██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝ # █████╗ ██║ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗ # ██╔══╝ ██║ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║ # ██║ ╚██████╔╝██║ ╚████║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║███████║ # ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ $echo = function($m){echo "
".print_r($m,true)."";}; function prepareDir($dir){ if (strlen($dir)){ if ( ! is_dir($dir) && ! is_file($dir)){ mkdir($dir, 0777, true); chown($dir, 'nobody'); chgrp($dir, 'users'); sleep(1); } } } function ContainerExist($container){ global $DockerClient; $all_containers = $DockerClient->getDockerContainers(); if ( ! $all_containers) { return FALSE; } foreach ($all_containers as $ct) { if ($ct['Name'] == $container){ return True; break; } } return False; } function ImageExist($image){ global $DockerClient; $all_images = $DockerClient->getDockerImages(); if ( ! $all_images) { return FALSE; } foreach ($all_images as $img) { if ( ! is_bool(strpos($img['Tags'][0], $image)) ){ return True; break; } } return False; } function trimLine($text){ return preg_replace("/([\n^])[\s]+/", '$1', $text); } $pullecho = function($line) { global $alltotals; $cnt = json_decode( $line, TRUE ); $id = ( isset( $cnt['id'] )) ? $cnt['id'] : ""; $status = ( isset( $cnt['status'] )) ? $cnt['status'] : ""; if (strlen(trim($status)) && strlen(trim($id))) { if ( isset($cnt['progressDetail']['total']) && $cnt['progressDetail']['total'] > 0 ) { $alltotals[$cnt['id']] = $cnt['progressDetail']['total']; } echo "\n"; @flush(); } if ($status == "Downloading") { $total = $cnt['progressDetail']['total']; $current = $cnt['progressDetail']['current']; $alltotals[$cnt['id']] = $cnt['progressDetail']['current']; if ($total > 0) { $percentage = round(($current/$total) * 100); echo "\n"; } else { // Docker must not know the total download size (http-chunked or something?) // just show the current download progress without the percentage echo "\n"; } @flush(); } }; function pullImage($image) { global $DockerClient, $pullecho, $alltotals; $alltotals = array(); if (! preg_match("/:[\w]*$/i", $image)) $image .= ":latest"; readfile("/usr/local/emhttp/plugins/dynamix.docker.manager/log.htm"); echo ""; @flush(); $DockerClient->pullImage($image, $pullecho); echo "\n"; } function sizeToHuman($size) { $units = ['B','KB','MB','GB']; $unitsIndex = 0; while ($size > 1024 && (($unitsIndex+1) < count($units))) { $size /= 1024; $unitsIndex++; } return ceil($size) . " " . $units[$unitsIndex]; } function xml_encode($string) { return htmlspecialchars($string, ENT_XML1, 'UTF-8'); } function xml_decode($string) { return strval(html_entity_decode($string, ENT_XML1, 'UTF-8')); } function postToXML($post, $setOwnership = FALSE){ $dom = new domDocument; $dom->appendChild($dom->createElement( "Container" )); $xml = simplexml_import_dom( $dom ); $xml["version"] = 2; $xml->Name = xml_encode($post['contName']); $xml->Repository = xml_encode($post['contRepository']); $xml->Registry = xml_encode($post['contRegistry']); $xml->Network = xml_encode($post['contNetwork']); $xml->Privileged = (strtolower($post["contPrivileged"]) == 'on') ? 'true' : 'false'; $xml->Support = xml_encode($post['contSupport']); $xml->Overview = xml_encode($post['contOverview']); $xml->Category = xml_encode($post['contCategory']); $xml->WebUI = xml_encode($post['contWebUI']); $xml->Icon = xml_encode($post['contIcon']); $xml->ExtraParams = xml_encode($post['contExtraParams']); # V1 compatibility $xml->Description = xml_encode($post['contOverview']); $xml->Networking->Mode = xml_encode($post['contNetwork']); $xml->Networking->addChild("Publish"); $xml->addChild("Data"); $xml->addChild("Environment"); for ($i = 0; $i < count($post["confName"]); $i++) { $Type = $post['confType'][$i]; $config = $xml->addChild('Config'); $config->{0} = xml_encode($post['confValue'][$i]); $config['Name'] = xml_encode($post['confName'][$i]); $config['Target'] = xml_encode($post['confTarget'][$i]); $config['Default'] = xml_encode($post['confDefault'][$i]); $config['Mode'] = xml_encode($post['confMode'][$i]); $config['Description'] = xml_encode($post['confDescription'][$i]); $config['Type'] = xml_encode($post['confType'][$i]); $config['Display'] = xml_encode($post['confDisplay'][$i]); $config['Required'] = xml_encode($post['confRequired'][$i]); $config['Mask'] = xml_encode($post['confMask'][$i]); # V1 compatibility if ($Type == "Port"){ $port = $xml->Networking->Publish->addChild("Port"); $port->HostPort = $post['confValue'][$i]; $port->ContainerPort = $post['confTarget'][$i]; $port->Protocol = $post['confMode'][$i]; } else if ($Type == "Path"){ $path = $xml->Data->addChild("Volume"); $path->HostDir = $post['confValue'][$i]; $path->ContainerDir = $post['confTarget'][$i]; $path->Mode = $post['confMode'][$i]; } else if ($Type == "Variable"){ $variable = $xml->Environment->addChild("Variable"); $variable->Value = $post['confValue'][$i]; $variable->Name = $post['confTarget'][$i]; $variable->Mode = $post['confMode'][$i]; } } $dom = new DOMDocument('1.0'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->loadXML($xml->asXML()); return $dom->saveXML(); } function xmlToVar($xml) { global $var; $out = array(); $xml = (is_file($xml)) ? simplexml_load_file($xml) : simplexml_load_string($xml); $out['Name'] = xml_decode($xml->Name); $out['Repository'] = xml_decode($xml->Repository); $out['Registry'] = xml_decode($xml->Registry); $out['Network'] = (isset($xml->Network)) ? xml_decode($xml->Network) : xml_decode($xml->Network['Default']); $out['Privileged'] = xml_decode($xml->Privileged); $out['Support'] = xml_decode($xml->Support); $out['Overview'] = stripslashes(xml_decode($xml->Overview)); $out['Category'] = xml_decode($xml->Category); $out['WebUI'] = xml_decode($xml->WebUI); $out['Icon'] = xml_decode($xml->Icon); $out['ExtraParams'] = xml_decode($xml->ExtraParams); $out['Config'] = array(); if (isset($xml->Config)) { foreach ($xml->Config as $config) { $c = array(); $c['Value'] = strlen(xml_decode($config)) ? xml_decode($config) : xml_decode($config['Default']) ; foreach ($config->attributes() as $key => $value) $c[$key] = xml_decode(xml_decode($value)); $out['Config'][] = $c; } } # V1 compatibility if ($xml["version"] != "2"){ if (isset($xml->Networking->Mode)){ $out['Network'] = xml_decode($xml->Networking->Mode); } if (isset($xml->Description)) { $out['Overview'] = stripslashes(xml_decode($xml->Description)); } if (isset($xml->Networking->Publish->Port)) { $portNum = 0; foreach ($xml->Networking->Publish->Port as $port) { $portNum += 1; $out['Config'][] = array('Name' => "Port ${portNum}", 'Target' => xml_decode($port->ContainerPort), 'Default' => xml_decode($port->HostPort), 'Value' => xml_decode($port->HostPort), 'Mode' => xml_decode($port->Protocol), 'Description' => '', 'Type' => 'Port', 'Display' => 'always', 'Required' => 'true', 'Mask' => 'false', ); } } if (isset($xml->Data->Volume)) { $volNum = 0; foreach ($xml->Data->Volume as $vol) { $volNum += 1; $out['Config'][] = array('Name' => "Path ${volNum}", 'Target' => xml_decode($vol->ContainerDir), 'Default' => xml_decode($vol->HostDir), 'Value' => xml_decode($vol->HostDir), 'Mode' => xml_decode($vol->Mode), 'Description' => '', 'Type' => 'Path', 'Display' => 'always', 'Required' => 'true', 'Mask' => 'false', ); } } if (isset($xml->Environment->Variable)) { $varNum = 0; foreach ($xml->Environment->Variable as $var) { $varNum += 1; $out['Config'][] = array('Name' => "Variable ${varNum}", 'Target' => xml_decode($var->Name), 'Default' => xml_decode($var->Value), 'Value' => xml_decode($var->Value), 'Mode' => '', 'Description' => '', 'Type' => 'Variable', 'Display' => 'always', 'Required' => 'false', 'Mask' => 'false', ); } } } return $out; } function xmlToCommand($xml) { global $var; $xml = xmlToVar($xml); $cmdName = (strlen($xml['Name'])) ? '--name="' . $xml['Name'] . '"' : ""; $cmdPrivileged = (strtolower($xml['Privileged']) == 'true') ? '--privileged="true"' : ""; $cmdNetwork = '--net="'.strtolower($xml['Network']).'"'; $Volumes = array(''); $Ports = array(''); $Variables = array(''); $Devices = array(''); # Bind Time $Variables[] = 'TZ="' . $var['timeZone'] . '"'; # Add HOST_OS variable $Variables[] = 'HOST_OS="unRAID"'; foreach ($xml['Config'] as $key => $config) { $confType = strtolower(strval($config['Type'])); $hostConfig = strlen($config['Value']) ? $config['Value'] : $config['Default']; $containerConfig = strval($config['Target']); $Mode = strval($config['Mode']); if (! strlen($containerConfig)) continue; if ($confType == "path") { $Volumes[] = sprintf( '"%s":"%s":%s', $hostConfig, $containerConfig, $Mode); } elseif ($confType == 'port') { $Ports[] = sprintf("%s:%s/%s", $hostConfig, $containerConfig, $Mode); } elseif ($confType == "variable") { $Variables[] = sprintf('%s="%s"', $containerConfig, $hostConfig); } elseif ($confType == "device") { $Devices[] = '"'.$containerConfig.'"'; } } $cmd = sprintf('/plugins/dynamix.docker.manager/scripts/docker run -d %s %s %s %s %s %s %s %s %s', $cmdName, $cmdNetwork, $cmdPrivileged, implode(' -e ', $Variables), implode(' -p ', $Ports), implode(' -v ', $Volumes), implode(' --device=', $Devices), $xml['ExtraParams'], $xml['Repository']); $cmd = preg_replace('/\s+/', ' ', $cmd); return array($cmd, $xml['Name'], $xml['Repository']); } function getXmlVal($xml, $element, $attr=null, $pos=0) { $xml = (is_file($xml)) ? simplexml_load_file($xml) : simplexml_load_string($xml); $element = $xml->xpath("//$element")[$pos]; return isset($element) ? (isset($element[$attr]) ? strval($element[$attr]) : strval($element)) : ""; } function setXmlVal(&$xml, $value, $el, $attr=null, $pos=0) { global $echo; $xml = (is_file($xml)) ? simplexml_load_file($xml) : simplexml_load_string($xml); $element = $xml->xpath("//$el")[$pos]; if (! isset($element)) $element = $xml->addChild($el); if ($attr) { $element[$attr] = $value; } else { $element->{0} = $value; } $dom = new DOMDocument('1.0'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->loadXML($xml->asXML()); $xml = $dom->saveXML(); } # ██████╗ ██████╗ ██████╗ ███████╗ # ██╔════╝██╔═══██╗██╔══██╗██╔════╝ # ██║ ██║ ██║██║ ██║█████╗ # ██║ ██║ ██║██║ ██║██╔══╝ # ╚██████╗╚██████╔╝██████╔╝███████╗ # ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ## ## CREATE CONTAINER ## if (isset($_POST['contName'])) { $postXML = postToXML($_POST, TRUE); // Get the command line list($cmd, $Name, $Repository) = xmlToCommand($postXML); // Run dry if ($_POST['dryRun'] == "true") { echo "
".htmlentities($postXML).""; echo "
".htmlentities($cmd).""; echo '