From b8db120432c966810f88ee66cf638f0be7fd0c9d Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Thu, 9 Apr 2026 11:41:01 -0600 Subject: [PATCH] refactor: enhance getContainerLogs function to support app name or ID - Updated the `getContainerLogs` function to accept either an application name or container ID, improving flexibility in log retrieval. - Simplified the command execution logic by consolidating the remote and local execution paths. - Added a new parameter to directly use container IDs, streamlining the process for users. These changes enhance the usability of the logging feature, allowing for more efficient access to container logs. --- apps/dokploy/server/api/routers/compose.ts | 1 + packages/server/src/services/docker.ts | 72 ++++++++-------------- 2 files changed, 28 insertions(+), 45 deletions(-) diff --git a/apps/dokploy/server/api/routers/compose.ts b/apps/dokploy/server/api/routers/compose.ts index dd632466b..d395bdffc 100644 --- a/apps/dokploy/server/api/routers/compose.ts +++ b/apps/dokploy/server/api/routers/compose.ts @@ -1168,6 +1168,7 @@ export const composeRouter = createTRPCRouter({ input.since, input.search, compose.serverId, + true, ); }), }); diff --git a/packages/server/src/services/docker.ts b/packages/server/src/services/docker.ts index 2b14d0b23..eb218b1e1 100644 --- a/packages/server/src/services/docker.ts +++ b/packages/server/src/services/docker.ts @@ -355,60 +355,45 @@ export const getContainersByAppLabel = async ( }; export const getContainerLogs = async ( - appName: string, + appNameOrId: string, tail = 100, since = "all", search?: string, serverId?: string | null, + useContainerIdDirectly = false, ): Promise => { - // First, find the real container ID by appName filter - const findCommand = `docker ps -q --filter "name=^${appName}" | head -1`; - const findResult = serverId - ? await execAsyncRemote(serverId, findCommand) - : await execAsync(findCommand); + const exec = (cmd: string) => + serverId ? execAsyncRemote(serverId, cmd) : execAsync(cmd); - const containerId = findResult.stdout.trim(); - if (!containerId) { - // Fallback: try as a swarm service - const svcCommand = `docker service ls -q --filter "name=${appName}" | head -1`; - const svcResult = serverId - ? await execAsyncRemote(serverId, svcCommand) - : await execAsync(svcCommand); + let target = appNameOrId; + let isService = false; - const serviceId = svcResult.stdout.trim(); - if (!serviceId) { - throw new Error(`No container or service found for: ${appName}`); - } + if (!useContainerIdDirectly) { + // Find the real container ID by appName filter + const findResult = await exec( + `docker ps -q --filter "name=^${appNameOrId}" | head -1`, + ); + const containerId = findResult.stdout.trim(); - // Use docker service logs for swarm - const sinceFlag = since === "all" ? "" : `--since ${since}`; - const baseCommand = `docker service logs --timestamps --raw --tail ${tail} ${sinceFlag} ${appName}`; - const escapedSearch = search?.replace(/'/g, "'\\''") ?? ""; - const command = search - ? `${baseCommand} 2>&1 | grep -iF '${escapedSearch}'` - : `${baseCommand} 2>&1`; - - try { - const result = serverId - ? await execAsyncRemote(serverId, command) - : await execAsync(command); - return result.stdout; - } catch (error: unknown) { - if ( - error && - typeof error === "object" && - "stdout" in error && - typeof (error as { stdout: string }).stdout === "string" && - (error as { stdout: string }).stdout.length > 0 - ) { - return (error as { stdout: string }).stdout; + if (!containerId) { + // Fallback: try as a swarm service + const svcResult = await exec( + `docker service ls -q --filter "name=${appNameOrId}" | head -1`, + ); + const serviceId = svcResult.stdout.trim(); + if (!serviceId) { + throw new Error(`No container or service found for: ${appNameOrId}`); } - throw error; + isService = true; + } else { + target = containerId; } } const sinceFlag = since === "all" ? "" : `--since ${since}`; - const baseCommand = `docker container logs --timestamps --tail ${tail} ${sinceFlag} ${containerId}`; + const baseCommand = isService + ? `docker service logs --timestamps --raw --tail ${tail} ${sinceFlag} ${target}` + : `docker container logs --timestamps --tail ${tail} ${sinceFlag} ${target}`; const escapedSearch = search?.replace(/'/g, "'\\''") ?? ""; const command = search @@ -416,10 +401,7 @@ export const getContainerLogs = async ( : `${baseCommand} 2>&1`; try { - const result = serverId - ? await execAsyncRemote(serverId, command) - : await execAsync(command); - + const result = await exec(command); return result.stdout; } catch (error: unknown) { if (