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(); 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 trimLine($text){ return preg_replace("/([\n^])[\s]+/", '$1', $text); } function pullImage($image) { if (! preg_match("/:[\w]*$/i", $image)) $image .= ":latest"; readfile("/usr/local/emhttp/plugins/dynamix.docker.manager/log.htm"); echo ''; echo ""; @flush(); $fp = stream_socket_client('unix:///var/run/docker.sock', $errno, $errstr); if ($fp === false) { echo "Couldn't create socket: [$errno] $errstr"; return NULL; } $out="POST /images/create?fromImage=$image HTTP/1.1\r\nConnection: Close\r\n\r\n"; fwrite($fp, $out); $cid = ""; $cstatus=""; $alltotals = []; while (!feof($fp)) { $cnt = json_decode( fgets($fp, 5000), TRUE ); $id = ( isset( $cnt['id'] )) ? $cnt['id'] : ""; if ($id != $cid && strlen($id)) { $cid = $id; $cstatus = ""; echo ""; @flush(); } $status = ( isset( $cnt['status'] )) ? $cnt['status'] : ""; if ($status != $cstatus && strlen($status)) { if ( isset($cnt['progressDetail']['total']) && $cnt['progressDetail']['total'] > 0 ) { $alltotals[$cnt['id']] = $cnt['progressDetail']['total']; } $cstatus = $status; echo ""; @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(); } } 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 xmlToCommand($xmlFile){ global $var; $doc = new DOMDocument(); $doc->loadXML($xmlFile); $Name = $doc->getElementsByTagName( "Name" )->item(0)->nodeValue; $cmdName = (strlen($Name)) ? '--name="' . $Name . '"' : ""; $Privileged = $doc->getElementsByTagName( "Privileged" )->item(0)->nodeValue; $cmdPrivileged = (strtolower($Privileged) == 'true') ? '--privileged="true"' : ""; $Repository = $doc->getElementsByTagName( "Repository" )->item(0)->nodeValue; $Mode = $doc->getElementsByTagName( "Mode" )->item(0)->nodeValue; $cmdMode = '--net="'.strtolower($Mode).'"'; $BindTime = $doc->getElementsByTagName( "BindTime" )->item(0)->nodeValue; // $cmdBindTime = (strtolower($BindTime) == "true") ? '"/etc/localtime":"/etc/localtime":ro' : ''; $cmdBindTime = (strtolower($BindTime) == "true") ? 'TZ="' . $var['timeZone'] . '"' : ''; $Ports = array(''); foreach($doc->getElementsByTagName('Port') as $port){ $ContainerPort = $port->getElementsByTagName( "ContainerPort" )->item(0)->nodeValue; if (! strlen($ContainerPort)){ continue; } $HostPort = $port->getElementsByTagName( "HostPort" )->item(0)->nodeValue; $Protocol = $port->getElementsByTagName( "Protocol" )->item(0)->nodeValue; $Ports[] = sprintf("%s:%s/%s", $HostPort, $ContainerPort, $Protocol); } $Volumes = array(''); foreach($doc->getElementsByTagName('Volume') as $volume){ $ContainerDir = $volume->getElementsByTagName( "ContainerDir" )->item(0)->nodeValue; if (! strlen($ContainerDir)){ continue; } $HostDir = $volume->getElementsByTagName( "HostDir" )->item(0)->nodeValue; $DirMode = $volume->getElementsByTagName( "Mode" )->item(0)->nodeValue; $Volumes[] = sprintf( '"%s":"%s":%s', $HostDir, $ContainerDir, $DirMode); } // if (strlen($cmdBindTime)) { // $Volumes[] = $cmdBindTime; // } $Variables = array(''); foreach($doc->getElementsByTagName('Variable') as $variable){ $VariableName = $variable->getElementsByTagName( "Name" )->item(0)->nodeValue; if (! strlen($VariableName)){ continue; } $VariableValue = $variable->getElementsByTagName( "Value" )->item(0)->nodeValue; $Variables[] = sprintf('%s="%s"', $VariableName, $VariableValue); } if (strlen($cmdBindTime)) { $Variables[] = $cmdBindTime; } $templateExtraParams = ''; if ( $doc->getElementsByTagName( "ExtraParams" )->length > 0 ) { $templateExtraParams = $doc->getElementsByTagName( "ExtraParams" )->item(0)->nodeValue; } $cmd = sprintf('/plugins/dynamix.docker.manager/scripts/docker run -d %s %s %s %s %s %s %s %s', $cmdName, $cmdMode, $cmdPrivileged, implode(' -e ', $Variables), implode(' -p ', $Ports), implode(' -v ', $Volumes), $templateExtraParams, $Repository); $cmd = preg_replace('/\s+/', ' ', $cmd); return array($cmd, $Name, $Repository); } function addElement($doc, $el, $elName, $elVal){ $node = $el->appendChild($doc->createElement($elName)); $node->appendChild($doc->createTextNode($elVal)); return $node; } function postToXML($post, $setOwnership = FALSE){ global $DockerUpdate; $doc = new DOMDocument('1.0', 'utf-8'); $doc->preserveWhiteSpace = false; $doc->formatOutput = true; $root = $doc->createElement('Container'); $root = $doc->appendChild($root); $docName = $root->appendChild($doc->createElement('Name')); if ( isset( $post[ 'Description' ] )) addElement($doc, $root, 'Description', $post[ 'Description' ]); if ( isset( $post[ 'Registry' ] )) addElement($doc, $root, 'Registry', $post[ 'Registry' ]); $docRepository = $root->appendChild($doc->createElement('Repository')); $BindTime = $root->appendChild($doc->createElement('BindTime')); $Privileged = $root->appendChild($doc->createElement('Privileged')); $Environment = $root->appendChild($doc->createElement('Environment')); $docNetworking = $root->appendChild($doc->createElement('Networking')); $Data = $root->appendChild($doc->createElement('Data')); $Version = $root->appendChild($doc->createElement('Version')); $Mode = $docNetworking->appendChild($doc->createElement('Mode')); $Publish = $docNetworking->appendChild($doc->createElement('Publish')); $Name = preg_replace('/\s+/', '', $post["containerName"]); // Editor Values if ( isset( $post[ 'WebUI' ] )) addElement($doc, $root, 'WebUI', $post[ 'WebUI' ]); if ( isset( $post[ 'Banner' ] )) addElement($doc, $root, 'Banner', $post[ 'Banner' ]); if ( isset( $post[ 'Icon' ] )) addElement($doc, $root, 'Icon', $post[ 'Icon' ]); if ( isset( $post[ 'ExtraParams' ] )) addElement($doc, $root, 'ExtraParams', $post[ 'ExtraParams' ]); $docName->appendChild($doc->createTextNode($Name)); $docRepository->appendChild($doc->createTextNode($post["Repository"])); $BindTime->appendChild($doc->createTextNode((strtolower($post["BindTime"]) == 'on') ? 'true' : 'false')); $Privileged->appendChild($doc->createTextNode((strtolower($post["Privileged"]) == 'on') ? 'true' : 'false')); $Mode->appendChild($doc->createTextNode(strtolower($post["NetworkType"]))); for ($i = 0; $i < count($post["hostPort"]); $i++){ if (! strlen($post["containerPort"][$i])) { continue; } $protocol = $post["portProtocol"][$i]; $Port = $Publish->appendChild($doc->createElement('Port')); $HostPort = $Port->appendChild($doc->createElement('HostPort')); $ContainerPort = $Port->appendChild($doc->createElement('ContainerPort')); $Protocol = $Port->appendChild($doc->createElement('Protocol')); $HostPort->appendChild($doc->createTextNode(trim($post["hostPort"][$i]))); $ContainerPort->appendChild($doc->createTextNode($post["containerPort"][$i])); $Protocol->appendChild($doc->createTextNode($protocol)); } for ($i = 0; $i < count($post["VariableName"]); $i++){ if (! strlen($post["VariableName"][$i])) { continue; } $Variable = $Environment->appendChild($doc->createElement('Variable')); $VariableName = $Variable->appendChild($doc->createElement('Name')); $VariableValue = $Variable->appendChild($doc->createElement('Value')); $VariableName->appendChild($doc->createTextNode(trim($post["VariableName"][$i]))); $VariableValue->appendChild($doc->createTextNode(trim($post["VariableValue"][$i]))); } for ($i = 0; $i < count($post["hostPath"]); $i++){ if (! strlen($post["hostPath"][$i])) { continue; } if (! strlen($post["containerPath"][$i])) { continue; } $tmpMode = $post["hostWritable"][$i]; if ($setOwnership){ prepareDir($post["hostPath"][$i]); } $Volume = $Data->appendChild($doc->createElement('Volume')); $HostDir = $Volume->appendChild($doc->createElement('HostDir')); $ContainerDir = $Volume->appendChild($doc->createElement('ContainerDir')); $DirMode = $Volume->appendChild($doc->createElement('Mode')); $HostDir->appendChild($doc->createTextNode($post["hostPath"][$i])); $ContainerDir->appendChild($doc->createTextNode($post["containerPath"][$i])); $DirMode->appendChild($doc->createTextNode($tmpMode)); } $currentVersion = $DockerUpdate->getRemoteVersion($post["Registry"], $post["Repository"]); $Version->appendChild($doc->createTextNode($currentVersion)); return $doc->saveXML(); } if ($_POST){ $postXML = postToXML($_POST, TRUE); // Get the command line list($cmd, $Name, $Repository) = xmlToCommand($postXML); // Saving the generated configuration file. $userTmplDir = $dockerManPaths['templates-user']; if(is_dir($userTmplDir) === FALSE){ mkdir($userTmplDir, 0777, true); } if(strlen($Name)) { $filename = sprintf('%s/my-%s.xml', $userTmplDir, $Name); file_put_contents($filename, $postXML); } // Pull image pullImage($Repository); // Remove existing container if (ContainerExist($Name)){ $_GET['cmd'] = "/plugins/dynamix.docker.manager/scripts/docker rm -f $Name"; include($dockerManPaths['plugin'] . "/include/Exec.php"); } // Remove old container if renamed $existing = isset($_POST['existingContainer']) ? $_POST['existingContainer'] : FALSE; if ($existing && ContainerExist($existing)){ $_GET['cmd'] = "/plugins/dynamix.docker.manager/scripts/docker rm -f $existing"; include($dockerManPaths['plugin'] . "/include/Exec.php"); } // Injecting the command in $_GET variable and executing. $_GET['cmd'] = $cmd; include($dockerManPaths['plugin'] . "/include/Exec.php"); $DockerTemplates->removeInfo($Name); $DockerUpdate->syncVersions($Name); echo '