diff --git a/panel/api/endpoints/docker.php b/panel/api/endpoints/docker.php index 32e99e1..8f4e6d5 100644 --- a/panel/api/endpoints/docker.php +++ b/panel/api/endpoints/docker.php @@ -265,5 +265,28 @@ match ($action) { Response::success($result, ucfirst($appKey) . ' launched successfully'); })(), + 'sync-orphans' => (function() use ($dm, $isAdmin) { + if (!$isAdmin) Response::error('Admin only', 403); + $result = shell_exec('docker ps -a --format "{{json .}}" 2>/dev/null') ?? ''; + $db = \DB::getInstance(); + $added = 0; + foreach (explode("\n", trim($result)) as $line) { + if (!$line) continue; + $c = json_decode($line, true); + if (!$c) continue; + $cid = $c['ID'] ?? ''; + $name = ltrim($c['Names'] ?? '', '/'); + $img = $c['Image'] ?? ''; + $st = $c['State'] ?? 'unknown'; + if (!$cid) continue; + $ex = $db->fetchOne('SELECT id FROM docker_containers WHERE container_id=?', [$cid]); + if (!$ex) { + $db->execute('INSERT INTO docker_containers (container_id,name,image,status,account_id,created_at) VALUES (?,?,?,?,0,datetime("now"))', [$cid,$name,$img,$st]); + $added++; + } + } + Response::success(['added' => $added], "Synced $added orphaned containers"); + })(), + default => Response::error("Unknown docker action: $action", 404), }; diff --git a/panel/lib/DockerManager.php b/panel/lib/DockerManager.php index db85d31..6030ac0 100644 --- a/panel/lib/DockerManager.php +++ b/panel/lib/DockerManager.php @@ -190,7 +190,11 @@ SH; public function removeImage(string $imageId): string { if (!preg_match('/^[a-zA-Z0-9:._\-\/]+$/', $imageId)) throw new RuntimeException("Invalid image ID"); - return trim(shell_exec("sudo docker rmi " . escapeshellarg($imageId) . " 2>&1") ?? ''); + $out = trim(shell_exec("sudo docker rmi " . escapeshellarg($imageId) . " 2>&1") ?? ''); + if (stripos($out, "Error") !== false || stripos($out, "conflict") !== false) { + throw new \RuntimeException($out); + } + return $out; } // ── Volumes & Networks ────────────────────────────────────────────────────