@lazycatcloud/lzc-cli 1.2.2 → 1.2.4
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.
- package/lib/app/lpk_build.js +6 -25
- package/lib/app/lpk_debug_bridge.js +17 -0
- package/lib/app/lpk_devshell.js +45 -2
- package/lib/app/lpk_devshell_docker.js +55 -0
- package/lib/box/index.js +40 -3
- package/lib/shellapi.js +28 -10
- package/lib/utils.js +43 -0
- package/package.json +3 -1
- package/template/_lpk/init_debug_bridge.sh +15 -8
- package/template/_lpk/vue.lzc-build.yml.in +16 -0
- package/template/golang/lzc-build.yml +15 -0
- package/template/ionic_vue3/lzc-build.yml +16 -0
- package/template/lite/lzc-build.yml +28 -0
package/lib/app/lpk_build.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import tar from "tar";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import fs from "node:fs";
|
|
4
3
|
import logger from "loglevel";
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
dumpToYaml,
|
|
10
9
|
envTemplateFile,
|
|
11
10
|
isValidPackageName,
|
|
11
|
+
tarContentDir,
|
|
12
12
|
} from "../utils.js";
|
|
13
13
|
import { spawnSync } from "child_process";
|
|
14
14
|
import { LpkManifest } from "./lpk_create.js";
|
|
@@ -17,29 +17,6 @@ import yaml from "js-yaml";
|
|
|
17
17
|
|
|
18
18
|
const isMacos = process.platform == "darwin";
|
|
19
19
|
|
|
20
|
-
async function tarContentDir(from, to, cwd = "./") {
|
|
21
|
-
const dest = fs.createWriteStream(to);
|
|
22
|
-
tar
|
|
23
|
-
.c(
|
|
24
|
-
{
|
|
25
|
-
cwd: cwd,
|
|
26
|
-
filter: (filePath, stat) => {
|
|
27
|
-
logger.debug(`tar gz ${filePath}`);
|
|
28
|
-
return true;
|
|
29
|
-
},
|
|
30
|
-
sync: true,
|
|
31
|
-
portable: {
|
|
32
|
-
uid: 0,
|
|
33
|
-
gid: 0,
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
[from]
|
|
37
|
-
)
|
|
38
|
-
.pipe(dest);
|
|
39
|
-
logger.debug(`pack: ${dest.path}`);
|
|
40
|
-
return dest.path;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
20
|
async function archiveFolderTo(appDir, out, format = "zip") {
|
|
44
21
|
return new Promise(async (resolve, reject) => {
|
|
45
22
|
if (!fs.existsSync(appDir)) {
|
|
@@ -251,7 +228,11 @@ export class LpkBuild {
|
|
|
251
228
|
return _prev;
|
|
252
229
|
}, contentdir);
|
|
253
230
|
}
|
|
254
|
-
tarContentDir(
|
|
231
|
+
await tarContentDir(
|
|
232
|
+
["./"],
|
|
233
|
+
path.join(tempDir, "content.tar"),
|
|
234
|
+
contentdir
|
|
235
|
+
);
|
|
255
236
|
|
|
256
237
|
// 如果是临时的 contentdir, 目录在打包完成后删除
|
|
257
238
|
if (!this.options["contentdir"]) {
|
|
@@ -108,4 +108,21 @@ export class DebugBridge {
|
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
+
|
|
112
|
+
async buildImage(label, contextTar) {
|
|
113
|
+
const tag = `dev.${this.boxname}.heiyu.space:5000/debug.bridge/${label}`;
|
|
114
|
+
const stream = fs.createReadStream(contextTar);
|
|
115
|
+
const ssh = spawn(this.sshCmd, [`build --tag ${tag}`], {
|
|
116
|
+
shell: true,
|
|
117
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
118
|
+
});
|
|
119
|
+
stream.pipe(ssh.stdin);
|
|
120
|
+
return new Promise((resolve, reject) => {
|
|
121
|
+
ssh.on("close", (code) => {
|
|
122
|
+
code == 0 ? resolve(tag) : reject("在盒子中构建 image 失败");
|
|
123
|
+
});
|
|
124
|
+
}).finally(() => {
|
|
125
|
+
fs.rmSync(contextTar);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
111
128
|
}
|
package/lib/app/lpk_devshell.js
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
loadFromYaml,
|
|
17
17
|
FileLocker,
|
|
18
18
|
isUserApp,
|
|
19
|
+
createTemplateFileCommon,
|
|
19
20
|
} from "../utils.js";
|
|
20
21
|
import os from "node:os";
|
|
21
22
|
import commandExists from "command-exists";
|
|
@@ -23,6 +24,7 @@ import chokidar from "chokidar";
|
|
|
23
24
|
import _ from "lodash";
|
|
24
25
|
import { DebugBridge } from "./lpk_debug_bridge.js";
|
|
25
26
|
import shellApi from "../shellapi.js";
|
|
27
|
+
import { collectContextFromDockerFile } from "./lpk_devshell_docker.js";
|
|
26
28
|
|
|
27
29
|
// 判断是否需要重新构建
|
|
28
30
|
// - 先判断 lzc-build.yml 是否发生改变
|
|
@@ -264,7 +266,36 @@ export class AppDevShell {
|
|
|
264
266
|
return manifest;
|
|
265
267
|
}
|
|
266
268
|
|
|
267
|
-
|
|
269
|
+
const depsStr = deps.sort().join(" ");
|
|
270
|
+
logger.debug("开始创建 Dockerfile 文件");
|
|
271
|
+
|
|
272
|
+
const tempDir = fs.mkdtempSync(".lzc-cli-build-dependencies");
|
|
273
|
+
try {
|
|
274
|
+
const dockerfilePath = path.join(
|
|
275
|
+
contextDirname(import.meta.url),
|
|
276
|
+
"../../template/_lpk/Dockerfile.in"
|
|
277
|
+
);
|
|
278
|
+
await createTemplateFileCommon(
|
|
279
|
+
dockerfilePath,
|
|
280
|
+
path.join(tempDir, "Dockerfile"),
|
|
281
|
+
{ dependencies: depsStr }
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const label = `${await md5String(depsStr)}:latest`;
|
|
285
|
+
logger.debug(`开始在盒子中构建 ${label} 镜像 from ${tempDir}`);
|
|
286
|
+
|
|
287
|
+
const contextTar = await collectContextFromDockerFile(
|
|
288
|
+
tempDir,
|
|
289
|
+
path.resolve(tempDir, "Dockerfile")
|
|
290
|
+
);
|
|
291
|
+
const bridge = new DebugBridge();
|
|
292
|
+
const tag = await bridge.buildImage(label, contextTar);
|
|
293
|
+
delete manifest["application"]["devshell"];
|
|
294
|
+
manifest["application"]["image"] = tag;
|
|
295
|
+
} finally {
|
|
296
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
297
|
+
}
|
|
298
|
+
return manifest;
|
|
268
299
|
});
|
|
269
300
|
|
|
270
301
|
// 如果 services 中有 devshell 的字段,需要检测是否需要提前构建
|
|
@@ -279,7 +310,19 @@ export class AppDevShell {
|
|
|
279
310
|
return manifest;
|
|
280
311
|
}
|
|
281
312
|
|
|
282
|
-
|
|
313
|
+
const label = `${manifest["package"]}-devshell:${manifest["version"]}`;
|
|
314
|
+
logger.debug(`开始在盒子中构建 ${label} 镜像`);
|
|
315
|
+
|
|
316
|
+
const contextTar = await collectContextFromDockerFile(
|
|
317
|
+
process.cwd(),
|
|
318
|
+
path.resolve(process.cwd(), config["build"], "Dockerfile")
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
const bridge = new DebugBridge();
|
|
322
|
+
const tag = await bridge.buildImage(label, contextTar);
|
|
323
|
+
delete manifest["application"]["devshell"];
|
|
324
|
+
manifest["application"]["image"] = tag;
|
|
325
|
+
return manifest;
|
|
283
326
|
});
|
|
284
327
|
|
|
285
328
|
// 如果 devshell 中指定了 image 字段将使用 image 字段
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { DockerfileParser } from "dockerfile-ast";
|
|
4
|
+
import glob from "fast-glob";
|
|
5
|
+
import ignore from "@balena/dockerignore";
|
|
6
|
+
import { tarContentDir } from "../utils.js";
|
|
7
|
+
|
|
8
|
+
export async function collectContextFromDockerFile(contextDir, dockerfilePath) {
|
|
9
|
+
if (!fs.existsSync(dockerfilePath)) {
|
|
10
|
+
throw "未发现 Dockerfile";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let src = [path.relative(contextDir, dockerfilePath)];
|
|
14
|
+
|
|
15
|
+
// 通过 COPY 和 ADD 获取所有context中的文件
|
|
16
|
+
const ast = DockerfileParser.parse(fs.readFileSync(dockerfilePath, "utf8"));
|
|
17
|
+
for (let a of ast.getInstructions()) {
|
|
18
|
+
if (["COPY", "ADD"].includes(a.getInstruction())) {
|
|
19
|
+
const from = a.getArguments()[0].getValue().replace(/^\//, "");
|
|
20
|
+
const fromFullPath = path.resolve(contextDir, from);
|
|
21
|
+
|
|
22
|
+
if (fs.existsSync(fromFullPath)) {
|
|
23
|
+
const stat = fs.statSync(fromFullPath);
|
|
24
|
+
if (stat.isDirectory()) {
|
|
25
|
+
let files = await glob(path.join(from, "**"), {
|
|
26
|
+
cwd: contextDir,
|
|
27
|
+
});
|
|
28
|
+
src = src.concat(files);
|
|
29
|
+
} else if (stat.isFile()) {
|
|
30
|
+
src.push(from);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
// try use glob
|
|
34
|
+
let files = await glob(from, {
|
|
35
|
+
cwd: contextDir,
|
|
36
|
+
});
|
|
37
|
+
src = src.concat(files);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// filter by dockerignore
|
|
42
|
+
const dockerIgnoreFile = path.join(contextDir, ".dockerignore");
|
|
43
|
+
if (fs.existsSync(dockerIgnoreFile)) {
|
|
44
|
+
let ig = ignore();
|
|
45
|
+
let data = fs.readFileSync(dockerIgnoreFile, "utf8");
|
|
46
|
+
ig.add(data.split("\n"));
|
|
47
|
+
src = ig.filter(src);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return await tarContentDir(
|
|
51
|
+
src,
|
|
52
|
+
path.join(contextDir, "lzc-build-image-context.tar"),
|
|
53
|
+
process.cwd()
|
|
54
|
+
);
|
|
55
|
+
}
|
package/lib/box/index.js
CHANGED
|
@@ -1,10 +1,47 @@
|
|
|
1
|
+
import shellapi from "../shellapi.js";
|
|
2
|
+
|
|
1
3
|
export function boxCommand(box) {
|
|
2
4
|
let subCommands = [
|
|
3
5
|
{
|
|
4
|
-
command: "switch <
|
|
6
|
+
command: "switch <boxname>",
|
|
5
7
|
desc: "设置默认的盒子",
|
|
6
|
-
handler: async () => {
|
|
7
|
-
|
|
8
|
+
handler: async ({ boxname }) => {
|
|
9
|
+
await shellapi.init();
|
|
10
|
+
await shellapi.setDefaultBox(boxname);
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
command: "list",
|
|
15
|
+
desc: "查看盒子列表",
|
|
16
|
+
builder: (args) => {
|
|
17
|
+
args.option("v", {
|
|
18
|
+
alias: "verbose",
|
|
19
|
+
describe: "查看详细输出",
|
|
20
|
+
type: "boolean",
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
handler: async ({ verbose }) => {
|
|
24
|
+
await shellapi.init();
|
|
25
|
+
const boxes = await shellapi.boxList();
|
|
26
|
+
if (boxes.length === 0) {
|
|
27
|
+
console.log("没有找到任何盒子,赶紧添加一个吧!");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (verbose) {
|
|
31
|
+
console.log(JSON.stringify(boxes, undefined, "\t"));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const list = boxes.map((b) => {
|
|
36
|
+
return {
|
|
37
|
+
名称: b.box_name,
|
|
38
|
+
状态: b.status,
|
|
39
|
+
登录用户: b.login_user,
|
|
40
|
+
是否管理员: b.is_admin_login ? "✔" : "✖",
|
|
41
|
+
是否默认盒子: b.is_default_box ? "✔" : "✖",
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
console.table(list);
|
|
8
45
|
},
|
|
9
46
|
},
|
|
10
47
|
];
|
package/lib/shellapi.js
CHANGED
|
@@ -71,25 +71,43 @@ class ShellApi {
|
|
|
71
71
|
return grpc.loadPackageDefinition(coreDefinition).space.heiyu.hportal.shell;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
async
|
|
74
|
+
async boxList() {
|
|
75
75
|
return new Promise((resolve, reject) => {
|
|
76
76
|
this.client.queryBoxList({}, this.metadata, function (err, response) {
|
|
77
77
|
if (err) {
|
|
78
78
|
reject(err);
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
if (box.is_default_box) {
|
|
83
|
-
resolve({ uid: box.login_user, boxname: box.box_name });
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
reject(
|
|
88
|
-
"没有默认盒子信息, 请先使用 lzc-cli box switch 设置默认的盒子信息"
|
|
89
|
-
);
|
|
81
|
+
resolve(response.boxes);
|
|
90
82
|
});
|
|
91
83
|
});
|
|
92
84
|
}
|
|
85
|
+
|
|
86
|
+
async initBoxInfo() {
|
|
87
|
+
const boxes = await this.boxList();
|
|
88
|
+
const box = boxes.find((b) => b.is_default_box);
|
|
89
|
+
if (box) {
|
|
90
|
+
return { uid: box.login_user, boxname: box.box_name };
|
|
91
|
+
}
|
|
92
|
+
throw "没有默认盒子信息, 请先使用 lzc-cli box switch 设置默认的盒子信息";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async setDefaultBox(boxname) {
|
|
96
|
+
const boxes = await this.boxList();
|
|
97
|
+
const box = boxes.find((b) => b.box_name === boxname);
|
|
98
|
+
if (!box) {
|
|
99
|
+
throw `${boxname} 盒子不存在`;
|
|
100
|
+
}
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
this.client.modifyBoxConfig(
|
|
103
|
+
{ id: box.id, name: box.box_name, set_as_default_box: true },
|
|
104
|
+
this.metadata,
|
|
105
|
+
function (err) {
|
|
106
|
+
err ? reject(err) : resolve();
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
93
111
|
}
|
|
94
112
|
|
|
95
113
|
export default new ShellApi();
|
package/lib/utils.js
CHANGED
|
@@ -14,6 +14,7 @@ import zlib from "node:zlib";
|
|
|
14
14
|
import process from "node:process";
|
|
15
15
|
import { spawnSync } from "node:child_process";
|
|
16
16
|
import logger from "loglevel";
|
|
17
|
+
import tar from "tar";
|
|
17
18
|
|
|
18
19
|
export const envsubstr = async (templateContents, args) => {
|
|
19
20
|
const parse = await importDefault("envsub/js/envsub-parser.js");
|
|
@@ -37,6 +38,18 @@ export function ensureDir(filePath) {
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
export async function createTemplateFileCommon(templateFile, outputFile, env) {
|
|
42
|
+
const options = {
|
|
43
|
+
envs: toPair(env),
|
|
44
|
+
syntax: "default",
|
|
45
|
+
protect: false,
|
|
46
|
+
};
|
|
47
|
+
const output = await envsubstr(fs.readFileSync(templateFile, "utf-8"), {
|
|
48
|
+
options,
|
|
49
|
+
});
|
|
50
|
+
fs.writeFileSync(outputFile, output);
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
export function loadFromYaml(file) {
|
|
41
54
|
return yaml.load(fs.readFileSync(file, "utf8"));
|
|
42
55
|
}
|
|
@@ -298,3 +311,33 @@ export function isValidPackageName(packageName) {
|
|
|
298
311
|
export function isUserApp(manifest) {
|
|
299
312
|
return !!manifest["application"]["user_app"];
|
|
300
313
|
}
|
|
314
|
+
|
|
315
|
+
export async function tarContentDir(from, to, cwd = "./") {
|
|
316
|
+
return new Promise((resolve, reject) => {
|
|
317
|
+
const dest = fs.createWriteStream(to);
|
|
318
|
+
tar
|
|
319
|
+
.c(
|
|
320
|
+
{
|
|
321
|
+
cwd: cwd,
|
|
322
|
+
filter: (filePath) => {
|
|
323
|
+
logger.debug(`tar gz ${filePath}`);
|
|
324
|
+
return true;
|
|
325
|
+
},
|
|
326
|
+
sync: true,
|
|
327
|
+
portable: {
|
|
328
|
+
uid: 0,
|
|
329
|
+
gid: 0,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
from
|
|
333
|
+
)
|
|
334
|
+
.pipe(dest)
|
|
335
|
+
.on("close", () => {
|
|
336
|
+
logger.debug(`pack: ${dest.path}`);
|
|
337
|
+
resolve(dest.path);
|
|
338
|
+
})
|
|
339
|
+
.on("error", (err) => {
|
|
340
|
+
reject(err);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "tap",
|
|
@@ -27,12 +27,14 @@
|
|
|
27
27
|
"author": "zac zeng",
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@balena/dockerignore": "^1.0.2",
|
|
30
31
|
"@grpc/grpc-js": "^1.8.18",
|
|
31
32
|
"@grpc/proto-loader": "^0.7.8",
|
|
32
33
|
"archiver": "^5.3.0",
|
|
33
34
|
"chalk": "^4.1.2",
|
|
34
35
|
"chokidar": "^3.5.3",
|
|
35
36
|
"command-exists": "^1.2.9",
|
|
37
|
+
"dockerfile-ast": "^0.5.0",
|
|
36
38
|
"envsub": "^4.0.7",
|
|
37
39
|
"fast-glob": "^3.2.7",
|
|
38
40
|
"form-data": "^4.0.0",
|
|
@@ -7,18 +7,25 @@ BUSYBOX=/lzcapp/pkg/content/devshell/busybox
|
|
|
7
7
|
mkdir -p /root/.ssh
|
|
8
8
|
mkdir -p /etc/debug.bridge
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
if ! [ -f /usr/bin/dropbearmulti ]; then
|
|
11
|
+
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/dropbearmulti -O /usr/bin/dropbearmulti
|
|
12
|
+
chmod +x /usr/bin/dropbearmulti
|
|
13
|
+
fi
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
if ! [ -f /usr/bin/rsync ]; then
|
|
16
|
+
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/rsync -O /usr/bin/rsync
|
|
17
|
+
chmod +x /usr/bin/rsync
|
|
18
|
+
fi
|
|
15
19
|
|
|
16
20
|
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/resources/authorized_keys -O /root/.ssh/authorized_keys
|
|
17
21
|
chmod 0644 /root/.ssh/authorized_keys
|
|
18
22
|
|
|
19
23
|
${BUSYBOX} wget ${DEBUG_BRIDGE_LZCAPP}/bannerfile -O /etc/debug.bridge/bannerfile
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
if ${BUSYBOX} netstat -tln | grep ':22222' >/dev/null; then
|
|
26
|
+
echo "端口22222正在监听"
|
|
27
|
+
${BUSYBOX} sleep infinity
|
|
28
|
+
else
|
|
29
|
+
mkdir -p /etc/dropbear
|
|
30
|
+
exec dropbearmulti dropbear -R -F -E -B -p 22222
|
|
31
|
+
fi
|
|
@@ -32,9 +32,25 @@ icon: ./lazycat.png
|
|
|
32
32
|
# - /=http://127.0.0.1:3000
|
|
33
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
34
|
|
|
35
|
+
# devshell 指定构建Dockerfile
|
|
36
|
+
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
+
# devshell:
|
|
38
|
+
# routes:
|
|
39
|
+
# - /=http://127.0.0.1:3000
|
|
40
|
+
# image: ${package}-devshell:${version}
|
|
41
|
+
# pull_policy: build
|
|
42
|
+
# build: .
|
|
43
|
+
|
|
44
|
+
# dvshell 指定开发依赖的情况
|
|
45
|
+
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
+
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
35
47
|
devshell:
|
|
36
48
|
routes:
|
|
37
49
|
- /=http://127.0.0.1:3000
|
|
50
|
+
dependencies:
|
|
51
|
+
- nodejs
|
|
52
|
+
- vim
|
|
53
|
+
- npm
|
|
38
54
|
# setupscript 每次进入到app container后都会执行的配置脚本
|
|
39
55
|
# - 可以为脚本的路径地址
|
|
40
56
|
# - 如果构建命令简单,也可以直接写 sh 的命令
|
|
@@ -32,9 +32,24 @@ icon: ./lazycat.png
|
|
|
32
32
|
# - /=http://127.0.0.1:3000
|
|
33
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
34
|
|
|
35
|
+
# devshell 指定构建Dockerfile
|
|
36
|
+
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
+
# devshell:
|
|
38
|
+
# routes:
|
|
39
|
+
# - /=http://127.0.0.1:3000
|
|
40
|
+
# image: ${package}-devshell:${version}
|
|
41
|
+
# pull_policy: build
|
|
42
|
+
# build: .
|
|
43
|
+
|
|
44
|
+
# dvshell 指定开发依赖的情况
|
|
45
|
+
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
+
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
35
47
|
devshell:
|
|
36
48
|
routes:
|
|
37
49
|
- /=http://127.0.0.1:3000
|
|
50
|
+
dependencies:
|
|
51
|
+
- go
|
|
52
|
+
- vim
|
|
38
53
|
# setupscript 每次进入到app container后都会执行的配置脚本
|
|
39
54
|
# - 可以为脚本的路径地址
|
|
40
55
|
# - 如果构建命令简单,也可以直接写 sh 的命令
|
|
@@ -32,9 +32,25 @@ icon: ./lazycat.png
|
|
|
32
32
|
# - /=http://127.0.0.1:3000
|
|
33
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
34
|
|
|
35
|
+
# devshell 指定构建Dockerfile
|
|
36
|
+
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
+
# devshell:
|
|
38
|
+
# routes:
|
|
39
|
+
# - /=http://127.0.0.1:3000
|
|
40
|
+
# image: ${package}-devshell:${version}
|
|
41
|
+
# pull_policy: build
|
|
42
|
+
# build: .
|
|
43
|
+
|
|
44
|
+
# dvshell 指定开发依赖的情况
|
|
45
|
+
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
+
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
35
47
|
devshell:
|
|
36
48
|
routes:
|
|
37
49
|
- /=http://127.0.0.1:3000
|
|
50
|
+
dependencies:
|
|
51
|
+
- nodejs
|
|
52
|
+
- vim
|
|
53
|
+
- npm
|
|
38
54
|
# setupscript 每次进入到app container后都会执行的配置脚本
|
|
39
55
|
# - 可以为脚本的路径地址
|
|
40
56
|
# - 如果构建命令简单,也可以直接写 sh 的命令
|
|
@@ -17,6 +17,7 @@ pkgout: ./
|
|
|
17
17
|
# icon 指定 lpk 包 icon 的路径路径,如果不指定将会警告
|
|
18
18
|
# icon 仅仅允许 png 后缀的文件
|
|
19
19
|
icon: ./lazycat.png
|
|
20
|
+
|
|
20
21
|
# devshell 自定义应用的开发容器环境
|
|
21
22
|
# - routers 指定应用容器的访问路由
|
|
22
23
|
|
|
@@ -30,3 +31,30 @@ icon: ./lazycat.png
|
|
|
30
31
|
# routes:
|
|
31
32
|
# - /=http://127.0.0.1:3000
|
|
32
33
|
# image: registry.lazycat.cloud/lzc-cli/devshell:0.0.4
|
|
34
|
+
|
|
35
|
+
# devshell 指定构建Dockerfile
|
|
36
|
+
# image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
|
|
37
|
+
# devshell:
|
|
38
|
+
# routes:
|
|
39
|
+
# - /=http://127.0.0.1:3000
|
|
40
|
+
# image: ${package}-devshell:${version}
|
|
41
|
+
# pull_policy: build
|
|
42
|
+
# build: .
|
|
43
|
+
|
|
44
|
+
# dvshell 指定开发依赖的情况
|
|
45
|
+
# 这种情况下,选用 apline:3.16 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
|
|
46
|
+
# 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
|
|
47
|
+
# devshell:
|
|
48
|
+
# routes:
|
|
49
|
+
# - /=http://127.0.0.1:3000
|
|
50
|
+
# dependencies:
|
|
51
|
+
# - go
|
|
52
|
+
# - vim
|
|
53
|
+
# # setupscript 每次进入到app container后都会执行的配置脚本
|
|
54
|
+
# # - 可以为脚本的路径地址
|
|
55
|
+
# # - 如果构建命令简单,也可以直接写 sh 的命令
|
|
56
|
+
# # setupscript: export GOPROXY=https://goproxy.cn
|
|
57
|
+
# # setupscript: ./setupscript.sh
|
|
58
|
+
# setupscript: |
|
|
59
|
+
# export GOPROXY=https://goproxy.cn
|
|
60
|
+
# export npm_config_registry=https://registry.npmmirror.com
|