1.0.29
This commit is contained in:
44 files changed
+1672
-226
No files matched your search
@@ -1046,6 +1046,7 @@ export interface ContainerInfo {
|
||||
networks: { [networkName: string]: { ipAddress: string } };
|
||||
health?: string;
|
||||
restartCount: number;
|
||||
exitCode?: number;
|
||||
mounts: Array<{ type: string; source: string; destination: string; mode: string; rw: boolean }>;
|
||||
labels: { [key: string]: string };
|
||||
command: string;
|
||||
@@ -1081,6 +1082,39 @@ export async function listContainers(all = true, envId?: number | null): Promise
|
||||
})
|
||||
);
|
||||
|
||||
// Fetch health status via inspect for containers with healthchecks where Status
|
||||
// string doesn't include health info (Podman compat API omits it from the list endpoint).
|
||||
// Skip entirely if any container already has health in Status (Docker includes it natively).
|
||||
const healthStatuses = new Map<string, string>();
|
||||
const healthRegex = /\((healthy|unhealthy|health:\s*starting)\)/i;
|
||||
const anyHasHealthInStatus = containers.some(c => healthRegex.test(c.Status || ''));
|
||||
if (!anyHasHealthInStatus) {
|
||||
// Single API call to find which containers have healthchecks configured
|
||||
try {
|
||||
const healthFiltered = await dockerJsonRequest<any[]>(
|
||||
'/containers/json?filters=' + encodeURIComponent(JSON.stringify({ health: ['healthy', 'unhealthy', 'starting'] })),
|
||||
{}, envId
|
||||
);
|
||||
const healthIds = new Set((healthFiltered || []).map((c: any) => c.Id));
|
||||
// Only inspect those specific containers (typically very few)
|
||||
if (healthIds.size > 0) {
|
||||
await Promise.all(
|
||||
[...healthIds].map(async (id) => {
|
||||
try {
|
||||
const inspect = await inspectContainer(id, envId);
|
||||
const h = inspect.State?.Health?.Status;
|
||||
if (h) healthStatuses.set(id, h);
|
||||
} catch {
|
||||
// Ignore errors
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
// Ignore - health filter may not be supported
|
||||
}
|
||||
}
|
||||
|
||||
return containers.map((container) => {
|
||||
// Extract network info with IP addresses
|
||||
const networks: { [networkName: string]: { ipAddress: string } } = {};
|
||||
@@ -1103,14 +1137,25 @@ export async function listContainers(all = true, envId?: number | null): Promise
|
||||
|
||||
// Extract health status from Status string
|
||||
// Docker formats: "(healthy)", "(unhealthy)", "(health: starting)"
|
||||
// Podman compat API omits health from Status string, so fall back to inspect data
|
||||
let health: string | undefined;
|
||||
const healthMatch = container.Status?.match(/\((healthy|unhealthy|health:\s*starting)\)/i);
|
||||
if (healthMatch) {
|
||||
const matched = healthMatch[1].toLowerCase();
|
||||
// Normalize "health: starting" to just "starting"
|
||||
health = matched.includes('starting') ? 'starting' : matched;
|
||||
} else {
|
||||
const inspectHealth = healthStatuses.get(container.Id);
|
||||
if (inspectHealth) {
|
||||
health = inspectHealth === 'health: starting' ? 'starting' : inspectHealth;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse exit code from Status string (e.g., "Exited (0) 5 minutes ago")
|
||||
const exitCode = container.State === 'exited'
|
||||
? parseInt(container.Status?.match(/\((\d+)\)/)?.[1] ?? '-1')
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
id: container.Id,
|
||||
name: container.Names[0]?.replace(/^\//, '') || 'unnamed',
|
||||
@@ -1122,6 +1167,7 @@ export async function listContainers(all = true, envId?: number | null): Promise
|
||||
networks,
|
||||
health,
|
||||
restartCount: restartCounts.get(container.Id) || 0,
|
||||
exitCode,
|
||||
mounts,
|
||||
labels: container.Labels || {},
|
||||
command: container.Command || '',
|
||||
|
||||
Reference in new issue
Block a user