mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-03 06:07:20 +02:00
Merge pull request #391 from eyerrock/list-containers-with-unexposed-ports
list containers with unexposed ports
This commit is contained in:
commit
df88084375
@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- Notes: This should be open in its original path-->
|
<!-- Notes: This should be open in its original path-->
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<link rel="stylesheet" href="../script/semantic/semantic.min.css" />
|
<link rel="stylesheet" href="../script/semantic/semantic.min.css" />
|
||||||
<script src="../script/jquery-3.6.0.min.js"></script>
|
<script src="../script/jquery-3.6.0.min.js"></script>
|
||||||
<script src="../script/semantic/semantic.min.js"></script>
|
<script src="../script/semantic/semantic.min.js"></script>
|
||||||
@ -10,6 +10,19 @@
|
|||||||
<body>
|
<body>
|
||||||
<br />
|
<br />
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" id="showUnexposed" class="hidden" />
|
||||||
|
<label for="showUnexposed"
|
||||||
|
>Show Containers with Unexposed Ports
|
||||||
|
<br />
|
||||||
|
<small
|
||||||
|
>Please make sure Zoraxy and the target container share a
|
||||||
|
network</small
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="ui header">
|
<div class="ui header">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
List of Docker Containers
|
List of Docker Containers
|
||||||
@ -33,56 +46,70 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const lines = {};
|
let lines = {};
|
||||||
const linesAded = {};
|
let linesAdded = {};
|
||||||
|
|
||||||
|
document
|
||||||
|
.getElementById("showUnexposed")
|
||||||
|
.addEventListener("change", () => {
|
||||||
|
console.log("showUnexposed", $("#showUnexposed").is(":checked"));
|
||||||
|
$("#containersList").html('<div class="ui loader active"></div>');
|
||||||
|
|
||||||
|
$("#containersAddedList").empty();
|
||||||
|
$("#containersAddedListHeader").attr("hidden", true);
|
||||||
|
|
||||||
|
lines = {};
|
||||||
|
linesAdded = {};
|
||||||
|
|
||||||
|
getDockerContainers();
|
||||||
|
});
|
||||||
|
|
||||||
function getDockerContainers() {
|
function getDockerContainers() {
|
||||||
const hostRequest = $.get("/api/proxy/list?type=host");
|
const hostRequest = $.get("/api/proxy/list?type=host");
|
||||||
const dockerRequest = $.get("/api/docker/containers");
|
const dockerRequest = $.get("/api/docker/containers");
|
||||||
|
|
||||||
// Wait for both requests to complete
|
|
||||||
Promise.all([hostRequest, dockerRequest])
|
Promise.all([hostRequest, dockerRequest])
|
||||||
.then(([hostData, dockerData]) => {
|
.then(([hostData, dockerData]) => {
|
||||||
if (
|
if (!dockerData.error && !hostData.error) {
|
||||||
dockerData.error === undefined &&
|
|
||||||
hostData.error === undefined
|
|
||||||
) {
|
|
||||||
const { containers, network } = dockerData;
|
const { containers, network } = dockerData;
|
||||||
const bridge = network.find(({ Name }) => Name === "bridge");
|
|
||||||
const {
|
const existingTargets = new Set(
|
||||||
IPAM: {
|
hostData.flatMap(({ ActiveOrigins }) =>
|
||||||
Config: [{ Gateway: gateway }],
|
ActiveOrigins.map(({ OriginIpOrDomain }) => OriginIpOrDomain)
|
||||||
},
|
)
|
||||||
} = bridge;
|
);
|
||||||
const existedDomains = hostData.reduce((acc, { ActiveOrigins }) => {
|
|
||||||
return acc.concat(ActiveOrigins.map(({ OriginIpOrDomain }) => OriginIpOrDomain));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
for (const container of containers) {
|
for (const container of containers) {
|
||||||
const {
|
const Ports = container.Ports;
|
||||||
Ports,
|
const name = container.Names[0].replace(/^\//, "");
|
||||||
Names: [name],
|
|
||||||
} = container;
|
|
||||||
|
|
||||||
for (const portObject of Ports.filter(
|
for (const portObject of Ports) {
|
||||||
({ IP: ip }) => ip === "::" || ip === '0.0.0.0'
|
let port = portObject.PublicPort;
|
||||||
)) {
|
if (!port) {
|
||||||
const { IP: ip, PublicPort: port } = portObject;
|
if (!$("#showUnexposed").is(":checked")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
port = portObject.PrivatePort;
|
||||||
|
}
|
||||||
const key = `${name}-${port}`;
|
const key = `${name}-${port}`;
|
||||||
|
|
||||||
|
// if port is not exposed, use container's name and let docker handle the routing
|
||||||
|
// BUT this will only work if the container is on the same network as Zoraxy
|
||||||
|
const targetAddress = portObject.IP || name;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
existedDomains.some((item) => item === `${gateway}:${port}`) &&
|
existingTargets.has(`${targetAddress}:${port}`) &&
|
||||||
!linesAded[key]
|
!linesAdded[key]
|
||||||
) {
|
) {
|
||||||
linesAded[key] = {
|
linesAdded[key] = {
|
||||||
name: name.replace(/^\//, ""),
|
name,
|
||||||
ip: gateway,
|
ip: targetAddress,
|
||||||
port,
|
port,
|
||||||
};
|
};
|
||||||
} else if (!lines[key]) {
|
} else if (!lines[key]) {
|
||||||
lines[key] = {
|
lines[key] = {
|
||||||
name: name.replace(/^\//, ""),
|
name,
|
||||||
ip: gateway,
|
ip: targetAddress,
|
||||||
port,
|
port,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -92,29 +119,31 @@
|
|||||||
for (const [key, line] of Object.entries(lines)) {
|
for (const [key, line] of Object.entries(lines)) {
|
||||||
$("#containersList").append(
|
$("#containersList").append(
|
||||||
`<div class="item">
|
`<div class="item">
|
||||||
<div class="right floated content">
|
<div class="right floated content">
|
||||||
<div class="ui button" onclick="addContainerItem('${key}');">Add</div>
|
<div class="ui button" onclick="addContainerItem('${key}');">Add</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="header">${line.name}</div>
|
<div class="header">${line.name}</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
${line.ip}:${line.port}
|
${line.ip}:${line.port}
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (const [key, line] of Object.entries(linesAded)) {
|
|
||||||
|
for (const [key, line] of Object.entries(linesAdded)) {
|
||||||
$("#containersAddedList").append(
|
$("#containersAddedList").append(
|
||||||
`<div class="item">
|
`<div class="item">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="header">${line.name}</div>
|
<div class="header">${line.name}</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
${line.ip}:${line.port}
|
${line.ip}:${line.port}
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Object.entries(linesAded).length &&
|
|
||||||
|
Object.entries(linesAdded).length &&
|
||||||
$("#containersAddedListHeader").removeAttr("hidden");
|
$("#containersAddedListHeader").removeAttr("hidden");
|
||||||
$("#containersList .loader").removeClass("active");
|
$("#containersList .loader").removeClass("active");
|
||||||
} else {
|
} else {
|
||||||
@ -122,7 +151,11 @@
|
|||||||
`Error loading data: ${dockerData.error || hostData.error}`,
|
`Error loading data: ${dockerData.error || hostData.error}`,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
$("#containersList").html(`<div class="ui basic segment"><i class="ui red times icon"></i> ${dockerData.error || hostData.error}</div>`);
|
$("#containersList").html(
|
||||||
|
`<div class="ui basic segment"><i class="ui red times icon"></i> ${
|
||||||
|
dockerData.error || hostData.error
|
||||||
|
}</div>`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user