server->uuid))]; } public function uniqueId(): string { return $this->server->uuid; } public function __construct(public Server $server) { } public function handle(): void { $queuedCount = 0; $this->server->applications()->each(function ($application) use ($queuedCount) { $count = data_get($application->deployments(), 'count', 0); $queuedCount += $count; }); if ($queuedCount > 0) { ray('DockerCleanupJob: ApplicationDeploymentQueue is not empty, skipping')->color('orange'); return; } try { if (!$this->server->isFunctional()) { return; } $this->dockerRootFilesystem = "/"; $this->usageBefore = $this->getFilesystemUsage(); if ($this->usageBefore >= $this->server->settings->cleanup_after_percentage) { ray('Cleaning up ' . $this->server->name)->color('orange'); instant_remote_process(['docker image prune -af'], $this->server); instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $this->server); instant_remote_process(['docker builder prune -af'], $this->server); $usageAfter = $this->getFilesystemUsage(); if ($usageAfter < $this->usageBefore) { ray('Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $this->server->name)->color('orange'); send_internal_notification('DockerCleanupJob done: Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $this->server->name); } else { ray('DockerCleanupJob failed to save disk space on ' . $this->server->name)->color('orange'); } } else { ray('No need to clean up ' . $this->server->name)->color('orange'); } } catch (\Throwable $e) { send_internal_notification('DockerCleanupJob failed with: ' . $e->getMessage()); ray($e->getMessage())->color('orange'); throw $e; } } private function getFilesystemUsage() { return instant_remote_process(["df '{$this->dockerRootFilesystem}'| tail -1 | awk '{ print $5}' | sed 's/%//g'"], $this->server, false); } }