useDocker.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. const App = require('../../../models/App');
  2. const axios = require('axios');
  3. const Logger = require('../../../utils/Logger');
  4. const logger = new Logger();
  5. const loadConfig = require('../../../utils/loadConfig');
  6. const useDocker = async (apps) => {
  7. const {
  8. useOrdering: orderType,
  9. unpinStoppedApps,
  10. dockerHost: host,
  11. } = await loadConfig();
  12. const dockerApps = [];
  13. let containers = null;
  14. let containers_swarm = null;
  15. function addApp(dockerApps, labels){
  16. // add each container as flame formatted app
  17. if (
  18. 'flame.name' in labels &&
  19. 'flame.url' in labels &&
  20. /^app/.test(labels['flame.type'])
  21. ) {
  22. for (let i = 0; i < labels['flame.name'].split(';').length; i++) {
  23. const names = labels['flame.name'].split(';');
  24. const urls = labels['flame.url'].split(';');
  25. let icons = '';
  26. if ('flame.icon' in labels) {
  27. icons = labels['flame.icon'].split(';');
  28. }
  29. dockerApps.push({
  30. name: names[i] || names[0],
  31. url: urls[i] || urls[0],
  32. icon: icons[i] || 'docker',
  33. });
  34. }
  35. }
  36. }
  37. // Get list of containers
  38. try {
  39. if (host.includes('localhost')) {
  40. // Use default host
  41. function getDocker(){
  42. return axios.get(
  43. `http://${host}/containers/json?{"status":["running"]}`,
  44. {
  45. socketPath: '/var/run/docker.sock',
  46. }
  47. );
  48. }
  49. function getSwarm(){
  50. return axios.get(
  51. `http://${host}/services`,
  52. {
  53. socketPath: '/var/run/docker.sock',
  54. }
  55. );
  56. }
  57. [ containers, containers_swarm ] = await Promise.all(
  58. [getDocker(),
  59. getSwarm()
  60. ]);
  61. } else {
  62. // Use custom host
  63. let { data } = await axios.get(
  64. `http://${host}/containers/json?{"status":["running"]}`
  65. );
  66. containers = data;
  67. }
  68. } catch {
  69. logger.log(`Can't connect to the Docker API on ${host}`, 'ERROR');
  70. }
  71. if (containers_swarm) {
  72. apps = await App.findAll({
  73. order: [[orderType, 'ASC']],
  74. });
  75. services = containers_swarm.data;
  76. for (const service of services) {
  77. let labels = service.Spec.Labels;
  78. labels['flame.name'] = service.Spec.Name;
  79. labels['flame.type'] = 'application';
  80. if (!('flame.url' in labels)) {
  81. for (const label of Object.keys(labels)) {
  82. if (/^traefik.*.frontend.rule/.test(label)) {
  83. // Traefik 1.x
  84. let value = labels[label];
  85. if (value.indexOf('Host') !== -1) {
  86. value = value.split('Host:')[1];
  87. labels['flame.url'] =
  88. 'https://' + value.split(',').join(';https://');
  89. }
  90. } else if (/^traefik.*?\.rule/.test(label)) {
  91. // Traefik 2.x
  92. const value = labels[label];
  93. if (value.indexOf('Host') !== -1) {
  94. const regex = /\`([a-zA-Z0-9\.\-]+)\`/g;
  95. const domains = [];
  96. while ((match = regex.exec(value)) != null) {
  97. domains.push('http://' + match[1]);
  98. }
  99. if (domains.length > 0) {
  100. labels['flame.url'] = domains.join(';');
  101. }
  102. }
  103. }
  104. }
  105. }
  106. addApp(dockerApps, labels);
  107. }
  108. }
  109. if (containers) {
  110. apps = await App.findAll({
  111. order: [[orderType, 'ASC']],
  112. });
  113. // Filter out containers without any annotations
  114. containers = containers.data.filter((e) => Object.keys(e.Labels).length !== 0);
  115. for (const container of containers) {
  116. let labels = container.Labels;
  117. if(!('com.docker.stack.namespace' in labels)){
  118. console.log(container)
  119. labels['flame.name'] = container.Names[0];
  120. labels['flame.type'] = 'application';
  121. // Traefik labels for URL configuration
  122. if (!('flame.url' in labels)) {
  123. for (const label of Object.keys(labels)) {
  124. if (/^traefik.*.frontend.rule/.test(label)) {
  125. // Traefik 1.x
  126. let value = labels[label];
  127. if (value.indexOf('Host') !== -1) {
  128. value = value.split('Host:')[1];
  129. labels['flame.url'] =
  130. 'https://' + value.split(',').join(';https://');
  131. }
  132. } else if (/^traefik.*?\.rule/.test(label)) {
  133. // Traefik 2.x
  134. const value = labels[label];
  135. if (value.indexOf('Host') !== -1) {
  136. const regex = /\`([a-zA-Z0-9\.\-]+)\`/g;
  137. const domains = [];
  138. while ((match = regex.exec(value)) != null) {
  139. domains.push('http://' + match[1]);
  140. }
  141. if (domains.length > 0) {
  142. labels['flame.url'] = domains.join(';');
  143. }
  144. }
  145. }
  146. }
  147. }
  148. }
  149. addApp(dockerApps, labels);
  150. }
  151. }
  152. if (unpinStoppedApps) {
  153. for (const app of apps) {
  154. await app.update({ isPinned: false });
  155. }
  156. }
  157. for (const item of dockerApps) {
  158. // If app already exists, update it
  159. if (apps.some((app) => app.name === item.name)) {
  160. const app = apps.find((a) => a.name === item.name);
  161. if (
  162. item.icon === 'custom' ||
  163. (item.icon === 'docker' && app.icon != 'docker')
  164. ) {
  165. // update without overriding icon
  166. await app.update({
  167. name: item.name,
  168. url: item.url,
  169. isPinned: true,
  170. });
  171. } else {
  172. await app.update({
  173. ...item,
  174. isPinned: true,
  175. });
  176. }
  177. } else {
  178. // else create new app
  179. await App.create({
  180. ...item,
  181. icon: item.icon === 'custom' ? 'docker' : item.icon,
  182. isPinned: true,
  183. });
  184. }
  185. }
  186. };
  187. module.exports = useDocker;