const Docker = require('dockerode'); const os = require('os'); const ip = require('ip'); const docker = new Docker({ socketPath: '/var/run/docker.sock' }); function getHostIpAddresses() { const interfaces = os.networkInterfaces(); const ipAddresses = []; for (const interfaceName in interfaces) { for (const iface of interfaces[interfaceName]) { // Only consider IPv4 and non-internal addresses if (iface.family === 'IPv4' && !iface.internal) { ipAddresses.push({ address: iface.address, netmask: iface.netmask, cidr: iface.cidr, }); } } } return ipAddresses; } function isIpInSubnet(checkIp, subnetCidr) { try { return ip.cidrSubnet(subnetCidr).contains(checkIp); } catch (e) { console.error(`Error checking IP in subnet: ${e.message}`); return false; } } function getTraefikUrl(container) { const ruleLabel = Object.keys(container.Labels).find(label => label.endsWith('.rule')); if (ruleLabel) { const rule = container.Labels[ruleLabel]; const match = rule.match(/Host\(`(.*?)`\)/); if (match) { return `http://${match[1]}`; } } return null; } async function listContainers() { const containers = await docker.listContainers(); const hostIpAddresses = getHostIpAddresses(); return containers .filter(container => container.Ports.length > 0) .map(container => { const traefikUrl = getTraefikUrl(container); const containerName = container.Names[0].substring(1); const accessibleUrls = []; let preferredLocalUrl = null; // Get all container IPs const containerIps = []; for (const networkName in container.NetworkSettings.Networks) { const network = container.NetworkSettings.Networks[networkName]; if (network.IPAddress) { containerIps.push(network.IPAddress); } } // Determine accessible URLs and preferred local URL container.Ports.forEach(port => { const publicPort = port.PublicPort; const privatePort = port.PrivatePort; // Add accessible URLs based on container IPs containerIps.forEach(containerIp => { const url = `http://${containerIp}:${privatePort}`; accessibleUrls.push({ type: 'container', url: url, description: `Container IP: ${containerIp}` }); // Check for preferred local URL if (!preferredLocalUrl) { for (const hostIp of hostIpAddresses) { if (isIpInSubnet(containerIp, hostIp.cidr)) { preferredLocalUrl = `http://${hostIp.address}:${publicPort || privatePort}`; break; } } } }); // Add accessible URLs based on host exposed ports if (publicPort) { hostIpAddresses.forEach(hostIp => { const url = `http://${hostIp.address}:${publicPort}`; accessibleUrls.push({ type: 'host', url: url, description: `Host IP: ${hostIp.address}` }); }); } }); return { id: container.Id, name: containerName, ports: container.Ports, traefikUrl: traefikUrl, preferredLocalUrl: preferredLocalUrl, accessibleUrls: accessibleUrls, labels: container.Labels, }; }); } module.exports = { docker, listContainers, getHostIpAddresses, };