@lazycatcloud/lzc-cli 1.1.5 → 1.1.8

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 (52) hide show
  1. package/cmds/app.js +1 -5
  2. package/cmds/dev.js +11 -5
  3. package/lib/api.js +24 -7
  4. package/lib/app/index.js +93 -0
  5. package/lib/app/lpk_build.js +241 -0
  6. package/lib/app/lpk_create.js +201 -0
  7. package/lib/app/lpk_devshell.js +621 -0
  8. package/lib/app/lpk_installer.js +67 -0
  9. package/lib/appstore/login.js +134 -0
  10. package/lib/archiver.js +0 -42
  11. package/lib/autologin.js +82 -0
  12. package/lib/box/check_qemu.js +39 -16
  13. package/lib/box/hportal.js +7 -1
  14. package/lib/box/index.js +8 -7
  15. package/lib/box/qemu_vm_mgr.js +12 -11
  16. package/lib/dev.js +0 -4
  17. package/lib/env.js +16 -49
  18. package/lib/generator.js +2 -2
  19. package/lib/sdk.js +5 -6
  20. package/lib/utils.js +66 -144
  21. package/package.json +8 -3
  22. package/scripts/cli.js +91 -12
  23. package/template/_lazycat/debug/shell/Dockerfile +5 -3
  24. package/template/_lazycat/debug/shell/docker-compose.override.yml.in +2 -12
  25. package/template/_lazycat/debug/shell/entrypoint.sh +3 -1
  26. package/template/_lpk/Dockerfile.in +8 -0
  27. package/template/_lpk/devshell/Dockerfile +18 -0
  28. package/template/_lpk/devshell/build.sh +5 -0
  29. package/template/_lpk/devshell/entrypoint.sh +8 -0
  30. package/template/_lpk/devshell/sshd_config +117 -0
  31. package/template/_lpk/manifest.yml.in +17 -0
  32. package/template/_lpk/sync/Dockerfile +16 -0
  33. package/template/_lpk/sync/build.sh +5 -0
  34. package/template/_lpk/sync/entrypoint.sh +8 -0
  35. package/template/_lpk/sync/sshd_config +117 -0
  36. package/template/_lpk/sync.manifest.yml.in +3 -0
  37. package/template/golang/build.sh +6 -0
  38. package/template/golang/lzc-build.yml +52 -0
  39. package/template/ionic_vue3/lzc-build.yml +53 -0
  40. package/template/ionic_vue3/vite.config.ts +1 -1
  41. package/template/release/golang/build.sh +1 -1
  42. package/template/release/ionic_vue3/Dockerfile +1 -1
  43. package/template/release/ionic_vue3/build.sh +1 -3
  44. package/template/release/ionic_vue3/docker-compose.yml.in +0 -5
  45. package/template/release/vue/Dockerfile +1 -1
  46. package/template/release/vue/build.sh +2 -3
  47. package/template/release/vue/docker-compose.yml.in +0 -5
  48. package/template/vue/lzc-build.yml +53 -0
  49. package/template/vue/src/main.js +3 -14
  50. package/template/vue/vue.config.js +2 -1
  51. package/template/_lazycat/debug/shell/nginx.conf.template +0 -64
  52. package/template/vue/src/lzc.js +0 -110
package/lib/sdk.js CHANGED
@@ -4,8 +4,8 @@ import Docker from "dockerode";
4
4
  import process from "process";
5
5
  import fs from "fs";
6
6
  import { Client } from "ssh2";
7
- import chalk from "chalk";
8
7
  import Key from "./key.js";
8
+ import logger from "loglevel";
9
9
 
10
10
  export async function connectOptions(host) {
11
11
  const pairs = await new Key().getKeyPair();
@@ -38,7 +38,7 @@ export class DockerClient {
38
38
  async init() {
39
39
  this.docker = !!this.host
40
40
  ? new Docker({
41
- protocal: "http",
41
+ protocal: "ssh",
42
42
  agent: ssh(await connectOptions(this.host)),
43
43
  })
44
44
  : new Docker();
@@ -47,9 +47,7 @@ export class DockerClient {
47
47
 
48
48
  async function onUncaughtException(e) {
49
49
  if (e.code == "ECONNREFUSED") {
50
- console.log(
51
- chalk.red(`无法连接 sdk 服务, 请确保 ${chalk.yellow(host)} 可以访问`)
52
- );
50
+ logger.error(`无法连接 sdk 服务, 请确保 ${host} 可以访问`);
53
51
  process.exit(1);
54
52
  } else {
55
53
  throw e;
@@ -78,6 +76,7 @@ export class SSHClient {
78
76
  this.con
79
77
  .on("ready", () => resolve(this.con))
80
78
  .on("error", (err) => {
79
+ logger.error("ssh client ", err);
81
80
  reject(err);
82
81
  })
83
82
  .on("close", () => resolve(null))
@@ -126,7 +125,7 @@ export class SSHClient {
126
125
  }
127
126
 
128
127
  export async function dockerPullLzcAppsImage(host) {
129
- console.log(chalk.yellow("* 更新lzcapp镜像, 未来可能会移除此操作"));
128
+ logger.warn("* 更新lzcapp镜像, 未来可能会移除此操作");
130
129
  const opts = await connectOptions(host);
131
130
  const client = new SSHClient(opts);
132
131
  await client.connect();
package/lib/utils.js CHANGED
@@ -8,13 +8,14 @@ import glob from "fast-glob";
8
8
  import yaml from "js-yaml";
9
9
  import mergeWith from "lodash.mergewith";
10
10
  import isArray from "lodash.isarray";
11
- import fetch from "node-fetch";
11
+ import { request } from "./autologin.js";
12
12
  import { dirname } from "path";
13
13
  import { fileURLToPath } from "url";
14
14
  import ignore from "ignore";
15
15
  import ora from "ora";
16
16
  import { desireStatusTimer } from "../lib/api.js";
17
17
  import { warn } from "console";
18
+ import { createHash } from "node:crypto";
18
19
 
19
20
  const META_MARK = "x-lazycat-app";
20
21
  const APP_FOLDER = ".lazycat";
@@ -26,103 +27,6 @@ export const envsubstr = async (templateContents, args) => {
26
27
  const parse = await importDefault("envsub/js/envsub-parser.js");
27
28
  return parse(templateContents, args);
28
29
  };
29
- /**
30
- * 为盒子安装SDK应用
31
- * @param box_url 盒子入口地址
32
- **/
33
- async function InstallSDK(box_url) {
34
- try {
35
- let url = `${box_url}/api/app/apply?id=sdk`;
36
- const resp = await fetch(url, { method: "post" });
37
- if (resp.status != 200) {
38
- throw new Error(
39
- chalk.red(
40
- `无法安装, 请确保 ${chalk.yellow(
41
- new URL(url).origin
42
- )} 可以访问或者在应用商店安装 sdk`
43
- )
44
- );
45
- }
46
- } catch (err) {
47
- throw err;
48
- }
49
- }
50
- /**
51
- * 检查SDK安装部署的状态
52
- * @param box_url 盒子入口地址
53
- **/
54
- async function checkSDKInstallStatus(box_url) {
55
- const checkSDKstatus = async function (box_url) {
56
- let url = `${box_url}/api/app/status?id=sdk`;
57
- const resp = await fetch(url);
58
- if (resp.status == 200) {
59
- const status = await resp.json();
60
- return status;
61
- } else {
62
- let text = await resp.text();
63
- throw text;
64
- }
65
- };
66
- const spinner = ora().start();
67
- let { status, info } = await checkSDKstatus(box_url);
68
- spinner.text = "部署进度";
69
- switch (status) {
70
- case "running":
71
- console.log(chalk.yellow("应用正在运行中"));
72
- break;
73
- case "error":
74
- spinner.stop();
75
- console.log(status, info);
76
- throw info.msg;
77
- default:
78
- try {
79
- await desireStatusTimer(
80
- (result) => {
81
- spinner.text = "部署进度 " + result.status;
82
- return result.status === "running";
83
- },
84
- () => {
85
- return checkSDKstatus(box_url);
86
- }
87
- );
88
- } catch (error) {
89
- throw error;
90
- } finally {
91
- spinner.stop();
92
- }
93
- break;
94
- }
95
- spinner.stop();
96
- }
97
-
98
- /**
99
- * 获取所有已安装的app
100
- * @param box_url 盒子入口地址
101
- **/
102
- async function getInstalledApps(box_url) {
103
- try {
104
- let url = `${box_url}/api/app/dump`;
105
- const resp = await fetch(url);
106
- if (resp.status != 200) throw new Error(chalk.red("获取所有已安装App失败"));
107
- return await resp.json();
108
- } catch (e) {
109
- console.log(e);
110
- }
111
- }
112
- /**
113
- * 查找某个app是否已安装]
114
- * @param box_url 盒子入口地址
115
- * @param app_id app名
116
- * */
117
- async function findAppIsInstalled(box_url, app_id) {
118
- const apps = await getInstalledApps(box_url);
119
- for (let app in apps) {
120
- if (app == app_id) {
121
- return true;
122
- }
123
- }
124
- return false;
125
- }
126
30
 
127
31
  /**
128
32
  * 确保文件夹存在
@@ -191,9 +95,10 @@ function findAppRootPath(aPath) {
191
95
 
192
96
  function toPair(object) {
193
97
  return Object.keys(object).map((key) => {
98
+ let value = object[key] ? object[key].toString() : "";
194
99
  return {
195
100
  name: key,
196
- value: object[key].toString(),
101
+ value,
197
102
  };
198
103
  });
199
104
  }
@@ -203,43 +108,14 @@ function getMetaInfo(composeFile) {
203
108
  return doc[META_MARK];
204
109
  }
205
110
 
206
- async function createTemplateFile(templateFile, outputFile, env) {
111
+ async function envTemplateFile(templateFile, env) {
207
112
  const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
208
- // const meta = template[META_MARK];
209
- // if (
210
- // meta &&
211
- // Array.isArray(meta["permissions"]) &&
212
- // meta["permissions"].includes("lzcapis")
213
- // ) {
214
- // template[META_MARK]["ingress"].push({
215
- // service: "lazycat-apis-sidecar",
216
- // port: 8888,
217
- // subdomain: "${APP_NAME}",
218
- // path: "/lzcapis/",
219
- // auth: "oidc",
220
- // authcallback: "/lzcapis/oidc-callback",
221
- // });
222
- // template["services"]["lazycat-apis-sidecar"] = {
223
- // image: "registry.lazycat.cloud/lazycat-apis-sidecar",
224
- // // volumes_from: ["${APP_NAME}:rw"],
225
- // volumes: ["lzcapis-lzcapp:/lzcapp"],
226
- // command: [
227
- // "--client-id=${LAZYCAT_AUTH_OIDC_CLIENT_ID}",
228
- // "--client-secret=${LAZYCAT_AUTH_OIDC_CLIENT_SECRET}",
229
- // "--client-url=https://${LAZYCAT_APP_ORIGIN}/lzcapis/",
230
- // "--issuer=${LAZYCAT_AUTH_OIDC_ISSUER_URL}",
231
- // "--prefix=lzcapis",
232
- // "--fs-root=/lzcapp/documents",
233
- // ],
234
- // };
235
- // }
236
- //
237
113
  const options = {
238
114
  envs: toPair(env),
239
115
  syntax: "default",
240
116
  protect: false,
241
117
  };
242
- const output = await envsubstr(
118
+ return await envsubstr(
243
119
  yaml.dump(template, {
244
120
  styles: {
245
121
  "!!null": "empty", // dump null as ""
@@ -247,7 +123,23 @@ async function createTemplateFile(templateFile, outputFile, env) {
247
123
  }),
248
124
  { options }
249
125
  );
126
+ }
250
127
 
128
+ async function createTemplateFile(templateFile, outputFile, env) {
129
+ let output = await envTemplateFile(templateFile, env);
130
+ fs.writeFileSync(outputFile, output);
131
+ }
132
+
133
+ async function createTemplateFileCommon(templateFile, outputFile, env) {
134
+ const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
135
+ const options = {
136
+ envs: toPair(env),
137
+ syntax: "default",
138
+ protect: false,
139
+ };
140
+ const output = await envsubstr(fs.readFileSync(templateFile, "utf-8"), {
141
+ options,
142
+ });
251
143
  fs.writeFileSync(outputFile, output);
252
144
  }
253
145
 
@@ -262,7 +154,7 @@ async function copyDotAppDir(from, to, opts = {}) {
262
154
  if (fs.existsSync(to)) {
263
155
  fs.rmSync(to, { recursive: true });
264
156
  }
265
- const _files = await glob(["*"].concat(include), {
157
+ const _files = await glob(["**"].concat(include), {
266
158
  cwd: from,
267
159
  dot: true,
268
160
  ignore: ignore,
@@ -289,6 +181,22 @@ async function copyDotAppDir(from, to, opts = {}) {
289
181
  }
290
182
  }
291
183
 
184
+ function mergeYamlInMemory(args) {
185
+ if (args.length == 0) {
186
+ return {};
187
+ } else if (args.length == 1) {
188
+ return args[0];
189
+ }
190
+ return args.reduce((prev, curr) => {
191
+ let result = mergeWith(prev, curr, (objValue, srcValue) => {
192
+ if (isArray(objValue)) {
193
+ return objValue.concat(srcValue);
194
+ }
195
+ });
196
+ return result;
197
+ }, {});
198
+ }
199
+
292
200
  // override yaml, notice this will change target file
293
201
  function mergeYaml(target, source) {
294
202
  const targetContent = yaml.load(fs.readFileSync(target, "utf8"));
@@ -302,15 +210,7 @@ function mergeYaml(target, source) {
302
210
  }
303
211
  }
304
212
  );
305
-
306
- fs.writeFileSync(
307
- target,
308
- yaml.dump(merged, {
309
- styles: {
310
- "!!null": "empty", // dump null as ""
311
- },
312
- })
313
- );
213
+ dumpToYaml(merged, target);
314
214
  }
315
215
 
316
216
  function archiveFolder(appDir, format = "zip") {
@@ -393,6 +293,14 @@ function isDirSync(path) {
393
293
  return stat.isDirectory();
394
294
  }
395
295
 
296
+ function isDirExist(path) {
297
+ try {
298
+ return isDirSync(path);
299
+ } catch {
300
+ return false;
301
+ }
302
+ }
303
+
396
304
  function isFileExist(path) {
397
305
  try {
398
306
  fs.accessSync(
@@ -416,6 +324,18 @@ function parse2CorrectName(name) {
416
324
  return name.replaceAll(" ", "-").toLowerCase();
417
325
  }
418
326
 
327
+ async function sleep(ms) {
328
+ return new Promise((resolve) => {
329
+ setTimeout(resolve, ms);
330
+ });
331
+ }
332
+
333
+ async function md5String(str) {
334
+ const hash = createHash("md5");
335
+ hash.update(str);
336
+ return hash.digest("hex");
337
+ }
338
+
419
339
  export {
420
340
  ensureDir,
421
341
  copyDotAppDir,
@@ -424,6 +344,7 @@ export {
424
344
  findAppRootPath,
425
345
  archiveFolder,
426
346
  mergeYaml,
347
+ mergeYamlInMemory,
427
348
  loadFromYaml,
428
349
  dumpToYaml,
429
350
  importDefault,
@@ -434,13 +355,14 @@ export {
434
355
  toPair,
435
356
  contextDirname,
436
357
  isDirSync,
358
+ isDirExist,
437
359
  GitIgnore,
438
360
  isFileExist,
439
361
  urlHostname,
440
- InstallSDK,
441
- findAppIsInstalled,
442
- getInstalledApps,
443
- checkSDKInstallStatus,
362
+ envTemplateFile,
444
363
  createTemplateFile,
445
364
  parse2CorrectName,
365
+ sleep,
366
+ md5String,
367
+ createTemplateFileCommon
446
368
  };
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@lazycatcloud/lzc-cli",
3
- "version": "1.1.5",
3
+ "version": "1.1.8",
4
4
  "description": "lazycat cloud developer kit",
5
5
  "scripts": {
6
- "test": "mocha",
7
- "publish": "npm publish --access public"
6
+ "test": "mocha"
8
7
  },
9
8
  "mocha": {
10
9
  "recursive": true,
@@ -48,6 +47,7 @@
48
47
  "lodash.merge": "^4.6.2",
49
48
  "lodash.mergewith": "^4.6.2",
50
49
  "log-update": "^5.0.0",
50
+ "loglevel": "^1.8.0",
51
51
  "minimist": "^1.2.5",
52
52
  "node-fetch": "^2.6.6",
53
53
  "node-stream-zip": "^1.15.0",
@@ -55,6 +55,7 @@
55
55
  "semver": "^7.3.5",
56
56
  "ssh2": "^1.5.0",
57
57
  "ssh2-promise": "^1.0.2",
58
+ "tar": "^6.1.11",
58
59
  "yargs": "^17.5.1"
59
60
  },
60
61
  "devDependencies": {
@@ -62,5 +63,9 @@
62
63
  "chai": "^4.3.6",
63
64
  "mocha": "^9.2.2",
64
65
  "prettier": "^2.5.0"
66
+ },
67
+ "publishConfig": {
68
+ "registry": "https://registry.npmjs.org",
69
+ "access": "public"
65
70
  }
66
71
  }
package/scripts/cli.js CHANGED
@@ -2,25 +2,82 @@
2
2
  import process from "process";
3
3
  import path from "path";
4
4
  import fs from "fs";
5
- import { contextDirname, importDefault } from "../lib/utils.js";
5
+ import logger from "loglevel";
6
6
  import yargs from "yargs";
7
7
  import { hideBin } from "yargs/helpers";
8
+ import chalk from "chalk";
8
9
 
10
+ import { contextDirname, importDefault } from "../lib/utils.js";
9
11
  import Env from "../lib/env.js";
10
12
  import { boxCommand } from "../lib/box/index.js";
13
+ import { lpkAppCommand, lpkProjectCommand } from "../lib/app/index.js";
11
14
  const pkgInfo = JSON.parse(
12
15
  fs.readFileSync(path.join(contextDirname(import.meta.url), "../package.json"))
13
16
  );
14
17
 
18
+ // logger level middleware
19
+ const logLevelOriginalFactory = logger.methodFactory;
20
+ logger.methodFactory = function (methodName, logLevel, loggerName) {
21
+ let rawMethod = logLevelOriginalFactory(methodName, logLevel, loggerName);
22
+ return function (...args) {
23
+ let color = (msg) => chalk.gray;
24
+ switch (methodName) {
25
+ case "trace":
26
+ color = chalk.dim.cyan;
27
+ break;
28
+ case "debug":
29
+ color = chalk.blue;
30
+ break;
31
+ case "info":
32
+ color = chalk.green;
33
+ break;
34
+ case "warn":
35
+ color = chalk.magenta;
36
+ break;
37
+ case "error":
38
+ color = chalk.bold.red;
39
+ break;
40
+ }
41
+ rawMethod(
42
+ `[${methodName}] ` +
43
+ args
44
+ .map((a) => {
45
+ let res = a;
46
+ if (typeof a == "object") {
47
+ res = JSON.stringify(a, undefined, 4);
48
+ }
49
+ return color(res);
50
+ })
51
+ .join(" ")
52
+ );
53
+ };
54
+ };
55
+ logger.setDefaultLevel("info");
56
+ function setLoggerLevel({ log }) {
57
+ logger.setLevel(log, false);
58
+ }
59
+
15
60
  const program = yargs(hideBin(process.argv))
16
61
  .scriptName("lzc-cli")
17
62
  .usage("<command> [options]")
18
63
  .version(`lzc-cli ${pkgInfo.version}`)
19
- .completion("completion", "生成bash/zsh补全脚本");
64
+ .option("log", {
65
+ type: "string",
66
+ default: "info",
67
+ describe: "log level 'trace', 'debug', 'info', 'warn', 'error'",
68
+ })
69
+ .option("help", {
70
+ alias: "h",
71
+ type: "boolean",
72
+ default: false,
73
+ })
74
+ .completion("completion", false);
20
75
 
76
+ // Set desc to false to create a hidden command. Hidden commands don’t show up
77
+ // in the help output and aren’t available for completion.
21
78
  program.command({
22
79
  command: "create <name>",
23
- desc: "创建懒猫云应用",
80
+ desc: false,
24
81
  aliases: ["c"],
25
82
  handler: async ({ name }) => {
26
83
  let create = await importDefault("../cmds/create.js");
@@ -30,7 +87,7 @@ program.command({
30
87
 
31
88
  program.command({
32
89
  command: "init",
33
- desc: "初始化懒猫云应用配置",
90
+ desc: false,
34
91
  handler: async () => {
35
92
  const { Init } = await import("../cmds/init.js");
36
93
  new Init({ cwd: process.cwd() }).create();
@@ -39,7 +96,7 @@ program.command({
39
96
 
40
97
  program.command({
41
98
  command: "uninstall",
42
- desc: "卸载应用",
99
+ desc: false,
43
100
  handler: async () => {
44
101
  const { uninstall } = await importDefault("../cmds/app.js");
45
102
  await uninstall();
@@ -48,7 +105,7 @@ program.command({
48
105
 
49
106
  program.command({
50
107
  command: "publish",
51
- desc: "发布应用",
108
+ desc: false,
52
109
  handler: async () => {
53
110
  // 第一步 打包镜像
54
111
  const Publisher = await importDefault("../cmds/publish.js");
@@ -64,7 +121,7 @@ program.command({
64
121
 
65
122
  program.command({
66
123
  command: "deploy",
67
- desc: "部署应用至设备",
124
+ desc: false,
68
125
  handler: async () => {
69
126
  const { deploy } = await importDefault("../cmds/app.js");
70
127
  await deploy();
@@ -73,7 +130,7 @@ program.command({
73
130
 
74
131
  program.command({
75
132
  command: "build [context]",
76
- desc: "构建",
133
+ desc: false,
77
134
  builder: (args) => {
78
135
  args.option("f", {
79
136
  alias: "file",
@@ -116,7 +173,7 @@ let devSubCommands = [
116
173
  ];
117
174
  program.command({
118
175
  command: "dev",
119
- desc: "dev [forward [addr] | shell]",
176
+ desc: false,
120
177
  builder: (args) => {
121
178
  args.command(devSubCommands);
122
179
  },
@@ -124,7 +181,7 @@ program.command({
124
181
 
125
182
  program.command({
126
183
  command: "log [project]",
127
- desc: "查看应用日志",
184
+ desc: false,
128
185
  builder: (args) => {
129
186
  args.option("u", {
130
187
  alias: "user",
@@ -141,7 +198,7 @@ program.command({
141
198
 
142
199
  program.command({
143
200
  command: "config [key] [value]",
144
- desc: "应用配置项",
201
+ desc: false,
145
202
  builder: (args) => {
146
203
  args.implies("key", "value");
147
204
  args.option("g", {
@@ -158,5 +215,27 @@ program.command({
158
215
  });
159
216
 
160
217
  boxCommand(program);
218
+ lpkAppCommand(program);
219
+ lpkProjectCommand(program);
220
+
221
+ const parser = program
222
+ .strict()
223
+ .showHelpOnFail(false, "使用 lzc-cli help 查看更多帮助")
224
+ .middleware([setLoggerLevel])
225
+ .parse();
161
226
 
162
- program.showHelpOnFail(false, "使用 lzc-cli help 查看更多帮助").parse();
227
+ // 当没有参数的时候,默认显示帮助。
228
+ (async () => {
229
+ const argv = await parser;
230
+ if (argv._.length == 1) {
231
+ switch (argv._[0]) {
232
+ case "box":
233
+ case "app":
234
+ case "project":
235
+ program.showHelp();
236
+ return;
237
+ }
238
+ } else if (argv._.length == 0) {
239
+ program.showHelp();
240
+ }
241
+ })();
@@ -1,8 +1,10 @@
1
- FROM node:16-alpine3.12
1
+ FROM registry.lazycat.cloud/lzc/lzcapp:0.1
2
2
 
3
3
  RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4
4
 
5
- RUN apk add --no-cache openssh rsync \
5
+ COPY --from=golang:1.18-alpine /usr/local/go/ /usr/local/go/
6
+
7
+ RUN apk add --no-cache openssh rsync musl-dev curl openssl curl nodejs npm \
6
8
  && echo "root:root" | chpasswd
7
9
 
8
10
  EXPOSE 22
@@ -13,4 +15,4 @@ COPY entrypoint.sh /entrypoint.sh
13
15
 
14
16
  RUN chmod +x /entrypoint.sh
15
17
 
16
- ENTRYPOINT ["/entrypoint.sh"]
18
+ ENTRYPOINT ./entrypoint.sh
@@ -1,20 +1,10 @@
1
1
  services:
2
2
  ${APP_ID}:
3
- image: nginx:1.21.4-alpine
4
- volumes:
5
- - ./nginx.conf.template:/etc/nginx/templates/nginx.conf.template
6
- - ./50x.html:/etc/nginx/50x.html
7
- environment:
8
- - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx
9
- - APP_DEBUG_PORT=${HTTP_SERVICE_PORT}
10
- - APP_DEBUG_SHELL=debug-shell.${APP_ID}.lzcapp
11
- command: [nginx, '-g', 'daemon off;']
12
- depends_on:
13
- - debug-shell
14
- debug-shell:
15
3
  image: ${APP_IMAGE_NAME}
16
4
  pull_policy: build
17
5
  build: .
6
+ environment:
7
+ - HTTP_SERVICE_PORT=${HTTP_SERVICE_PORT}
18
8
  volumes:
19
9
  - ./debug/ssh:/root/.ssh
20
10
  - project-data:/root/
@@ -7,4 +7,6 @@ ssh-keygen -A
7
7
  rsync --daemon
8
8
 
9
9
  # do not detach (-D), log to stderr (-e), passthrough other arguments
10
- exec /usr/sbin/sshd -D -e "$@"
10
+ /usr/sbin/sshd -e "$@"
11
+
12
+ exec /usr/bin/lzcinit -listen :$HTTP_SERVICE_PORT -up /="http://127.0.0.1:3000"
@@ -0,0 +1,8 @@
1
+ FROM alpine:3.16
2
+
3
+ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4
+
5
+ RUN apk add --no-cache bash ${dependencies} \
6
+ && echo "root:root" | chpasswd
7
+
8
+ CMD ["sleep", "infinity"]
@@ -0,0 +1,18 @@
1
+ FROM alpine
2
+
3
+ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
4
+
5
+ COPY --from=golang:1.18-alpine /usr/local/go/ /usr/local/go/
6
+
7
+ RUN apk add --no-cache openssh musl-dev curl openssl curl nodejs npm sshfs rsync \
8
+ && echo "root:root" | chpasswd
9
+
10
+ EXPOSE 22
11
+
12
+ COPY sshd_config /etc/ssh/sshd_config
13
+
14
+ COPY entrypoint.sh /entrypoint.sh
15
+
16
+ RUN chmod +x /entrypoint.sh
17
+
18
+ CMD ["./entrypoint.sh"]
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/sh
2
+
3
+ VERSION=0.0.4
4
+ docker build -f Dockerfile . -t registry.lazycat.cloud/lzc-cli/devshell:$VERSION
5
+ docker push registry.lazycat.cloud/lzc-cli/devshell:$VERSION
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+ set -ex
3
+
4
+ # generate host keys if not present
5
+ ssh-keygen -A
6
+
7
+ # do not detach (-D), log to stderr (-e), passthrough other arguments
8
+ exec /usr/sbin/sshd -D -e "$@"