server.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import express from 'express';
  2. import session from 'express-session';
  3. import memorystore from 'memorystore';
  4. import ejs from 'ejs';
  5. import Docker from 'dockerode';
  6. import { router } from './router/index.js';
  7. import { sequelize, Container } from './database/models.js';
  8. import { currentLoad, mem, networkStats, fsSize } from 'systeminformation';
  9. import { containerCard } from './components/containerCard.js';
  10. export var docker = new Docker();
  11. export { setEvent, sse, cpu, ram, tx, rx, disk }
  12. const app = express();
  13. const MemoryStore = memorystore(session);
  14. const port = process.env.PORT || 8000;
  15. // Session middleware
  16. const sessionMiddleware = session({
  17. store: new MemoryStore({ checkPeriod: 86400000 }), // Prune expired entries every 24h
  18. secret: "keyboard cat",
  19. resave: false,
  20. saveUninitialized: false,
  21. cookie:{
  22. secure:false, // Only set to true if you are using HTTPS.
  23. httpOnly:false, // Only set to true if you are using HTTPS.
  24. maxAge:3600000 * 8 // Session max age in milliseconds. 3600000 = 1 hour.
  25. }
  26. });
  27. // Express middleware
  28. app.set('view engine', 'html');
  29. app.engine('html', ejs.renderFile);
  30. app.use([
  31. express.static('public'),
  32. express.json(),
  33. express.urlencoded({ extended: true }),
  34. sessionMiddleware,
  35. router
  36. ]);
  37. // Initialize server
  38. app.listen(port, async () => {
  39. async function init() {
  40. try { await sequelize.authenticate().then(
  41. () => { console.log('DB Connection: ✔️') }); }
  42. catch { console.log('DB Connection: ❌'); }
  43. try { await sequelize.sync().then( // check out that formatting
  44. () => { console.log('Synced Models: ✔️') }); }
  45. catch { console.log('Synced Models: ❌'); } }
  46. await init().then(() => {
  47. console.log(`Listening on http://localhost:${port}`);
  48. });
  49. });
  50. let [ cpu, ram, tx, rx, disk ] = [0, 0, 0, 0, 0];
  51. let [ hidden, cardList, sentList ] = ['', '', ''];
  52. let event = false;
  53. let sse = false;
  54. let eventInfo = '';
  55. function setEvent(value, type) {
  56. event = value;
  57. eventInfo = type;
  58. }
  59. // Server metrics
  60. let serverMetrics = async () => {
  61. currentLoad().then(data => {
  62. cpu = Math.round(data.currentLoad);
  63. });
  64. mem().then(data => {
  65. ram = Math.round((data.active / data.total) * 100);
  66. });
  67. networkStats().then(data => {
  68. tx = data[0].tx_bytes / (1024 * 1024);
  69. rx = data[0].rx_bytes / (1024 * 1024);
  70. });
  71. fsSize().then(data => {
  72. disk = data[0].use;
  73. });
  74. }
  75. setInterval(serverMetrics, 1000);
  76. // Get hidden containers
  77. async function getHidden() {
  78. hidden = await Container.findAll({ where: {visibility:false}});
  79. hidden = hidden.map((container) => container.name);
  80. }
  81. // Create list of docker containers cards
  82. let containerCards = async () => {
  83. let list = '';
  84. const allContainers = await docker.listContainers({ all: true });
  85. for (const container of allContainers) {
  86. if (!hidden.includes(container.Names[0].slice(1))) {
  87. let imageVersion = container.Image.split('/');
  88. let service = imageVersion[imageVersion.length - 1].split(':')[0];
  89. let containerId = docker.getContainer(container.Id);
  90. let containerInfo = await containerId.inspect();
  91. let ports_list = [];
  92. try {
  93. for (const [key, value] of Object.entries(containerInfo.HostConfig.PortBindings)) {
  94. let ports = {
  95. check: 'checked',
  96. external: value[0].HostPort,
  97. internal: key.split('/')[0],
  98. protocol: key.split('/')[1]
  99. }
  100. ports_list.push(ports);
  101. }
  102. } catch {}
  103. let external_port = ports_list[0]?.external || 0;
  104. let internal_port = ports_list[0]?.internal || 0;
  105. let container_info = {
  106. name: container.Names[0].slice(1),
  107. service: service,
  108. id: container.Id,
  109. state: container.State,
  110. image: container.Image,
  111. external_port: external_port,
  112. internal_port: internal_port,
  113. ports: ports_list,
  114. link: 'localhost',
  115. }
  116. let card = containerCard(container_info);
  117. list += card;
  118. }
  119. }
  120. cardList = list;
  121. }
  122. // Docker events
  123. docker.getEvents((err, stream) => {
  124. if (err) throw err;
  125. stream.on('data', (chunk) => {
  126. event = true;
  127. eventInfo = 'docker';
  128. });
  129. });
  130. // Check if the container cards need to be updated
  131. setInterval(async () => {
  132. if (event == false) { return; }
  133. await getHidden();
  134. await containerCards();
  135. if (cardList != sentList) {
  136. cardList = sentList;
  137. sse = true;
  138. }
  139. event = false;
  140. }, 1000);
  141. // Gets called at load and after server-side events
  142. router.get('/containers', async (req, res) => {
  143. await getHidden();
  144. await containerCards();
  145. sentList = cardList;
  146. res.send(cardList);
  147. });
  148. router.get('/sse_event', (req, res) => {
  149. res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', });
  150. let eventCheck = setInterval(async () => {
  151. if (sse == true) {
  152. sse = false;
  153. console.log(`event: ${eventInfo}`);
  154. res.write(`event: ${eventInfo}\n`);
  155. res.write(`data: there was an event!\n\n`);
  156. }
  157. }, 1000);
  158. req.on('close', () => {
  159. clearInterval(eventCheck);
  160. });
  161. });