dockerContainersList.html 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- Notes: This should be open in its original path-->
  5. <meta charset="utf-8" />
  6. <link rel="stylesheet" href="../script/semantic/semantic.min.css" />
  7. <script src="../script/jquery-3.6.0.min.js"></script>
  8. <script src="../script/semantic/semantic.min.js"></script>
  9. </head>
  10. <body>
  11. <link rel="stylesheet" href="../darktheme.css">
  12. <script src="../script/darktheme.js"></script>
  13. <br />
  14. <div class="ui container">
  15. <div class="field">
  16. <div class="ui checkbox">
  17. <input type="checkbox" id="showUnexposed" class="hidden" />
  18. <label for="showUnexposed"
  19. >Show Containers with Unexposed Ports
  20. <br />
  21. <small
  22. >Please make sure Zoraxy and the target container share a
  23. network</small
  24. >
  25. </label>
  26. </div>
  27. </div>
  28. <div class="ui header">
  29. <div class="content">
  30. List of Docker Containers
  31. <div class="sub header">
  32. Below is a list of all detected Docker containers currently running
  33. on the system.
  34. </div>
  35. </div>
  36. </div>
  37. <div id="containersList" class="ui middle aligned divided list active">
  38. <div class="ui loader active"></div>
  39. </div>
  40. <div class="ui horizontal divider"></div>
  41. <div id="containersAddedListHeader" class="ui header" hidden>
  42. Already added containers:
  43. </div>
  44. <div
  45. id="containersAddedList"
  46. class="ui middle aligned divided list"
  47. ></div>
  48. </div>
  49. <script>
  50. let lines = {};
  51. let linesAdded = {};
  52. document
  53. .getElementById("showUnexposed")
  54. .addEventListener("change", () => {
  55. console.log("showUnexposed", $("#showUnexposed").is(":checked"));
  56. $("#containersList").html('<div class="ui loader active"></div>');
  57. $("#containersAddedList").empty();
  58. $("#containersAddedListHeader").attr("hidden", true);
  59. lines = {};
  60. linesAdded = {};
  61. getDockerContainers();
  62. });
  63. function getDockerContainers() {
  64. const hostRequest = $.get("/api/proxy/list?type=host");
  65. const dockerRequest = $.get("/api/docker/containers");
  66. Promise.all([hostRequest, dockerRequest])
  67. .then(([hostData, dockerData]) => {
  68. if (!dockerData.error && !hostData.error) {
  69. const { containers, network } = dockerData;
  70. const existingTargets = new Set(
  71. hostData.flatMap(({ ActiveOrigins }) =>
  72. ActiveOrigins.map(({ OriginIpOrDomain }) => OriginIpOrDomain)
  73. )
  74. );
  75. for (const container of containers) {
  76. const Ports = container.Ports;
  77. const name = container.Names[0].replace(/^\//, "");
  78. for (const portObject of Ports) {
  79. let port = portObject.PublicPort;
  80. if (!port) {
  81. if (!$("#showUnexposed").is(":checked")) {
  82. continue;
  83. }
  84. port = portObject.PrivatePort;
  85. }
  86. const key = `${name}-${port}`;
  87. // if port is not exposed, use container's name and let docker handle the routing
  88. // BUT this will only work if the container is on the same network as Zoraxy
  89. const targetAddress = portObject.IP || name;
  90. if (
  91. existingTargets.has(`${targetAddress}:${port}`) &&
  92. !linesAdded[key]
  93. ) {
  94. linesAdded[key] = {
  95. name,
  96. ip: targetAddress,
  97. port,
  98. };
  99. } else if (!lines[key]) {
  100. lines[key] = {
  101. name,
  102. ip: targetAddress,
  103. port,
  104. };
  105. }
  106. }
  107. }
  108. for (const [key, line] of Object.entries(lines)) {
  109. $("#containersList").append(
  110. `<div class="item">
  111. <div class="right floated content">
  112. <div class="ui button" onclick="addContainerItem('${key}');">Add</div>
  113. </div>
  114. <div class="content">
  115. <div class="header">${line.name}</div>
  116. <div class="description">
  117. ${line.ip}:${line.port}
  118. </div>
  119. </div>`
  120. );
  121. }
  122. for (const [key, line] of Object.entries(linesAdded)) {
  123. $("#containersAddedList").append(
  124. `<div class="item">
  125. <div class="content">
  126. <div class="header">${line.name}</div>
  127. <div class="description">
  128. ${line.ip}:${line.port}
  129. </div>
  130. </div>`
  131. );
  132. }
  133. Object.entries(linesAdded).length &&
  134. $("#containersAddedListHeader").removeAttr("hidden");
  135. $("#containersList .loader").removeClass("active");
  136. } else {
  137. parent.msgbox(
  138. `Error loading data: ${dockerData.error || hostData.error}`,
  139. false
  140. );
  141. $("#containersList").html(
  142. `<div class="ui basic segment"><i class="ui red times icon"></i> ${
  143. dockerData.error || hostData.error
  144. }</div>`
  145. );
  146. }
  147. })
  148. .catch((error) => {
  149. console.log(error.responseText);
  150. parent.msgbox("Error loading data: " + error.message, false);
  151. });
  152. }
  153. getDockerContainers();
  154. function addContainerItem(item) {
  155. if (lines[item]) {
  156. parent.addContainerItem(lines[item]);
  157. }
  158. }
  159. </script>
  160. </body>
  161. </html>