Initial commit

This commit is contained in:
kirill.labutin 2025-08-19 12:42:16 +03:00
commit caf0f55219
4 changed files with 163 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.idea/

2
composer.json Normal file
View File

@ -0,0 +1,2 @@
{
}

8
docker-decompose.iml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

152
docker-decompose.php Normal file
View File

@ -0,0 +1,152 @@
#!/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";
}