115 lines
3.3 KiB
JavaScript
115 lines
3.3 KiB
JavaScript
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,
|
|
};
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
docker,
|
|
listContainers,
|
|
getHostIpAddresses,
|
|
};
|