From e4e5cc97d3c07d7ab33eb11bc3402f71034e1343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Wed, 4 Feb 2026 01:17:46 +0100 Subject: [PATCH] Deep-link Dozzle logs button to specific container The discover API now fetches container names from Docker via the Python API on port 9876 and matches them to services by UUID. The Dozzle logs button builds a proper deep link using the Dozzle host ID and container name, opening directly to that container's log stream. Co-Authored-By: Claude Opus 4.5 --- src/app/api/discover/route.ts | 24 +++++++++++++++++++++++- src/components/ServiceCard.tsx | 4 +--- src/lib/config.ts | 1 + src/lib/services.ts | 9 +++++++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/app/api/discover/route.ts b/src/app/api/discover/route.ts index 01b91f8..85001eb 100644 --- a/src/app/api/discover/route.ts +++ b/src/app/api/discover/route.ts @@ -56,9 +56,28 @@ function buildUrl(fqdn: string | null, port: number): string { return `http://${nucHost}`; } +async function fetchContainerNames(): Promise { + try { + const res = await fetch(`http://${nucHost}:9876/containers`, { + signal: AbortSignal.timeout(5000), + }); + if (!res.ok) return []; + return await res.json() as string[]; + } catch { + return []; + } +} + +function findContainerName(uuid: string, containers: string[]): string | undefined { + return containers.find(c => c.includes(uuid)); +} + export async function GET() { try { - const resources = await fetchResources(); + const [resources, containerNames] = await Promise.all([ + fetchResources(), + fetchContainerNames(), + ]); if (!resources) { return NextResponse.json( @@ -88,6 +107,7 @@ export async function GET() { resourceType: 'application', uuid: resource.uuid, coolifyStatus: resource.status, + container: findContainerName(resource.uuid, containerNames), }; } @@ -121,6 +141,7 @@ export async function GET() { resourceType: 'service', uuid: resource.uuid, coolifyStatus: resource.status, + container: findContainerName(resource.uuid, containerNames), }; } @@ -137,6 +158,7 @@ export async function GET() { resourceType: 'database', uuid: resource.uuid, coolifyStatus: resource.status, + container: findContainerName(resource.uuid, containerNames), }; } diff --git a/src/components/ServiceCard.tsx b/src/components/ServiceCard.tsx index ab7fd6b..a505f28 100644 --- a/src/components/ServiceCard.tsx +++ b/src/components/ServiceCard.tsx @@ -2,8 +2,6 @@ import { useState, useCallback } from 'react'; import { Service, DiscoveredService, getCoolifyUrl, getDozzleUrl } from '@/lib/services'; - -const dozzleUrl = getDozzleUrl(); import { HealthStatus } from '@/lib/PortalContext'; import { Icon } from './Icons'; @@ -175,7 +173,7 @@ export function ServiceCard({ service, status }: ServiceCardProps) { {/* View logs in Dozzle */} {discovered && (