fix: docker image-remove throws on daemon error; add sync-orphans endpoint

- removeImage now throws RuntimeException when docker rmi output contains
  'Error' or 'conflict' so the API returns success:false with the message
- Added docker/sync-orphans endpoint (admin only) to register existing
  Docker containers not tracked in the NovaCPX DB (e.g. after a restore)
This commit is contained in:
2026-06-22 12:32:44 +00:00
parent 55f5fc1da9
commit 1c4a06d31e
2 changed files with 28 additions and 1 deletions
+23
View File
@@ -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),
};
+5 -1
View File
@@ -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 ────────────────────────────────────────────────────