@whyour/qinglong 2.20.2-2 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/.env.example +5 -0
  2. package/AGENTS.md +43 -0
  3. package/CLAUDE.md +43 -0
  4. package/README-en.md +11 -0
  5. package/README.md +11 -0
  6. package/docker/Dockerfile +51 -69
  7. package/docker/Dockerfile.310 +94 -0
  8. package/docker/Dockerfile.debian +120 -0
  9. package/docker/{310.Dockerfile → Dockerfile.debian310} +13 -5
  10. package/docker/docker-entrypoint.sh +95 -3
  11. package/docs/PROJECT_ARCHITECTURE.md +550 -0
  12. package/package.json +28 -25
  13. package/sample/config.sample.sh +12 -1
  14. package/sample/notify.js +81 -9
  15. package/sample/notify.py +54 -11
  16. package/shell/api.sh +44 -20
  17. package/shell/bot.sh +30 -16
  18. package/shell/check.sh +21 -19
  19. package/shell/lang/en.sh +105 -0
  20. package/shell/lang/zh.sh +105 -0
  21. package/shell/otask.sh +114 -28
  22. package/shell/preload/client.js +20 -2
  23. package/shell/preload/esm-loader.mjs +41 -0
  24. package/shell/preload/sitecustomize.js +36 -0
  25. package/shell/pub.sh +8 -8
  26. package/shell/rmlog.sh +5 -5
  27. package/shell/share.sh +49 -30
  28. package/shell/start.sh +40 -27
  29. package/shell/task.sh +10 -2
  30. package/shell/update.sh +22 -22
  31. package/static/build/api/config.js +17 -7
  32. package/static/build/api/cron.js +38 -1
  33. package/static/build/api/dashboard.js +337 -0
  34. package/static/build/api/env.js +40 -2
  35. package/static/build/api/index.js +2 -0
  36. package/static/build/api/log.js +5 -4
  37. package/static/build/api/script.js +34 -9
  38. package/static/build/api/system.js +16 -1
  39. package/static/build/api/user.js +6 -5
  40. package/static/build/app.js +3 -0
  41. package/static/build/config/const.js +7 -6
  42. package/static/build/config/container.js +12 -0
  43. package/static/build/config/grpcCerts.js +150 -0
  44. package/static/build/config/index.js +6 -0
  45. package/static/build/config/util.js +66 -15
  46. package/static/build/data/cron.js +3 -1
  47. package/static/build/data/cronStats.js +59 -0
  48. package/static/build/data/env.js +2 -0
  49. package/static/build/data/notify.js +11 -1
  50. package/static/build/data/runningInstance.js +57 -0
  51. package/static/build/loaders/app.js +1 -1
  52. package/static/build/loaders/db.js +6 -0
  53. package/static/build/loaders/express.js +2 -1
  54. package/static/build/loaders/initData.js +19 -2
  55. package/static/build/loaders/initFile.js +2 -0
  56. package/static/build/schedule/api.js +1 -1
  57. package/static/build/schedule/client.js +9 -1
  58. package/static/build/schedule/health.js +1 -1
  59. package/static/build/services/config.js +19 -5
  60. package/static/build/services/cron.js +118 -8
  61. package/static/build/services/env.js +31 -3
  62. package/static/build/services/grpc.js +32 -6
  63. package/static/build/services/http.js +33 -18
  64. package/static/build/services/notify.js +40 -3
  65. package/static/build/services/open.js +2 -1
  66. package/static/build/services/sshKey.js +6 -3
  67. package/static/build/services/subscription.js +2 -1
  68. package/static/build/services/system.js +22 -7
  69. package/static/build/services/user.js +8 -7
  70. package/static/build/shared/i18n.js +105 -0
  71. package/static/build/shared/pLimit.js +12 -1
  72. package/static/build/shared/runCron.js +5 -0
  73. package/static/build/validation/schedule.js +1 -0
  74. package/static/dist/1089.0ecc5383.async.js +1 -0
  75. package/static/dist/1147.c420132e.async.js +1 -0
  76. package/static/dist/1192.4e5740f2.async.js +1 -0
  77. package/static/dist/1214.c6469b53.async.js +1 -0
  78. package/static/dist/134.54df9e38.async.js +1 -0
  79. package/static/dist/1352.96a77e1d.async.js +1 -0
  80. package/static/dist/{1765.d8e002d7.async.js → 1765.5ac01a93.async.js} +1 -1
  81. package/static/dist/1836.f0b74cf1.async.js +1 -0
  82. package/static/dist/{1885.e0d00d2d.async.js → 1885.e1ea09f6.async.js} +1 -1
  83. package/static/dist/1967.3f3945d0.async.js +1 -0
  84. package/static/dist/{2096.383c1047.async.js → 2096.6d98fd12.async.js} +1 -1
  85. package/static/dist/2208.f7ba3dfa.async.js +1 -0
  86. package/static/dist/2286.164bb089.async.js +1 -0
  87. package/static/dist/2476.4e9b0992.async.js +1 -0
  88. package/static/dist/2537.2b262ee0.async.js +1 -0
  89. package/static/dist/{255.12f03ab2.async.js → 255.8a80b983.async.js} +1 -1
  90. package/static/dist/2635.d4c59d23.async.js +1 -0
  91. package/static/dist/2808.cdc0995c.async.js +1 -0
  92. package/static/dist/{2821.be3dc88e.async.js → 2821.651f31e5.async.js} +1 -1
  93. package/static/dist/2986.4c49eef7.async.js +1 -0
  94. package/static/dist/300.08ac9875.async.js +1 -0
  95. package/static/dist/{3191.70bc19db.async.js → 3191.63263871.async.js} +1 -1
  96. package/static/dist/3714.8d6dba9e.async.js +1 -0
  97. package/static/dist/3906.a5eee612.async.js +1 -0
  98. package/static/dist/{6541.a6d499de.async.js → 3948.4fe809fd.async.js} +1 -1
  99. package/static/dist/{5171.7fc6d0a2.async.js → 4573.16f19278.async.js} +1 -1
  100. package/static/dist/{4859.93e63ea6.async.js → 4859.6592cebb.async.js} +1 -1
  101. package/static/dist/4887.8e3ae573.async.js +1 -0
  102. package/static/dist/{4902.54ecbdb5.async.js → 4902.555f92ab.async.js} +1 -1
  103. package/static/dist/{4934.1ca6b6b0.async.js → 4934.f3539d08.async.js} +1 -1
  104. package/static/dist/5077.cbd111cd.async.js +1 -0
  105. package/static/dist/{6247.b550d996.async.js → 5157.7c5af144.async.js} +1 -1
  106. package/static/dist/{540.481d4708.async.js → 540.19ddf020.async.js} +1 -1
  107. package/static/dist/{5970.10ac4f16.async.js → 5970.d3a6e7bd.async.js} +1 -1
  108. package/static/dist/{6013.2d7bb12a.async.js → 6013.4e38de36.async.js} +1 -1
  109. package/static/dist/{6016.9c379049.async.js → 6016.1e6574b6.async.js} +1 -1
  110. package/static/dist/{6035.5889ddc7.async.js → 6035.32ebfad9.async.js} +1 -1
  111. package/static/dist/6339.ab305e96.async.js +1 -0
  112. package/static/dist/6569.55177f6a.async.js +1 -0
  113. package/static/dist/6610.c111af7e.async.js +1 -0
  114. package/static/dist/{3034.6413c38e.async.js → 6638.87a163d2.async.js} +1 -1
  115. package/static/dist/{6646.5fc37228.async.js → 6646.95e92533.async.js} +1 -1
  116. package/static/dist/6665.1d099ad1.async.js +1 -0
  117. package/static/dist/{7355.b7c0562f.async.js → 7355.f9f263d8.async.js} +1 -1
  118. package/static/dist/{7384.065ccae2.async.js → 7384.1bb449d5.async.js} +1 -1
  119. package/static/dist/7441.ee1bf2bb.async.js +1 -0
  120. package/static/dist/{7508.a31662a3.async.js → 7508.7dcee91c.async.js} +1 -1
  121. package/static/dist/{7802.6b73f16a.async.js → 7802.34255805.async.js} +1 -1
  122. package/static/dist/{7984.e6bb9378.async.js → 7984.594296a5.async.js} +1 -1
  123. package/static/dist/{5653.4fce7ce8.async.js → 8033.5cb31493.async.js} +1 -1
  124. package/static/dist/8147.2fb55202.async.js +1 -0
  125. package/static/dist/8187.48c130d6.async.js +1 -0
  126. package/static/dist/8495.d53e15ca.async.js +1 -0
  127. package/static/dist/8587.315b06c0.async.js +1 -0
  128. package/static/dist/8826.2447a104.async.js +1 -0
  129. package/static/dist/{2742.4852aac8.async.js → 8865.ed665d31.async.js} +1 -1
  130. package/static/dist/901.7ee5c6d3.async.js +1 -0
  131. package/static/dist/9271.231db2ce.async.js +1 -0
  132. package/static/dist/9323.a33f47da.async.js +1 -0
  133. package/static/dist/{9730.30083c91.async.js → 9730.801665a3.async.js} +1 -1
  134. package/static/dist/{9761.627ca3b5.async.js → 9761.360a19d8.async.js} +1 -1
  135. package/static/dist/index.html +2 -2
  136. package/static/dist/layouts__index.a7a2bfe0.async.js +1 -0
  137. package/static/dist/layouts__index.adf0692f.chunk.css +1 -0
  138. package/static/dist/preload_helper.0431c0f3.js +1 -0
  139. package/static/dist/{src__pages__config__index.622b6ee8.async.js → src__pages__config__index.a22ff7dc.async.js} +1 -1
  140. package/static/dist/{src__pages__crontab__const.323d5124.async.js → src__pages__crontab__const.aba07deb.async.js} +1 -1
  141. package/static/dist/src__pages__crontab__detail.b9c36808.async.js +1 -0
  142. package/static/dist/src__pages__crontab__index.fed99fd0.async.js +1 -0
  143. package/static/dist/{src__pages__crontab__logModal.5e6a4bf2.async.js → src__pages__crontab__logModal.0b8cce8c.async.js} +1 -1
  144. package/static/dist/src__pages__crontab__modal.f7041c7c.async.js +1 -0
  145. package/static/dist/src__pages__crontab__type.d7af36e5.async.js +1 -0
  146. package/static/dist/{src__pages__crontab__viewCreateModal.ffcf7a24.async.js → src__pages__crontab__viewCreateModal.4d589f66.async.js} +1 -1
  147. package/static/dist/{src__pages__crontab__viewManageModal.c2724575.async.js → src__pages__crontab__viewManageModal.0e317746.async.js} +1 -1
  148. package/static/dist/src__pages__dashboard__index.b30f2f47.async.js +1 -0
  149. package/static/dist/{src__pages__dependence__logModal.f123e2ac.async.js → src__pages__dependence__logModal.0681830b.async.js} +1 -1
  150. package/static/dist/src__pages__dependence__modal.11124896.async.js +1 -0
  151. package/static/dist/src__pages__env__editNameModal.5d264b25.async.js +1 -0
  152. package/static/dist/src__pages__env__index.baa27d4e.async.js +1 -0
  153. package/static/dist/src__pages__env__modal.7f2ef1bc.async.js +1 -0
  154. package/static/dist/src__pages__error__index.f156b45e.async.js +1 -0
  155. package/static/dist/src__pages__initialization__index.e96d4ba8.async.js +1 -0
  156. package/static/dist/{src__pages__log__index.cf00c9af.async.js → src__pages__log__index.e0978bae.async.js} +1 -1
  157. package/static/dist/{src__pages__login__index.cd6e3152.async.js → src__pages__login__index.8c813eb1.async.js} +1 -1
  158. package/static/dist/{src__pages__script__components__UnsupportedFilePreview__index.39074c68.async.js → src__pages__script__components__UnsupportedFilePreview__index.c347a13a.async.js} +1 -1
  159. package/static/dist/src__pages__script__editNameModal.3e7e100d.async.js +1 -0
  160. package/static/dist/src__pages__script__index.2765d1b8.async.js +1 -0
  161. package/static/dist/src__pages__script__renameModal.5e987ef5.async.js +1 -0
  162. package/static/dist/src__pages__script__saveModal.3f9d23d6.async.js +1 -0
  163. package/static/dist/src__pages__script__setting.a535793a.async.js +1 -0
  164. package/static/dist/src__pages__setting__appModal.251cd14f.async.js +1 -0
  165. package/static/dist/src__pages__setting__dependence.8a7a9529.async.js +1 -0
  166. package/static/dist/src__pages__setting__index.cc85fdfb.async.js +1 -0
  167. package/static/dist/src__pages__setting__notification.390fc905.async.js +1 -0
  168. package/static/dist/src__pages__setting__other.b22d2165.async.js +1 -0
  169. package/static/dist/src__pages__setting__security.598720a8.async.js +1 -0
  170. package/static/dist/src__pages__setting__systemLog.67406721.async.js +1 -0
  171. package/static/dist/{src__pages__subscription__logModal.0caa7283.async.js → src__pages__subscription__logModal.3864b37f.async.js} +1 -1
  172. package/static/dist/src__pages__subscription__modal.3562c670.async.js +1 -0
  173. package/static/dist/{umi.ef8199a4.js → umi.ca04a019.js} +1 -1
  174. package/version.yaml +33 -4
  175. package/sample/notify.py.save +0 -1010
  176. package/static/dist/105.85a5c47a.async.js +0 -1
  177. package/static/dist/1083.f86ce804.async.js +0 -1
  178. package/static/dist/1147.32f41a88.async.js +0 -1
  179. package/static/dist/1352.ab6da08e.async.js +0 -1
  180. package/static/dist/1690.f0290540.async.js +0 -1
  181. package/static/dist/1742.6cbe5aca.async.js +0 -1
  182. package/static/dist/2208.8e3a7325.async.js +0 -1
  183. package/static/dist/5312.74b95311.async.js +0 -1
  184. package/static/dist/5691.931f59c5.async.js +0 -1
  185. package/static/dist/6159.55cb068a.async.js +0 -1
  186. package/static/dist/7025.f4080d63.async.js +0 -1
  187. package/static/dist/739.6be5552a.async.js +0 -1
  188. package/static/dist/7571.4f6240b1.async.js +0 -1
  189. package/static/dist/786.59fc381c.async.js +0 -1
  190. package/static/dist/8317.c44c1ebd.async.js +0 -1
  191. package/static/dist/8826.0291edfd.async.js +0 -1
  192. package/static/dist/955.3c9481f7.async.js +0 -1
  193. package/static/dist/layouts__index.1fce90e0.chunk.css +0 -1
  194. package/static/dist/layouts__index.8dcf1576.async.js +0 -1
  195. package/static/dist/preload_helper.116a62f6.js +0 -1
  196. package/static/dist/src__pages__crontab__detail.b07f0c0a.async.js +0 -1
  197. package/static/dist/src__pages__crontab__index.2e2e1096.async.js +0 -1
  198. package/static/dist/src__pages__crontab__modal.4d8c2a22.async.js +0 -1
  199. package/static/dist/src__pages__crontab__type.db7c1858.async.js +0 -1
  200. package/static/dist/src__pages__dependence__modal.631ffb5b.async.js +0 -1
  201. package/static/dist/src__pages__env__editNameModal.ff85ef8c.async.js +0 -1
  202. package/static/dist/src__pages__env__index.a0a2fece.async.js +0 -1
  203. package/static/dist/src__pages__env__modal.d1004662.async.js +0 -1
  204. package/static/dist/src__pages__error__index.1bc3c90b.async.js +0 -1
  205. package/static/dist/src__pages__initialization__index.8b1cbaf9.async.js +0 -1
  206. package/static/dist/src__pages__script__editNameModal.53424d49.async.js +0 -1
  207. package/static/dist/src__pages__script__index.e65df827.async.js +0 -1
  208. package/static/dist/src__pages__script__renameModal.4bbe7fb1.async.js +0 -1
  209. package/static/dist/src__pages__script__saveModal.cf449f3c.async.js +0 -1
  210. package/static/dist/src__pages__script__setting.b345d59a.async.js +0 -1
  211. package/static/dist/src__pages__setting__appModal.03faec89.async.js +0 -1
  212. package/static/dist/src__pages__setting__dependence.4495c7b6.async.js +0 -1
  213. package/static/dist/src__pages__setting__index.6919c399.async.js +0 -1
  214. package/static/dist/src__pages__setting__notification.d6a3884f.async.js +0 -1
  215. package/static/dist/src__pages__setting__other.0d931d6f.async.js +0 -1
  216. package/static/dist/src__pages__setting__security.91cb545f.async.js +0 -1
  217. package/static/dist/src__pages__setting__systemLog.1d433a48.async.js +0 -1
  218. package/static/dist/src__pages__subscription__modal.0b84f6cf.async.js +0 -1
package/.env.example CHANGED
@@ -1,6 +1,11 @@
1
1
  GRPC_PORT=5500
2
2
  BACK_PORT=5700
3
3
 
4
+ # 服务绑定地址,默认 ::(IPv6 通配,双栈系统同时支持 IPv4/IPv6)
5
+ # 纯 IPv4 环境自动 fallback 到 0.0.0.0,也可手动指定
6
+ # BIND_HOST=0.0.0.0
7
+ # BIND_HOST_GRPC=0.0.0.0
8
+
4
9
  LOG_LEVEL='info'
5
10
 
6
11
  JWT_SECRET=
package/AGENTS.md ADDED
@@ -0,0 +1,43 @@
1
+ <!-- gitnexus:start -->
2
+ # GitNexus — Code Intelligence
3
+
4
+ This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
5
+
6
+ > Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
7
+
8
+ ## Always Do
9
+
10
+ - **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
11
+ - **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
12
+ - **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
13
+ - When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
14
+ - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
15
+
16
+ ## Never Do
17
+
18
+ - NEVER edit a function, class, or method without first running `impact` on it.
19
+ - NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
20
+ - NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
21
+ - NEVER commit changes without running `detect_changes()` to check affected scope.
22
+
23
+ ## Resources
24
+
25
+ | Resource | Use for |
26
+ |----------|---------|
27
+ | `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
28
+ | `gitnexus://repo/qinglong/clusters` | All functional areas |
29
+ | `gitnexus://repo/qinglong/processes` | All execution flows |
30
+ | `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
31
+
32
+ ## CLI
33
+
34
+ | Task | Read this skill file |
35
+ |------|---------------------|
36
+ | Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
37
+ | Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
38
+ | Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
39
+ | Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
40
+ | Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
41
+ | Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
42
+
43
+ <!-- gitnexus:end -->
package/CLAUDE.md ADDED
@@ -0,0 +1,43 @@
1
+ <!-- gitnexus:start -->
2
+ # GitNexus — Code Intelligence
3
+
4
+ This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
5
+
6
+ > Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
7
+
8
+ ## Always Do
9
+
10
+ - **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
11
+ - **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
12
+ - **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
13
+ - When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
14
+ - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
15
+
16
+ ## Never Do
17
+
18
+ - NEVER edit a function, class, or method without first running `impact` on it.
19
+ - NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
20
+ - NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
21
+ - NEVER commit changes without running `detect_changes()` to check affected scope.
22
+
23
+ ## Resources
24
+
25
+ | Resource | Use for |
26
+ |----------|---------|
27
+ | `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
28
+ | `gitnexus://repo/qinglong/clusters` | All functional areas |
29
+ | `gitnexus://repo/qinglong/processes` | All execution flows |
30
+ | `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
31
+
32
+ ## CLI
33
+
34
+ | Task | Read this skill file |
35
+ |------|---------------------|
36
+ | Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
37
+ | Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
38
+ | Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
39
+ | Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
40
+ | Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
41
+ | Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
42
+
43
+ <!-- gitnexus:end -->
package/README-en.md CHANGED
@@ -48,6 +48,17 @@ docker pull whyour/qinglong:latest
48
48
  docker pull whyour/qinglong:debian
49
49
  ```
50
50
 
51
+ When running the `debian` image as a non-root user, specify `--user qinglong`:
52
+
53
+ ```bash
54
+ docker run -d \
55
+ -v /path/to/ql/data:/ql/data \
56
+ -p 5700:5700 \
57
+ --user qinglong \
58
+ --name qinglong \
59
+ whyour/qinglong:debian
60
+ ```
61
+
51
62
  ### npm
52
63
 
53
64
  The npm version supports `debian/ubuntu/alpine` systems and requires `node/npm/python3/pip3/pnpm` to be installed.
package/README.md CHANGED
@@ -50,6 +50,17 @@ docker pull whyour/qinglong:latest
50
50
  docker pull whyour/qinglong:debian
51
51
  ```
52
52
 
53
+ 使用 `debian` 镜像以非 root 用户运行时,需指定 `--user qinglong`:
54
+
55
+ ```bash
56
+ docker run -d \
57
+ -v /path/to/ql/data:/ql/data \
58
+ -p 5700:5700 \
59
+ --user qinglong \
60
+ --name qinglong \
61
+ whyour/qinglong:debian
62
+ ```
63
+
53
64
  ### npm
54
65
 
55
66
  npm 版本支持 `debian/ubuntu/alpine` 系统,需要自行安装 `node/npm/python3/pip3/pnpm`
package/docker/Dockerfile CHANGED
@@ -1,18 +1,13 @@
1
- FROM node:22-slim AS nodebuilder
2
-
3
- FROM python:3.11-slim-bookworm AS builder
1
+ FROM python:3.11-alpine3.18 AS builder
4
2
  COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
5
- COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
6
- COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
7
- RUN set -x && \
8
- ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
9
- apt-get update && \
10
- apt-get install --no-install-recommends -y libatomic1 && \
11
- npm i -g pnpm@8.3.1 && \
12
- cd /tmp/build && \
13
- pnpm install --prod
14
-
15
- FROM python:3.11-slim-bookworm
3
+ RUN set -x \
4
+ && apk update \
5
+ && apk add nodejs npm git \
6
+ && npm i -g pnpm@8.3.1 pm2 ts-node \
7
+ && cd /tmp/build \
8
+ && pnpm install --prod
9
+
10
+ FROM python:3.11-alpine
16
11
 
17
12
  ARG QL_MAINTAINER="whyour"
18
13
  LABEL maintainer="${QL_MAINTAINER}"
@@ -22,67 +17,56 @@ ARG PYTHON_SHORT_VERSION=3.11
22
17
 
23
18
  ENV QL_DIR=/ql \
24
19
  QL_BRANCH=${QL_BRANCH} \
20
+ QL_CONTAINER=true \
25
21
  LANG=C.UTF-8 \
26
22
  SHELL=/bin/bash \
27
23
  PS1="\u@\h:\w \$ "
28
24
 
29
- ARG QL_UID=5432
30
- ARG QL_GID=5432
31
- RUN groupadd -g ${QL_GID} qinglong && \
32
- useradd -m -u ${QL_UID} -g ${QL_GID} -s /bin/bash qinglong && \
33
- mkdir -p /home/qinglong/bin /home/qinglong/.ssh && \
34
- chmod 700 /home/qinglong/.ssh && \
35
- chown -R ${QL_UID}:${QL_GID} /home/qinglong
36
-
37
- ENV QL_USER=qinglong
38
- ENV QL_HOME=/home/$QL_USER
39
-
40
- COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
41
- COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
42
-
43
- RUN set -x && \
44
- ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
45
- ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \
46
- apt-get update && \
47
- apt-get upgrade -y && \
48
- apt-get install --no-install-recommends -y git \
25
+ VOLUME /ql/data
26
+
27
+ EXPOSE 5700
28
+
29
+ COPY --from=builder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
30
+ COPY --from=builder /usr/local/bin/. /usr/local/bin/
31
+
32
+ RUN set -x \
33
+ && apk update -f \
34
+ && apk upgrade \
35
+ && apk --no-cache add -f bash \
36
+ coreutils \
37
+ git \
49
38
  curl \
50
39
  wget \
51
40
  tzdata \
52
41
  perl \
53
42
  openssl \
54
- openssh-client \
43
+ nodejs \
55
44
  jq \
45
+ openssh \
56
46
  procps \
57
47
  netcat-openbsd \
58
48
  unzip \
59
- libatomic1 && \
60
- apt-get clean && \
61
- ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
62
- echo "Asia/Shanghai" >/etc/timezone && \
63
- git config --global user.email "qinglong@users.noreply.github.com" && \
64
- git config --global user.name "qinglong" && \
65
- git config --global http.postBuffer 524288000 && \
66
- npm install -g pnpm@8.3.1 pm2 ts-node && \
67
- rm -rf /root/.cache && \
68
- rm -rf /root/.npm && \
69
- rm -rf /etc/apt/apt.conf.d/docker-clean && \
70
- ulimit -c 0
71
-
72
- RUN mkdir -p ${QL_DIR} && \
73
- chown -R ${QL_UID}:${QL_GID} ${QL_DIR}
74
-
75
- USER qinglong
49
+ npm \
50
+ && rm -rf /var/cache/apk/* \
51
+ && apk update \
52
+ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
53
+ && echo "Asia/Shanghai" > /etc/timezone \
54
+ && git config --global user.email "qinglong@users.noreply.github.com" \
55
+ && git config --global user.name "qinglong" \
56
+ && git config --global http.postBuffer 524288000 \
57
+ && rm -rf /root/.cache \
58
+ && ulimit -c 0
59
+
76
60
  ARG SOURCE_COMMIT
77
- RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} && \
78
- cd ${QL_DIR} && \
79
- cp -f .env.example .env && \
80
- chmod 777 ${QL_DIR}/shell/*.sh && \
81
- chmod 777 ${QL_DIR}/docker/*.sh && \
82
- git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /tmp/static && \
83
- mkdir -p ${QL_DIR}/static && \
84
- cp -rf /tmp/static/* ${QL_DIR}/static && \
85
- rm -rf /tmp/static
61
+ RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
62
+ && cd ${QL_DIR} \
63
+ && cp -f .env.example .env \
64
+ && chmod 777 ${QL_DIR}/shell/*.sh \
65
+ && chmod 777 ${QL_DIR}/docker/*.sh \
66
+ && git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
67
+ && mkdir -p ${QL_DIR}/static \
68
+ && cp -rf /static/* ${QL_DIR}/static \
69
+ && rm -rf /static
86
70
 
87
71
  ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
88
72
  PYTHON_HOME=${QL_DIR}/data/dep_cache/python3 \
@@ -90,23 +74,21 @@ ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
90
74
  HOME=/root
91
75
 
92
76
  ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PNPM_HOME}:${PYTHON_HOME}/bin:${HOME}/bin \
93
- NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules:${PNPM_HOME}/global/5/node_modules \
77
+ NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules \
94
78
  PIP_CACHE_DIR=${PYTHON_HOME}/pip \
95
79
  PYTHONPATH=${PYTHON_HOME}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}/site-packages
96
80
 
97
81
  RUN pip3 install --prefix ${PYTHON_HOME} requests
98
82
 
99
- COPY --chown=qinglong:qinglong --from=builder /tmp/build/node_modules/. /ql/node_modules/
83
+ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
100
84
 
101
- USER root
85
+ RUN ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \
86
+ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/ql \
87
+ && chmod +x /usr/local/bin/task /usr/local/bin/ql
102
88
 
103
89
  WORKDIR ${QL_DIR}
104
90
 
105
91
  HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
106
- CMD curl -sf --noproxy '*' http://127.0.0.1:5700/api/health || exit 1
92
+ CMD curl -sf --noproxy '*' http://localhost:${QlPort:-5700}/api/health || exit 1
107
93
 
108
94
  ENTRYPOINT ["./docker/docker-entrypoint.sh"]
109
-
110
- VOLUME /ql/data
111
-
112
- EXPOSE 5700
@@ -0,0 +1,94 @@
1
+ FROM python:3.10-alpine3.18 AS builder
2
+ COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
3
+ RUN set -x \
4
+ && apk update \
5
+ && apk add nodejs npm git \
6
+ && npm i -g pnpm@8.3.1 pm2 ts-node \
7
+ && cd /tmp/build \
8
+ && pnpm install --prod
9
+
10
+ FROM python:3.10-alpine
11
+
12
+ ARG QL_MAINTAINER="whyour"
13
+ LABEL maintainer="${QL_MAINTAINER}"
14
+ ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
15
+ ARG QL_BRANCH=develop
16
+ ARG PYTHON_SHORT_VERSION=3.10
17
+
18
+ ENV QL_DIR=/ql \
19
+ QL_BRANCH=${QL_BRANCH} \
20
+ QL_CONTAINER=true \
21
+ LANG=C.UTF-8 \
22
+ SHELL=/bin/bash \
23
+ PS1="\u@\h:\w \$ "
24
+
25
+ VOLUME /ql/data
26
+
27
+ EXPOSE 5700
28
+
29
+ COPY --from=builder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
30
+ COPY --from=builder /usr/local/bin/. /usr/local/bin/
31
+
32
+ RUN set -x \
33
+ && apk update -f \
34
+ && apk upgrade \
35
+ && apk --no-cache add -f bash \
36
+ coreutils \
37
+ git \
38
+ curl \
39
+ wget \
40
+ tzdata \
41
+ perl \
42
+ openssl \
43
+ nodejs \
44
+ jq \
45
+ openssh \
46
+ procps \
47
+ netcat-openbsd \
48
+ unzip \
49
+ npm \
50
+ && rm -rf /var/cache/apk/* \
51
+ && apk update \
52
+ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
53
+ && echo "Asia/Shanghai" > /etc/timezone \
54
+ && git config --global user.email "qinglong@users.noreply.github.com" \
55
+ && git config --global user.name "qinglong" \
56
+ && git config --global http.postBuffer 524288000 \
57
+ && rm -rf /root/.cache \
58
+ && ulimit -c 0
59
+
60
+ ARG SOURCE_COMMIT
61
+ RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
62
+ && cd ${QL_DIR} \
63
+ && cp -f .env.example .env \
64
+ && chmod 777 ${QL_DIR}/shell/*.sh \
65
+ && chmod 777 ${QL_DIR}/docker/*.sh \
66
+ && git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
67
+ && mkdir -p ${QL_DIR}/static \
68
+ && cp -rf /static/* ${QL_DIR}/static \
69
+ && rm -rf /static
70
+
71
+ ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
72
+ PYTHON_HOME=${QL_DIR}/data/dep_cache/python3 \
73
+ PYTHONUSERBASE=${QL_DIR}/data/dep_cache/python3 \
74
+ HOME=/root
75
+
76
+ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PNPM_HOME}:${PYTHON_HOME}/bin:${HOME}/bin \
77
+ NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules \
78
+ PIP_CACHE_DIR=${PYTHON_HOME}/pip \
79
+ PYTHONPATH=${PYTHON_HOME}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}/site-packages
80
+
81
+ RUN pip3 install --prefix ${PYTHON_HOME} requests
82
+
83
+ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
84
+
85
+ RUN ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \
86
+ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/ql \
87
+ && chmod +x /usr/local/bin/task /usr/local/bin/ql
88
+
89
+ WORKDIR ${QL_DIR}
90
+
91
+ HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
92
+ CMD curl -sf --noproxy '*' http://localhost:${QlPort:-5700}/api/health || exit 1
93
+
94
+ ENTRYPOINT ["./docker/docker-entrypoint.sh"]
@@ -0,0 +1,120 @@
1
+ FROM node:22-slim AS nodebuilder
2
+
3
+ FROM python:3.11-slim-bookworm AS builder
4
+ COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
5
+ COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
6
+ COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
7
+ RUN set -x && \
8
+ ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
9
+ apt-get update && \
10
+ apt-get install --no-install-recommends -y libatomic1 && \
11
+ npm i -g pnpm@8.3.1 && \
12
+ cd /tmp/build && \
13
+ pnpm install --prod
14
+
15
+ FROM python:3.11-slim-bookworm
16
+
17
+ ARG QL_MAINTAINER="whyour"
18
+ LABEL maintainer="${QL_MAINTAINER}"
19
+ ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
20
+ ARG QL_BRANCH=develop
21
+ ARG PYTHON_SHORT_VERSION=3.11
22
+
23
+ ENV QL_DIR=/ql \
24
+ QL_BRANCH=${QL_BRANCH} \
25
+ QL_CONTAINER=true \
26
+ LANG=C.UTF-8 \
27
+ SHELL=/bin/bash \
28
+ PS1="\u@\h:\w \$ "
29
+
30
+ ARG QL_UID=5432
31
+ ARG QL_GID=5432
32
+ RUN groupadd -g ${QL_GID} qinglong && \
33
+ useradd -m -u ${QL_UID} -g ${QL_GID} -s /bin/bash qinglong && \
34
+ mkdir -p /home/qinglong/bin /home/qinglong/.ssh && \
35
+ chmod 700 /home/qinglong/.ssh && \
36
+ chown -R ${QL_UID}:${QL_GID} /home/qinglong && \
37
+ mkdir -p /etc/sudoers.d && \
38
+ echo 'qinglong ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/qinglong
39
+
40
+ ENV QL_USER=qinglong
41
+ ENV QL_HOME=/home/$QL_USER
42
+
43
+ COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
44
+ COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
45
+
46
+ RUN set -x && \
47
+ ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
48
+ ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \
49
+ apt-get update && \
50
+ apt-get upgrade -y && \
51
+ apt-get install --no-install-recommends -y git \
52
+ curl \
53
+ wget \
54
+ tzdata \
55
+ perl \
56
+ openssl \
57
+ openssh-client \
58
+ jq \
59
+ procps \
60
+ netcat-openbsd \
61
+ sudo \
62
+ unzip \
63
+ libatomic1 && \
64
+ apt-get clean && \
65
+ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
66
+ echo "Asia/Shanghai" >/etc/timezone && \
67
+ git config --global user.email "qinglong@users.noreply.github.com" && \
68
+ git config --global user.name "qinglong" && \
69
+ git config --global http.postBuffer 524288000 && \
70
+ npm install -g pnpm@8.3.1 pm2 ts-node && \
71
+ rm -rf /root/.cache && \
72
+ rm -rf /root/.npm && \
73
+ rm -rf /etc/apt/apt.conf.d/docker-clean && \
74
+ ulimit -c 0
75
+
76
+ RUN mkdir -p ${QL_DIR} && \
77
+ chown -R ${QL_UID}:${QL_GID} ${QL_DIR}
78
+
79
+ USER qinglong
80
+ ARG SOURCE_COMMIT
81
+ RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} && \
82
+ cd ${QL_DIR} && \
83
+ cp -f .env.example .env && \
84
+ chmod 777 ${QL_DIR}/shell/*.sh && \
85
+ chmod 777 ${QL_DIR}/docker/*.sh && \
86
+ git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /tmp/static && \
87
+ mkdir -p ${QL_DIR}/static && \
88
+ cp -rf /tmp/static/* ${QL_DIR}/static && \
89
+ rm -rf /tmp/static
90
+
91
+ ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
92
+ PYTHON_HOME=${QL_DIR}/data/dep_cache/python3 \
93
+ PYTHONUSERBASE=${QL_DIR}/data/dep_cache/python3 \
94
+ HOME=/home/qinglong
95
+
96
+ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PNPM_HOME}:${PYTHON_HOME}/bin:${HOME}/bin \
97
+ NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules \
98
+ PIP_CACHE_DIR=${PYTHON_HOME}/pip \
99
+ PYTHONPATH=${PYTHON_HOME}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}/site-packages
100
+
101
+ RUN pip3 install --prefix ${PYTHON_HOME} requests
102
+
103
+ COPY --chown=qinglong:qinglong --from=builder /tmp/build/node_modules/. /ql/node_modules/
104
+
105
+ USER root
106
+
107
+ RUN ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \
108
+ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/ql \
109
+ && chmod +x /usr/local/bin/task /usr/local/bin/ql
110
+
111
+ WORKDIR ${QL_DIR}
112
+
113
+ HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
114
+ CMD curl -sf --noproxy '*' http://localhost:${QlPort:-5700}/api/health || exit 1
115
+
116
+ ENTRYPOINT ["./docker/docker-entrypoint.sh"]
117
+
118
+ VOLUME /ql/data
119
+
120
+ EXPOSE 5700
@@ -22,6 +22,7 @@ ARG PYTHON_SHORT_VERSION=3.10
22
22
 
23
23
  ENV QL_DIR=/ql \
24
24
  QL_BRANCH=${QL_BRANCH} \
25
+ QL_CONTAINER=true \
25
26
  LANG=C.UTF-8 \
26
27
  SHELL=/bin/bash \
27
28
  PS1="\u@\h:\w \$ "
@@ -32,7 +33,9 @@ RUN groupadd -g ${QL_GID} qinglong && \
32
33
  useradd -m -u ${QL_UID} -g ${QL_GID} -s /bin/bash qinglong && \
33
34
  mkdir -p /home/qinglong/bin /home/qinglong/.ssh && \
34
35
  chmod 700 /home/qinglong/.ssh && \
35
- chown -R ${QL_UID}:${QL_GID} /home/qinglong
36
+ chown -R ${QL_UID}:${QL_GID} /home/qinglong && \
37
+ mkdir -p /etc/sudoers.d && \
38
+ echo 'qinglong ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/qinglong
36
39
 
37
40
  ENV QL_USER=qinglong
38
41
  ENV QL_HOME=/home/$QL_USER
@@ -54,6 +57,7 @@ RUN set -x && \
54
57
  jq \
55
58
  procps \
56
59
  netcat-openbsd \
60
+ sudo \
57
61
  unzip \
58
62
  libatomic1 && \
59
63
  apt-get clean && \
@@ -87,10 +91,10 @@ RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} && \
87
91
  ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
88
92
  PYTHON_HOME=${QL_DIR}/data/dep_cache/python3 \
89
93
  PYTHONUSERBASE=${QL_DIR}/data/dep_cache/python3 \
90
- HOME=/root
94
+ HOME=/home/qinglong
91
95
 
92
96
  ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PNPM_HOME}:${PYTHON_HOME}/bin:${HOME}/bin \
93
- NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules:${PNPM_HOME}/global/5/node_modules \
97
+ NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules \
94
98
  PIP_CACHE_DIR=${PYTHON_HOME}/pip \
95
99
  PYTHONPATH=${PYTHON_HOME}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}/site-packages
96
100
 
@@ -100,13 +104,17 @@ COPY --chown=qinglong:qinglong --from=builder /tmp/build/node_modules/. /ql/node
100
104
 
101
105
  USER root
102
106
 
107
+ RUN ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \
108
+ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/ql \
109
+ && chmod +x /usr/local/bin/task /usr/local/bin/ql
110
+
103
111
  WORKDIR ${QL_DIR}
104
112
 
105
113
  HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
106
- CMD curl -sf --noproxy '*' http://127.0.0.1:5700/api/health || exit 1
114
+ CMD curl -sf --noproxy '*' http://localhost:${QlPort:-5700}/api/health || exit 1
107
115
 
108
116
  ENTRYPOINT ["./docker/docker-entrypoint.sh"]
109
117
 
110
118
  VOLUME /ql/data
111
-
119
+
112
120
  EXPOSE 5700