path = $path; $this->options = $options; } public function getPath(): string { return $this->path; } public function getName(): string { return $this->options['name'] ?? basename($this->path); } public function getComposeFile(): string { return $this->path . "/" . ($this->options['compose']??"docker-compose.yml"); } public function getContainersTable(OutputInterface $output): Table { exec("docker-compose -f " . escapeshellarg($this->getComposeFile()) . " ps -q", $ids, $ret); if (count($ids) === 0) { $json = []; } else { exec("docker inspect ".join(" ",$ids), $out, $ret); $json = json_decode(join("", $out)); } $table = new Table($output); $table->setStyle("box"); $table->setHeaders([ "Name", "Status", "Image", "Ports" ]); foreach ($json as $container) { $startedTs = preg_replace('/(\.([0-9]+)Z)$/', '+0100', $container->State->StartedAt); $s = date_parse($startedTs); $started = mktime($s['hour'], $s['minute'], $s['second'], $s['month'], $s['day'], $s['year']) + 3600; if ($container->State->Dead) { $status = "".self::BULLET." ".$container->State->Status; } elseif ($container->State->Restarting) { $status = "".self::BULLET." ".$container->State->Status; } elseif ($container->State->Running) { $elapsed = time() - $started; if ($elapsed > 60) { $em = floor($elapsed / 60); $es = $elapsed - ($em * 60); if ($em>60) { $eh = floor($em / 60); $em = $em - ($eh * 60); $elapsed = sprintf("%dh%dm%ds", $eh, $em, $es); } else { $elapsed = sprintf("%dm%ds", $em, $es); } } else { $elapsed = sprintf("%ds", $elapsed); } $status = "".self::BULLET." ".$container->State->Status." ({$elapsed})"; } else { $status = "".self::BULLET." ".$container->State->Status; } $ports = $container->Config->ExposedPorts??[]; $ports = array_keys((array)$ports); $table->addRow([ $container->Name, $status, $container->Config->Image, join(", ", $ports) ]); } return $table; } }