diff --git a/src/pages/api/docker/stats/[...service].js b/src/pages/api/docker/stats/[...service].js index d214ffb28..82604f8c7 100644 --- a/src/pages/api/docker/stats/[...service].js +++ b/src/pages/api/docker/stats/[...service].js @@ -14,7 +14,8 @@ export default async function handler(req, res) { } try { - const docker = new Docker(getDockerArguments(containerServer)); + const dockerArgs = getDockerArguments(containerServer); + const docker = new Docker(dockerArgs.conn); const containers = await docker.listContainers({ all: true, }); @@ -31,18 +32,44 @@ export default async function handler(req, res) { const containerNames = containers.map((container) => container.Names[0].replace(/^\//, "")); const containerExists = containerNames.includes(containerName); - if (!containerExists) { - res.status(200).send({ - error: "not found", + if (containerExists) { + const container = docker.getContainer(containerName); + const stats = await container.stats({ stream: false }); + + res.status(200).json({ + stats, }); return; } - const container = docker.getContainer(containerName); - const stats = await container.stats({ stream: false }); + // Try with a service deployed in Docker Swarm, if enabled + if (dockerArgs.swarm) { + const tasks = await docker.listTasks({ + filters: { + service: [containerName], + // A service can have several offline containers, so we only look for an active one. + "desired-state": ["running"], + }, + }) + .catch(() => []); + + // For now we are only interested in the first one (in case replicas > 1). + // TODO: Show the result for all replicas/containers? + const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID; + + if (taskContainerId) { + const container = docker.getContainer(taskContainerId); + const stats = await container.stats({ stream: false }); + + res.status(200).json({ + stats, + }); + return; + } + } - res.status(200).json({ - stats, + res.status(200).send({ + error: "not found", }); } catch { res.status(500).send({ diff --git a/src/pages/api/docker/status/[...service].js b/src/pages/api/docker/status/[...service].js index 2861a1e58..fa54e6f3b 100644 --- a/src/pages/api/docker/status/[...service].js +++ b/src/pages/api/docker/status/[...service].js @@ -13,7 +13,8 @@ export default async function handler(req, res) { } try { - const docker = new Docker(getDockerArguments(containerServer)); + const dockerArgs = getDockerArguments(containerServer); + const docker = new Docker(dockerArgs.conn); const containers = await docker.listContainers({ all: true, }); @@ -29,18 +30,43 @@ export default async function handler(req, res) { const containerNames = containers.map((container) => container.Names[0].replace(/^\//, "")); const containerExists = containerNames.includes(containerName); - if (!containerExists) { - return res.status(200).send({ - error: "not found", + if (containerExists) { + const container = docker.getContainer(containerName); + const info = await container.inspect(); + + return res.status(200).json({ + status: info.State.Status, + health: info.State.Health?.Status, }); } - const container = docker.getContainer(containerName); - const info = await container.inspect(); + if (dockerArgs.swarm) { + const tasks = await docker.listTasks({ + filters: { + service: [containerName], + // A service can have several offline containers, we only look for an active one. + "desired-state": ["running"], + }, + }) + .catch(() => []); + + // For now we are only interested in the first one (in case replicas > 1). + // TODO: Show the result for all replicas/containers? + const taskContainerId = tasks.at(0)?.Status?.ContainerStatus?.ContainerID; + + if (taskContainerId) { + const container = docker.getContainer(taskContainerId); + const info = await container.inspect(); + + return res.status(200).json({ + status: info.State.Status, + health: info.State.Health?.Status, + }); + } + } - return res.status(200).json({ - status: info.State.Status, - health: info.State.Health?.Status + return res.status(200).send({ + error: "not found", }); } catch { return res.status(500).send({ diff --git a/src/utils/config/docker.js b/src/utils/config/docker.js index 9aef74086..7e1422e0f 100644 --- a/src/utils/config/docker.js +++ b/src/utils/config/docker.js @@ -22,11 +22,14 @@ export default function getDockerArguments(server) { if (servers[server]) { if (servers[server].socket) { - return { socketPath: servers[server].socket }; + return { conn: { socketPath: servers[server].socket }, swarm: !!servers[server].swarm }; } if (servers[server].host) { - return { host: servers[server].host, port: servers[server].port || null }; + return { + conn: { host: servers[server].host, port: servers[server].port || null }, + swarm: !!servers[server].swarm, + }; } return servers[server]; diff --git a/src/utils/config/service-helpers.js b/src/utils/config/service-helpers.js index e0a9f23f1..623b7d6be 100644 --- a/src/utils/config/service-helpers.js +++ b/src/utils/config/service-helpers.js @@ -44,7 +44,7 @@ export async function servicesFromDocker() { const serviceServers = await Promise.all( Object.keys(servers).map(async (serverName) => { - const docker = new Docker(getDockerArguments(serverName)); + const docker = new Docker(getDockerArguments(serverName).conn); const containers = await docker.listContainers({ all: true, });