mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-06-15 20:25:23 +02:00
feat: add readLogs procedure to multiple routers for container log retrieval
- Implemented a new `readLogs` procedure across various routers (application, compose, libsql, mariadb, mongo, mysql, postgres, redis) to enable users to retrieve logs from containers. - Each procedure includes input validation for parameters such as `tail`, `since`, and `search`, ensuring robust access control and authorization checks. - Enhanced the `getContainerLogs` service to support fetching logs from both Docker containers and services, improving the logging capabilities of the application. This feature enhances observability and troubleshooting for users by providing direct access to container logs.
This commit is contained in:
@@ -354,6 +354,87 @@ export const getContainersByAppLabel = async (
|
||||
return [];
|
||||
};
|
||||
|
||||
export const getContainerLogs = async (
|
||||
appName: string,
|
||||
tail = 100,
|
||||
since = "all",
|
||||
search?: string,
|
||||
serverId?: string | null,
|
||||
): Promise<string> => {
|
||||
// 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 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);
|
||||
|
||||
const serviceId = svcResult.stdout.trim();
|
||||
if (!serviceId) {
|
||||
throw new Error(`No container or service found for: ${appName}`);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const sinceFlag = since === "all" ? "" : `--since ${since}`;
|
||||
const baseCommand = `docker container logs --timestamps --tail ${tail} ${sinceFlag} ${containerId}`;
|
||||
|
||||
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;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const containerRestart = async (containerId: string) => {
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(
|
||||
|
||||
Reference in New Issue
Block a user