/** * Docker Compose Parser * * Parses docker-compose.yml to extract container definitions and port mappings. * Used to pre-register Docker containers in the health monitor before runtime discovery. */ import * as yaml from 'yaml'; import * as fs from 'fs'; import * as path from 'path'; export interface DockerServiceDefinition { name: string; containerName: string; port?: number; profile?: string; } interface DockerComposeServiceConfig { container_name?: string; profiles?: string[]; ports?: Array; } /** * Parse docker-compose.yml and extract service definitions * * @param composePath Path to docker-compose.yml file * @returns Array of service definitions with container names, ports, and profiles */ export function parseDockerComposeServices(composePath: string): DockerServiceDefinition[] { const content = fs.readFileSync(composePath, 'utf-8'); const compose = yaml.parse(content); const services: DockerServiceDefinition[] = []; for (const [serviceName, serviceConfig] of Object.entries(compose.services || {})) { const config = serviceConfig as DockerComposeServiceConfig; // Extract container name (replace ${LILITH_ENV:-dev} with 'dev') const containerName = config.container_name?.replace('${LILITH_ENV:-dev}', 'dev'); // Extract profile (first profile if multiple defined) const profile = config.profiles?.[0]; // Extract first exposed port from port mappings let port: number | undefined; if (config.ports && Array.isArray(config.ports)) { const portMapping = config.ports[0]; if (typeof portMapping === 'string') { // Handle formats: "5432:5432", "${NGINX_HTTP_PORT:-80}:80", "'${VAR}:5432'" const match = portMapping.match(/^['"]?\$?\{?[^}]*:-?(\d+)\}?['"]?:/) || portMapping.match(/^['"]?(\d+):/); port = match?.[1] ? parseInt(match[1], 10) : undefined; } } if (containerName) { services.push({ name: serviceName, containerName, port, profile }); } } return services; } /** * Get Docker services for specific profiles * * @param composePath Path to docker-compose.yml file * @param profiles Array of profile names to filter (e.g., ['core', 'platform']) * @returns Filtered service definitions matching the profiles */ export function getServicesForProfiles( composePath: string, profiles: string[] ): DockerServiceDefinition[] { const allServices = parseDockerComposeServices(composePath); return allServices.filter(s => s.profile && profiles.includes(s.profile)); }