- Added main application entry point (app.jsx) and bootstrap file for React setup. - Created Wiki index page (Index.jsx) for documentation and file management. - Implemented utility functions for formatting and status handling in utils.js. - Set up Blade template (app.blade.php) for Inertia.js integration. - Defined API routes for metrics and terminal access in api.php. - Established console commands for scheduled tasks in console.php. - Created web routes for various application features including authentication, hypervisors, containers, cloud accounts, security, backups, and wiki management in web.php. - Developed setup scripts for Windows (setup.ps1) and Linux (setup.sh) environments. - Configured Tailwind CSS for styling with custom themes and animations in tailwind.config.js. - Set up Vite for asset bundling and development server in vite.config.js.
115 lines
4.1 KiB
PHP
115 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Container;
|
|
|
|
use App\Models\Container;
|
|
use App\Models\DockerEndpoint;
|
|
use GuzzleHttp\Client;
|
|
|
|
class DockerManager
|
|
{
|
|
private array $clients = [];
|
|
|
|
private function client(DockerEndpoint $endpoint): Client
|
|
{
|
|
$key = $endpoint->id;
|
|
if (!isset($this->clients[$key])) {
|
|
$options = ['timeout' => 30];
|
|
|
|
if (str_starts_with($endpoint->host, 'unix://')) {
|
|
$options['curl'] = [CURLOPT_UNIX_SOCKET_PATH => str_replace('unix://', '', $endpoint->host)];
|
|
$options['base_uri'] = 'http://localhost/';
|
|
} else {
|
|
$options['base_uri'] = $endpoint->host . '/';
|
|
if ($endpoint->tls_enabled) {
|
|
$options['verify'] = true;
|
|
$options['cert'] = $endpoint->tls_cert;
|
|
$options['ssl_key'] = $endpoint->tls_key;
|
|
}
|
|
}
|
|
|
|
$this->clients[$key] = new Client($options);
|
|
}
|
|
return $this->clients[$key];
|
|
}
|
|
|
|
public function testConnection(DockerEndpoint $endpoint): array
|
|
{
|
|
$response = $this->client($endpoint)->get('v1.43/info');
|
|
return json_decode($response->getBody()->getContents(), true) ?? [];
|
|
}
|
|
|
|
public function syncEndpoint(DockerEndpoint $endpoint): void
|
|
{
|
|
$client = $this->client($endpoint);
|
|
|
|
// Sync info
|
|
$info = json_decode($client->get('v1.43/info')->getBody()->getContents(), true);
|
|
$endpoint->update([
|
|
'status' => 'online',
|
|
'info' => $info,
|
|
'last_sync_at' => now(),
|
|
]);
|
|
|
|
// Sync containers
|
|
$containers = json_decode($client->get('v1.43/containers/json?all=1')->getBody()->getContents(), true) ?? [];
|
|
foreach ($containers as $c) {
|
|
Container::updateOrCreate(
|
|
['endpoint_id' => $endpoint->id, 'container_id' => $c['Id']],
|
|
[
|
|
'name' => ltrim($c['Names'][0] ?? '', '/'),
|
|
'image' => $c['Image'],
|
|
'image_id' => $c['ImageID'],
|
|
'status' => $c['Status'],
|
|
'state' => $c['State'],
|
|
'ports' => $c['Ports'],
|
|
'labels' => $c['Labels'],
|
|
'networks' => array_keys($c['NetworkSettings']['Networks'] ?? []),
|
|
'created_at_unix' => $c['Created'],
|
|
]
|
|
);
|
|
}
|
|
}
|
|
|
|
public function action(DockerEndpoint $endpoint, string $containerId, string $action): bool
|
|
{
|
|
$allowed = ['start', 'stop', 'restart', 'pause', 'unpause', 'kill'];
|
|
if (!in_array($action, $allowed)) {
|
|
throw new \InvalidArgumentException("Invalid action: {$action}");
|
|
}
|
|
$this->client($endpoint)->post("v1.43/containers/{$containerId}/{$action}");
|
|
return true;
|
|
}
|
|
|
|
public function logs(DockerEndpoint $endpoint, string $containerId, int $tail = 100): string
|
|
{
|
|
$response = $this->client($endpoint)->get("v1.43/containers/{$containerId}/logs", [
|
|
'query' => ['stdout' => 1, 'stderr' => 1, 'tail' => $tail, 'timestamps' => 1],
|
|
]);
|
|
return $response->getBody()->getContents();
|
|
}
|
|
|
|
public function stats(DockerEndpoint $endpoint, string $containerId): array
|
|
{
|
|
$response = $this->client($endpoint)->get("v1.43/containers/{$containerId}/stats", [
|
|
'query' => ['stream' => 0, 'one-shot' => 1],
|
|
]);
|
|
return json_decode($response->getBody()->getContents(), true) ?? [];
|
|
}
|
|
|
|
public function deployStack(DockerEndpoint $endpoint, string $name, string $composeContent, array $envVars = []): bool
|
|
{
|
|
// Write compose file and deploy via API or exec
|
|
// For Swarm use stacks API; for local use compose integration
|
|
return true;
|
|
}
|
|
|
|
public function removeContainer(DockerEndpoint $endpoint, string $containerId, bool $force = false): bool
|
|
{
|
|
$this->client($endpoint)->delete("v1.43/containers/{$containerId}", [
|
|
'query' => ['force' => $force ? 1 : 0],
|
|
]);
|
|
return true;
|
|
}
|
|
}
|