Menu="Docker:1"
Title="Docker Containers"
Tag="cubes"
Cond="(pgrep('dockerd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2017, Lime Technology
 * Copyright 2014-2017, Guilherme Jardim, Eric Schultz, Jon Panozzo.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation.
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 */
?>
<?
// Add the Docker JSON client
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";

$DockerClient    = new DockerClient();
$DockerUpdate    = new DockerUpdate();
$DockerTemplates = new DockerTemplates();
?>
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.ui.css">
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.switchbutton.css">
<style>
body {-webkit-overflow-scrolling: touch;}
img.started{opacity:1.0;}
img.stopped{opacity:0.3;}
.log{cursor:zoom-in;}
.exec{cursor:pointer;}
.fa-custom{font-size: 1.3em;}
.basic{display: block;}
.advanced{display:none;white-space: nowrap;}
.iconstatus{position:absolute;z-index:2;bottom:-4px;right:-4px;font-size:1.2em;text-shadow:0 0 2px #FFF;}
.iconstatus.started{font-size:1.3em;}
.iconstatus.stopped{font-size:1.2em;}
.started{color:#009900;}
.stopped{color:#EF3D47;}
.switch-button-label.off{color:inherit;}
</style>
<form id="formAutostart" method="POST" action="/plugins/dynamix.docker.manager/include/UpdateConfig.php" target="progressFrame">
  <input type="hidden" name="action" value="autostart" />
  <input type="hidden" name="container" value="none" />
</form>
<form id="formStartStop" method="POST" action="/update.php" target="progressFrame">
  <input type="hidden" id="cmdStartStop" name="#command" value="">
  <input type="hidden" id="cmdArg1" name="#arg[1]" value="">
  <input type="hidden" id="cmdArg2" name="#arg[2]" value="">
</form>
<div id="dialog-confirm" style="display:none;" title="Dialog Title"></div>
<div id="iframe-popup" style="display:none;-webkit-overflow-scrolling:touch;"></div>
<span class="status" style="margin-top: -44px;"><input type="checkbox" class="advancedview"></span>
<table class="tablesorter shift" id="docker_containers">
	<thead>
		<tr>
			<th>&nbsp;</th>
			<th>Application</th>
			<th>Version</th>
			<th>Port Mappings <small>(App to Host)</small></th>
			<th>Volume Mappings <small>(App to Host)</small></th>
			<th width="80px" style="text-align: center">Autostart</th>
			<th>Log</th>
		</tr>
	</thead>
	<tbody id="docker_list">
		<?
		$all_containers = $DockerClient->getDockerContainers();
		if (!$all_containers) {
			$all_containers = [];
			echo "<tr><td></td><td colspan=\"7\">No Docker Containers Installed</td></tr>";
		}
		$info = $DockerTemplates->getAllInfo();
		$contextMenus = [];

		$IP = $eth0["IPADDR:0"];
		foreach ($all_containers as $ct) {
			$name           = $ct["Name"];
			$is_autostart   = ($info[$name]['autostart']) ? 'true' : 'false';
			$updateStatus   = $info[$name]['updated'];
			$updateStatus   = ($updateStatus == "true" || $updateStatus == "undef") ? 'true' : 'false';
			$running        = ($ct['Running']) ? 'true' : 'false';
			$webGuiUrl      = $info[$name]['url'];
			$contextMenus[] = sprintf("addDockerContainerContext('%s', '%s', '%s', %s, %s, %s, '%s', '%s');", addslashes($ct['Name']), addslashes($ct['ImageId']), addslashes($info[$name]['template']), $running, $updateStatus, $is_autostart, addslashes($webGuiUrl), $ct["Id"]);
			$shape          = ($ct["Running"]) ? "play" : "square";
			$status         = ($ct["Running"]) ? "started" : "stopped";

			$Icon           = $info[$name]['icon'];
			if (!$Icon) {
				$Icon = "/plugins/dynamix.docker.manager/images/question.png";
			}

			$ports = [];
			foreach ($ct['Ports'] as $p) {
				if (strlen($p['PublicPort'])) {
					$ipAddr    = sprintf("%s:%s", $IP, $p['PublicPort']);
					$outFormat = sprintf('<a href="http://%s" target="_blank">%s/%s <i class="fa fa-arrows-h" style="margin: 0 3px"></i> %s</a>', $ipAddr, $p['PrivatePort'], $p['Type'], htmlspecialchars($ipAddr));
				} else {
					$outFormat = sprintf("%s/%s", $p['PrivatePort'], $p['Type']);
				}
				$ports[] = $outFormat;
			}

			$paths = [];
			if (count($ct['Volumes'])){
				foreach ($ct['Volumes'] as $value) {
					if (preg_match('/localtime/', $value) == true) continue;
					list($host_path, $container_path, $access_mode) = explode(":", $value);

					$tip = 'Container volume \'' . $container_path . '\' has ' . ($access_mode == 'ro' ? 'read-only' : 'read-write') . ' access to Host path \'' . $host_path . '\'';

					$paths[] = sprintf('<a href="/Shares/Browse?dir=%s" target="_blank" title="%s">%s <i class="fa fa-%s" style="margin: 0 3px"></i> %s</a>', urlencode($host_path), htmlspecialchars($tip), htmlspecialchars($container_path), ($access_mode == 'ro' ? 'long-arrow-left' : 'arrows-h'), htmlspecialchars($host_path));
				}
			}
			?>
		<tr>
			<td style="width: 48px; padding: 4px">
				<?
				echo "	<div id=\"context-".htmlspecialchars($name)."\" style=\"display:block; cursor:pointer\">
							<div style=\"position: relative; width: 48px; height: 48px; margin: 0px auto;\">
								<img src=\"".htmlspecialchars($Icon)."\" class=\"".htmlspecialchars($status)."\" style=\"position: absolute; z-index: 1; top: 0; bottom: 0; left: 0; right: 0; width: 48px; height: 48px;\"/>
								<i class=\"fa iconstatus fa-$shape $status\" title=\"".htmlspecialchars($status)."\"></i>
							</div>
						</div>";

				?>
			</td>
			<td>
				<?if($info[$ct['Name']]['template']):?>
					<a class="exec" onclick="editContainer('<?=addslashes(htmlspecialchars($ct['Name']));?>','<?=addslashes(htmlspecialchars($info[$ct['Name']]['template']));?>');"><?=htmlspecialchars($ct['Name']);?></a>
				<?else:?>
					<?=htmlspecialchars($ct['Name']);?>
				<?endif;?>
				<div class="advanced" style="color:#888; width: 160px;">Container ID: <?=htmlspecialchars($ct['Id']);?></div>
				<?if($ct['BaseImage']):?>
					<div class="advanced" style="color:#888; width: 160px;"><i class="fa fa-cubes" style="margin-right: 5px"></i><?=htmlspecialchars(${ct[BaseImage]})?></div>
				<?endif;?>
				<div class="advanced" style="color:#888; width: 160px;">By:
				<?if($Registry = $info[$ct['Name']]['registry']):?>
					<a href="<?=htmlspecialchars($Registry)?>" target="_blank"><?=htmlspecialchars($ct['Image'])?></a>
				<?else:?>
					<?=htmlspecialchars($ct['Image']);?>
				<?endif;?>
				</div>
			</td>
			<td class="updatecolumn">
				<?
				$updateStatus = $info[$ct['Name']]['updated'];
				if ($updateStatus == "false") {
					echo "<a class=\"exec\" onclick=\"updateContainer('" . addslashes(htmlspecialchars($ct["Name"])) . "');\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> update ready</span></a>";
				} elseif ($updateStatus == "true") {
					echo "<span style=\"color:#44B012;white-space:nowrap;\"><i class=\"fa fa-check\"></i> up-to-date</span>";
					echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('" . addslashes(htmlspecialchars($ct["Name"])) . "');\" style=\"color:#888;\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
				} else {
					echo "<span style=\"color:#FF2400;white-space:nowrap;\"><i class=\"fa fa-exclamation-triangle\"></i> not available</span>";
					echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('" . addslashes(htmlspecialchars($ct["Name"])) . "');\" style=\"color:#888;\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
				}
				?>
			</td>
			<td style="white-space:nowrap;"><span class="docker_readmore"><?= implode("<br>", $ports); ?></span></td>
			<td style="word-break:break-all;"><span class="docker_readmore"><?= implode("<br>", $paths); ?></span></td>
			<td data-sort-value="<?=$is_autostart?>"><input type="checkbox" class="autostart" container="<?=htmlspecialchars($ct['Name']);?>" <?=$info[$ct['Name']]['autostart'] ? "checked" : ""?>></td>
			<td><a class="log" onclick="containerLogs('<?=addslashes(htmlspecialchars($ct['Name']));?>','<?=$ct['Id'];?>', false, false)"><img class="basic" src="/plugins/dynamix/icons/log.png"/><div class="advanced" style="width: 124px;"><?=htmlspecialchars($ct['Status'])?></div><div class="advanced" style="color:#888;">Created <?=htmlspecialchars($ct['Created'])?></div></a></td>
		</tr>
		<?}?>


		<?
		foreach ($DockerClient->getDockerImages() as $image) {
			if (count($image['usedBy'])) {
				continue;
			}

			$contextMenus[] = sprintf("addDockerImageContext('%s', '%s');", $image['Id'], implode(', ', $image['Tags']));

			?>
		<tr class="advanced">
			<td style="width: 48px; padding: 4px">
				<?
				echo "	<div id=\"context-".htmlspecialchars($image['Id'])."\" style=\"display:block; cursor:pointer\">
							<div style=\"position: relative; width: 48px; height: 48px; margin: 0px auto;\">
								<img src=\"/webGui/images/disk.png\" style=\"position: absolute; z-index: 1; opacity: 0.3; top: 0; bottom: 0; left: 0; right: 0; width: 48px; height: 48px;\"/>
							</div>
						</div>";

				?>
			</td>
			<td data-sort-value="ZZZZZZZZZZZ">
				<i>(orphan image)</i>
				<div style="color:#888; width: 160px;">Image ID: <?=htmlspecialchars($image['Id'])?></div>
				<?if(strpos(implode($image['Tags']), "&lt;none&gt;:&lt;none&gt;") === false):?>
					<div style="color:#888; width: 160px;"><?=implode("<br>", array_map('htmlspecialchars',$image['Tags']))?></div>
				<?endif;?>
			</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td><div class="advanced" style="width: 124px; color:#888;">Created <?=htmlspecialchars($image['Created'])?></div></td>
		</tr>
		<?}?>
	</tbody>
</table>
<input type="button" onclick="addContainer()" value="Add Container"/>
<input type="button" onclick="reloadUpdate()" value="Check for Updates"/>

<script src="/webGui/javascript/jquery.switchbutton.js"></script>
<script src="/plugins/dynamix.docker.manager/javascript/docker.js"></script>
<script>
<?if ($display['resize']):?>
function resize(bind) {
  var width = [];
  var h = $('#docker_list').height();
  var s = Math.max(window.innerHeight-300,370);
  if (h>s || bind) {
    $('#docker_list').height(s);
    $('#docker_containers tbody tr:first-child td').each(function(){width.push($(this).width());});
    $('#docker_containers thead tr th').each(function(i){$(this).width(width[i]);});
    if (!bind) $('#docker_containers thead,#docker_containers tbody').addClass('fixed');
  }
}
<?endif;?>
$(function() {
	if ($.cookie('docker_listview_mode') == 'advanced') {
		$('.advanced').show();
		$('.basic').hide();
	}

	$('.autostart').switchButton({
		labels_placement: "right"
	});
	$('.autostart').change(function () {
		$.post( "/plugins/dynamix.docker.manager/include/UpdateConfig.php", { action: "autostart", container: $(this).attr('container'), response: "json" }, function( data ) {
			$(this).prop('checked', data.autostart );
		}, "json");
	});

	$('.advancedview').switchButton({
		labels_placement: "left",
		on_label: 'Advanced View',
  		off_label: 'Basic View',
  		checked: $.cookie('docker_listview_mode') == 'advanced'
	});
	$('.advancedview').change(function () {
		$('.advanced').toggle('slow');
		$('.basic').toggle('slow');
		$.cookie('docker_listview_mode', $('.advancedview').is(':checked') ? 'advanced' : 'basic', { expires: 3650 });
	});

<?if ($display['resize']):?>
  resize();
  $(window).bind('resize',function(){resize(true);});
<?endif;?>

	$('#docker_containers').tablesorter( {sortList: [[1,0]], headers: {0: {sorter: false }, 7: {sorter: false }}});
	$('#docker_containers tr:even').addClass('odd');

	context.init({ preventDoubleContext: false });
	<?=htmlspecialchars(implode("\n\t", $contextMenus));?>

	$('.docker_readmore').readmore({maxHeight:48, moreLink: '<a href="#" style="text-align:center;"><i class="fa fa-chevron-down"></i></a>', lessLink: '<a href="#" style="text-align:center;"><i class="fa fa-chevron-up"></i></a>'});
});
</script>
