import Docker from "dockerode"; import type { ContainerStats } from "dockerode"; import type { DockerContainerResult } from "@/lib/types/widget-result"; const docker = new Docker({ socketPath: process.env.DOCKER_SOCKET_PATH ?? "/var/run/docker.sock", }); function calcCpuPercent(stats: ContainerStats): number | null { const cpuDelta = stats.cpu_stats.cpu_usage.total_usage - stats.precpu_stats.cpu_usage.total_usage; const systemDelta = stats.cpu_stats.system_cpu_usage - stats.precpu_stats.system_cpu_usage; const cpuCount = stats.cpu_stats.online_cpus || stats.cpu_stats.cpu_usage.percpu_usage?.length || 1; if (systemDelta <= 0 || cpuDelta < 0) return null; return (cpuDelta / systemDelta) * cpuCount * 100; } const EPOCH_STARTED_AT = "0001-01-01T00:00:00Z"; export async function collectDockerContainer( containerName: string, showStats: boolean ): Promise { const container = docker.getContainer(containerName); const inspect = await container.inspect(); let cpuPercent: number | null = null; let memUsageBytes: number | null = null; let memLimitBytes: number | null = null; if (showStats && inspect.State.Running) { const stats = await container.stats({ stream: false }); cpuPercent = calcCpuPercent(stats); memUsageBytes = stats.memory_stats.usage ?? null; memLimitBytes = stats.memory_stats.limit ?? null; } const startedAt = inspect.State.StartedAt && inspect.State.StartedAt !== EPOCH_STARTED_AT ? inspect.State.StartedAt : null; return { status: (inspect.State.Status as DockerContainerResult["status"]) || "unknown", health: (inspect.State.Health?.Status as DockerContainerResult["health"]) || "none", startedAt, uptimeSeconds: startedAt ? Math.max(0, Math.floor((Date.now() - new Date(startedAt).getTime()) / 1000)) : null, restartCount: inspect.RestartCount ?? 0, cpuPercent, memUsageBytes, memLimitBytes, image: inspect.Config.Image, }; }