docker-decompose/docker-decompose.php

153 lines
3.7 KiB
PHP

#!/usr/bin/php
<?php
const COMPOSE_FILE = "docker-compose.yml";
const COMPOSE_BINARY = "docker-compose";
function cin($trim = true, $lower = true)
{
$input = fgets(STDIN);
if ($trim) {
$input = trim($input);
}
if ($lower) {
$input = strtolower($input);
}
return $input;
}
function println($w)
{
echo $w . "\n";
}
class DecomposerApp
{
/**
* @var false|string
*/
private $root;
public function __construct()
{
$this->checkBinary();
$this->root = getcwd();
println("Working in directory: " . $this->root);
$this->checkComposeFile();
$existing = false;
if ($this->checkRunningContainers()) {
$existing = true;
println("There are existing containers. Do you want to export them? [y/n]");
if (cin() != "y") {
println("Canceling...");
return;
}
} else {
$this->startContainers();
}
if ($this->checkRunningContainers() && count($this->containerNames) > 0) {
println("Exporting " . count($this->containerNames) . " images...");
foreach ($this->containerNames as $name) {
$this->exportContainer($name);
}
} else {
throw new RuntimeException("Something went wrong. There is no containers detected.");
}
if($existing){
println("Do you want to remove running containers? [y/n]");
if (cin() == "y") {
$this->removeContainers();
}
}else{
$this->removeContainers();
}
println("Done");
}
function startContainers()
{
println("Starting containers...");
println(shell_exec("docker-compose up -d"));
}
function exportContainer($name)
{
println("Creating image of " . $name . "...");
println(shell_exec("docker commit " . $name . " " . $name));
println("Exporting image to file...");
println(shell_exec("docker save -o " . $name . ".tar " . $name . ":latest"));
println("Removing image...");
println(shell_exec("docker image rm " . $name . ":latest"));
if (!file_exists($name . ".tar")) {
throw new RuntimeException("Unable to find output image file");
}
}
function removeContainers()
{
println("Removing containers...");
println(shell_exec("docker-compose down -v --remove-orphans"));
}
function checkBinary()
{
$compose = @shell_exec("which " . COMPOSE_BINARY);
if (!file_exists(trim($compose))) {
throw new RuntimeException(COMPOSE_BINARY . " binary was not found in PATH");
}
}
function checkComposeFile()
{
if (!file_exists($this->root . "/" . COMPOSE_FILE)) {
throw new RuntimeException(COMPOSE_FILE . " was not found in " . $this->root);
}
}
function checkRunningContainers(): bool
{
$running_data = @shell_exec("docker-compose ps");
$running_data = explode("\n", trim($running_data));
if (count($running_data) > 2) {
$this->containerNames = [];
for ($i = 2; $i < count($running_data); $i++) {
$parts = explode(" ", $running_data[$i], 2);
$this->containerNames[] = $parts[0];
}
foreach ($running_data as $row) {
println(trim($row));
}
return true;
}
return false;
}
private $containerNames = [];
}
try {
$app = new DecomposerApp();
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
exit(1);
} finally {
echo "\n";
}