ethan-skill 1.7.0 → 1.8.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 (61) hide show
  1. package/README.md +83 -24
  2. package/dist/skills/15-git-workflow.d.ts +3 -0
  3. package/dist/skills/15-git-workflow.d.ts.map +1 -0
  4. package/dist/skills/15-git-workflow.js +288 -0
  5. package/dist/skills/15-git-workflow.js.map +1 -0
  6. package/dist/skills/16-unit-testing.d.ts +3 -0
  7. package/dist/skills/16-unit-testing.d.ts.map +1 -0
  8. package/dist/skills/16-unit-testing.js +298 -0
  9. package/dist/skills/16-unit-testing.js.map +1 -0
  10. package/dist/skills/17-system-design.d.ts +3 -0
  11. package/dist/skills/17-system-design.d.ts.map +1 -0
  12. package/dist/skills/17-system-design.js +294 -0
  13. package/dist/skills/17-system-design.js.map +1 -0
  14. package/dist/skills/18-database-optimize.d.ts +3 -0
  15. package/dist/skills/18-database-optimize.d.ts.map +1 -0
  16. package/dist/skills/18-database-optimize.js +294 -0
  17. package/dist/skills/18-database-optimize.js.map +1 -0
  18. package/dist/skills/19-docker.d.ts +3 -0
  19. package/dist/skills/19-docker.d.ts.map +1 -0
  20. package/dist/skills/19-docker.js +360 -0
  21. package/dist/skills/19-docker.js.map +1 -0
  22. package/dist/skills/20-cicd.d.ts +3 -0
  23. package/dist/skills/20-cicd.d.ts.map +1 -0
  24. package/dist/skills/20-cicd.js +364 -0
  25. package/dist/skills/20-cicd.js.map +1 -0
  26. package/dist/skills/21-performance.d.ts +3 -0
  27. package/dist/skills/21-performance.d.ts.map +1 -0
  28. package/dist/skills/21-performance.js +139 -0
  29. package/dist/skills/21-performance.js.map +1 -0
  30. package/dist/skills/22-refactoring.d.ts +3 -0
  31. package/dist/skills/22-refactoring.d.ts.map +1 -0
  32. package/dist/skills/22-refactoring.js +235 -0
  33. package/dist/skills/22-refactoring.js.map +1 -0
  34. package/dist/skills/23-observability.d.ts +3 -0
  35. package/dist/skills/23-observability.d.ts.map +1 -0
  36. package/dist/skills/23-observability.js +266 -0
  37. package/dist/skills/23-observability.js.map +1 -0
  38. package/dist/skills/24-design-patterns.d.ts +3 -0
  39. package/dist/skills/24-design-patterns.d.ts.map +1 -0
  40. package/dist/skills/24-design-patterns.js +258 -0
  41. package/dist/skills/24-design-patterns.js.map +1 -0
  42. package/dist/skills/index.d.ts +10 -0
  43. package/dist/skills/index.d.ts.map +1 -1
  44. package/dist/skills/index.js +41 -1
  45. package/dist/skills/index.js.map +1 -1
  46. package/dist/skills/skills.test.js +3 -3
  47. package/dist/skills/skills.test.js.map +1 -1
  48. package/dist/templates/templates.test.js +2 -3
  49. package/dist/templates/templates.test.js.map +1 -1
  50. package/package.json +1 -1
  51. package/rules/claude-code/CLAUDE.md +2410 -3
  52. package/rules/cline/.clinerules +2262 -2
  53. package/rules/codebuddy/CODEBUDDY.md +2361 -2
  54. package/rules/continue/.continuerules +2262 -2
  55. package/rules/copilot/copilot-instructions.md +2331 -2
  56. package/rules/cursor/.cursorrules +2399 -2
  57. package/rules/cursor/smart-flow.mdc +2399 -2
  58. package/rules/jetbrains/smart-flow.md +2331 -2
  59. package/rules/lingma/smart-flow.md +2352 -3
  60. package/rules/windsurf/.windsurf/rules/smart-flow.md +2332 -3
  61. package/rules/zed/smart-flow.rules +2251 -1
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.databaseOptimizeSkill = void 0;
4
+ exports.databaseOptimizeSkill = {
5
+ id: 'database-optimize',
6
+ name: '数据库优化',
7
+ nameEn: 'database_optimize',
8
+ order: 18,
9
+ category: '质量侧',
10
+ description: '系统诊断数据库性能问题,涵盖 Schema 审查、索引设计、慢查询分析和 N+1 修复',
11
+ descriptionEn: 'Diagnose and optimize database performance covering schema review, index design, slow query analysis, and N+1 fixes',
12
+ detailDescription: `端到端数据库性能优化指导,从 Schema 设计审查、索引策略制定、慢查询日志分析、
13
+ N+1 查询识别与修复,到分区分表策略,帮助系统在数据量增长时保持查询性能。`,
14
+ triggers: [
15
+ '数据库优化',
16
+ 'database optimize',
17
+ '慢查询',
18
+ 'slow query',
19
+ 'SQL 优化',
20
+ 'SQL optimization',
21
+ '索引优化',
22
+ 'index optimization',
23
+ 'N+1 问题',
24
+ 'N+1 query',
25
+ '查询性能',
26
+ 'query performance',
27
+ '@ethan db',
28
+ '@ethan database-optimize',
29
+ ],
30
+ steps: [
31
+ {
32
+ title: '1. Schema 设计审查',
33
+ content: `检查数据库表结构是否存在设计问题:
34
+
35
+ **规范化检查(防止冗余)**
36
+ \`\`\`sql
37
+ -- ❌ 反模式:在用户表存储地址字符串
38
+ CREATE TABLE users (
39
+ id INT PRIMARY KEY,
40
+ name VARCHAR(100),
41
+ address VARCHAR(500) -- 难以精准查询城市/省份
42
+ );
43
+
44
+ -- ✅ 正确:拆分为 addresses 表
45
+ CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(100));
46
+ CREATE TABLE addresses (
47
+ id INT PRIMARY KEY,
48
+ user_id INT REFERENCES users(id),
49
+ province VARCHAR(50),
50
+ city VARCHAR(50),
51
+ detail VARCHAR(200)
52
+ );
53
+ \`\`\`
54
+
55
+ **数据类型选择**
56
+
57
+ | 场景 | 推荐类型 | 避免 |
58
+ |------|---------|------|
59
+ | 主键 | BIGINT / UUID | INT(可能溢出) |
60
+ | 状态枚举 | TINYINT / ENUM | VARCHAR |
61
+ | 金额 | DECIMAL(10,2) | FLOAT(精度丢失)|
62
+ | 时间 | TIMESTAMP / DATETIME | VARCHAR |
63
+ | 短字符串(≤255) | VARCHAR(N) | TEXT |
64
+ | 布尔值 | TINYINT(1) | VARCHAR('true') |
65
+
66
+ **常见 Schema 问题清单**
67
+ - [ ] 是否有未使用的列?
68
+ - [ ] VARCHAR 长度是否合理(不要都 VARCHAR(255))?
69
+ - [ ] 外键是否有索引?
70
+ - [ ] 是否有重复的字段(非规范化导致)?
71
+ - [ ] 是否用了 TEXT/BLOB 存储应该单独存储的大文件?`,
72
+ },
73
+ {
74
+ title: '2. 索引设计策略',
75
+ content: `**索引类型选择**
76
+
77
+ \`\`\`sql
78
+ -- 单列索引:高选择性字段(如 email、手机号)
79
+ CREATE INDEX idx_users_email ON users(email);
80
+
81
+ -- 联合索引:遵循最左前缀原则
82
+ -- 适合查询: WHERE status = ? AND created_at > ?
83
+ -- 适合查询: WHERE status = ?
84
+ -- 不适合: WHERE created_at > ? (无法命中)
85
+ CREATE INDEX idx_orders_status_created ON orders(status, created_at);
86
+
87
+ -- 覆盖索引:索引包含查询所有字段,避免回表
88
+ -- 查询: SELECT user_id, status FROM orders WHERE order_no = ?
89
+ CREATE INDEX idx_orders_covering ON orders(order_no, user_id, status);
90
+
91
+ -- 前缀索引:长字符串节省空间
92
+ CREATE INDEX idx_url_prefix ON pages(url(50));
93
+
94
+ -- 函数索引(MySQL 8.0+):对表达式建索引
95
+ CREATE INDEX idx_lower_email ON users((LOWER(email)));
96
+ \`\`\`
97
+
98
+ **EXPLAIN 分析索引使用**
99
+ \`\`\`sql
100
+ EXPLAIN SELECT * FROM orders
101
+ WHERE user_id = 1001 AND status = 'PAID'
102
+ ORDER BY created_at DESC LIMIT 10;
103
+
104
+ -- 关注字段:
105
+ -- type: ref > range > index > ALL(ALL 最差)
106
+ -- key: 使用的索引名(NULL 表示未使用索引)
107
+ -- rows: 预估扫描行数(越小越好)
108
+ -- Extra: Using filesort / Using temporary(需优化的信号)
109
+ \`\`\`
110
+
111
+ **索引原则**
112
+ - 高频查询的 WHERE / JOIN / ORDER BY 字段建索引
113
+ - 选择性低的字段慎建索引(如 status 只有3个值)
114
+ - 避免在频繁更新的列上建过多索引(写性能代价)
115
+ - 复合索引字段顺序:等值条件在前,范围条件在后`,
116
+ },
117
+ {
118
+ title: '3. 慢查询分析与优化',
119
+ content: `**开启慢查询日志**
120
+ \`\`\`sql
121
+ -- MySQL 配置
122
+ SET GLOBAL slow_query_log = 'ON';
123
+ SET GLOBAL long_query_time = 1; -- 超过1秒记录
124
+ SET GLOBAL log_queries_not_using_indexes = 'ON';
125
+
126
+ -- 查看慢查询日志文件位置
127
+ SHOW VARIABLES LIKE 'slow_query_log_file';
128
+
129
+ -- 使用 pt-query-digest 分析日志
130
+ pt-query-digest /var/log/mysql/slow.log | head -100
131
+ \`\`\`
132
+
133
+ **常见慢查询模式与修复**
134
+ \`\`\`sql
135
+ -- ❌ 问题1: SELECT * 全列查询
136
+ SELECT * FROM orders WHERE user_id = 1001;
137
+ -- ✅ 修复: 只查需要的列
138
+ SELECT id, order_no, status, total FROM orders WHERE user_id = 1001;
139
+
140
+ -- ❌ 问题2: 对索引列使用函数,导致索引失效
141
+ SELECT * FROM orders WHERE DATE(created_at) = '2024-01-01';
142
+ -- ✅ 修复: 使用范围查询
143
+ SELECT * FROM orders
144
+ WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02';
145
+
146
+ -- ❌ 问题3: OR 导致索引失效(某些情况)
147
+ SELECT * FROM users WHERE email = ? OR phone = ?;
148
+ -- ✅ 修复: UNION ALL
149
+ SELECT * FROM users WHERE email = ?
150
+ UNION ALL
151
+ SELECT * FROM users WHERE phone = ?;
152
+
153
+ -- ❌ 问题4: LIKE 前缀通配符
154
+ SELECT * FROM products WHERE name LIKE '%iPhone%';
155
+ -- ✅ 修复: 使用全文索引或 Elasticsearch
156
+ SELECT * FROM products WHERE MATCH(name) AGAINST('iPhone' IN BOOLEAN MODE);
157
+
158
+ -- ❌ 问题5: 隐式类型转换
159
+ SELECT * FROM users WHERE user_id = '1001'; -- user_id 是 INT
160
+ -- ✅ 修复: 类型匹配
161
+ SELECT * FROM users WHERE user_id = 1001;
162
+ \`\`\``,
163
+ },
164
+ {
165
+ title: '4. N+1 查询识别与修复',
166
+ content: `**N+1 问题定义**:查询1次获取N条记录,再针对每条记录查询1次,共 N+1 次数据库访问。
167
+
168
+ **ORM 场景中的 N+1**
169
+ \`\`\`typescript
170
+ // ❌ TypeORM N+1 示例:查100个用户 → 执行101次SQL
171
+ const users = await userRepository.find(); // Query 1: SELECT * FROM users
172
+ for (const user of users) {
173
+ const orders = await user.orders; // Query 2-101: 每个用户各查一次
174
+ console.log(orders.length);
175
+ }
176
+
177
+ // ✅ 修复:使用 eager loading(JOIN)
178
+ const users = await userRepository.find({
179
+ relations: ['orders'], // 一次 JOIN 查询搞定
180
+ });
181
+
182
+ // ✅ 或使用 QueryBuilder(更精确控制)
183
+ const users = await userRepository
184
+ .createQueryBuilder('user')
185
+ .leftJoinAndSelect('user.orders', 'order')
186
+ .where('order.status = :status', { status: 'PAID' })
187
+ .getMany();
188
+ \`\`\`
189
+
190
+ **原生 SQL 批量查询模式**
191
+ \`\`\`sql
192
+ -- ❌ N+1: 循环查询
193
+ -- for user_id in user_ids: SELECT * FROM orders WHERE user_id = ?
194
+
195
+ -- ✅ 批量查询 + 应用层 Map 聚合
196
+ SELECT user_id, COUNT(*) as order_count, SUM(total) as total_amount
197
+ FROM orders
198
+ WHERE user_id IN (1,2,3,...,100) -- 一次查询
199
+ GROUP BY user_id;
200
+ -- 在应用层用 Map 按 user_id 聚合
201
+ \`\`\`
202
+
203
+ **检测 N+1 工具**
204
+ \`\`\`
205
+ - Laravel Debugbar(PHP)
206
+ - Django Debug Toolbar(Python)
207
+ - Bullet gem(Rails)
208
+ - TypeORM logging: { logging: true } 观察 SQL 数量
209
+ - DataLoader(GraphQL 场景批量加载)
210
+ \`\`\``,
211
+ },
212
+ {
213
+ title: '5. 分区与分表策略',
214
+ content: `**表分区(Partitioning)— 单机方案**
215
+ \`\`\`sql
216
+ -- 按时间范围分区(适合日志、订单历史)
217
+ CREATE TABLE orders (
218
+ id BIGINT,
219
+ user_id INT,
220
+ created_at DATETIME,
221
+ total DECIMAL(10,2)
222
+ ) PARTITION BY RANGE (YEAR(created_at)) (
223
+ PARTITION p2022 VALUES LESS THAN (2023),
224
+ PARTITION p2023 VALUES LESS THAN (2024),
225
+ PARTITION p2024 VALUES LESS THAN (2025),
226
+ PARTITION pmax VALUES LESS THAN MAXVALUE
227
+ );
228
+
229
+ -- 分区裁剪:查询自动只扫描相关分区
230
+ SELECT * FROM orders WHERE created_at >= '2024-01-01';
231
+ -- 只扫描 p2024 分区,跳过历史分区
232
+ \`\`\`
233
+
234
+ **分库分表策略(超千万行后考虑)**
235
+
236
+ | 方案 | 分片键选择 | 适用场景 |
237
+ |------|----------|---------|
238
+ | 水平分表(同库) | user_id % N | 单库容量瓶颈 |
239
+ | 水平分库 | user_id % N | 读写 QPS 瓶颈 |
240
+ | 按地区分库 | region | 合规/延迟要求 |
241
+
242
+ \`\`\`
243
+ 分片键选择原则:
244
+ - 选择查询中高频使用的字段(避免跨分片查询)
245
+ - 选择数据分布均匀的字段(避免热点)
246
+ - 一旦确定不能轻易更改
247
+
248
+ 常见工具:
249
+ - ShardingSphere(Java)
250
+ - Vitess(MySQL 集群,YouTube 方案)
251
+ - Citus(PostgreSQL 分布式扩展)
252
+ \`\`\`
253
+
254
+ **读写分离配置**
255
+ \`\`\`
256
+ 主库(Primary): 处理写操作 + 强一致读
257
+ 从库(Replica): 处理读操作(注意主从延迟,通常 <1s)
258
+
259
+ 适用于读写比 > 4:1 的场景
260
+ 注意: 写后立即读可能读到旧数据(主从同步延迟)
261
+ 解决: 重要读操作路由到主库;或用 Redis 缓存最新写入
262
+ \`\`\``,
263
+ },
264
+ ],
265
+ outputFormat: 'Markdown 优化报告,含 Schema 问题列表、索引设计方案、慢查询 EXPLAIN 分析、N+1 修复代码示例和分区建议',
266
+ examples: [
267
+ {
268
+ input: '用户列表页加载很慢,查询订单表,数据量1000万行',
269
+ output: `## 数据库性能诊断
270
+
271
+ **Step 1: 执行 EXPLAIN**
272
+ \`\`\`sql
273
+ EXPLAIN SELECT o.*, u.name FROM orders o
274
+ JOIN users u ON o.user_id = u.id
275
+ WHERE o.status = 'PAID' ORDER BY o.created_at DESC LIMIT 20;
276
+ \`\`\`
277
+
278
+ **发现问题**:type = ALL(全表扫描),rows = 10,000,000
279
+
280
+ **优化方案**:
281
+ 1. 添加联合索引:\`CREATE INDEX idx_orders_status_created ON orders(status, created_at DESC);\`
282
+ 2. 加 users 表关联索引:\`CREATE INDEX idx_users_id ON users(id);\`(通常主键已有)
283
+ 3. 预期效果:rows 从 1000万 降至 <1000,响应时间从 5s → 50ms`,
284
+ },
285
+ ],
286
+ notes: [
287
+ '优化前先用 EXPLAIN 分析,避免盲目加索引',
288
+ '索引不是越多越好,每个索引都会降低写入性能,控制在 5-8 个以内',
289
+ '分库分表是最后手段,优先考虑索引优化、缓存、读写分离',
290
+ '生产环境加索引使用 gh-ost 或 pt-online-schema-change,避免锁表',
291
+ ],
292
+ nextSkill: 'docker',
293
+ };
294
+ //# sourceMappingURL=18-database-optimize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"18-database-optimize.js","sourceRoot":"","sources":["../../src/skills/18-database-optimize.ts"],"names":[],"mappings":";;;AAEa,QAAA,qBAAqB,GAAoB;IACpD,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,OAAO;IACb,MAAM,EAAE,mBAAmB;IAC3B,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,6CAA6C;IAC1D,aAAa,EAAE,qHAAqH;IACpI,iBAAiB,EAAE;uCACkB;IACrC,QAAQ,EAAE;QACR,OAAO;QACP,mBAAmB;QACnB,KAAK;QACL,YAAY;QACZ,QAAQ;QACR,kBAAkB;QAClB,MAAM;QACN,oBAAoB;QACpB,QAAQ;QACR,WAAW;QACX,MAAM;QACN,mBAAmB;QACnB,WAAW;QACX,0BAA0B;KAC3B;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCAsCoB;SAC9B;QACD;YACE,KAAK,EAAE,WAAW;YAClB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAwCU;SACpB;QACD;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CR;SACF;QACD;YACE,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CR;SACF;QACD;YACE,KAAK,EAAE,YAAY;YACnB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDR;SACF;KACF;IACD,YAAY,EACV,mEAAmE;IACrE,QAAQ,EAAE;QACR;YACE,KAAK,EAAE,2BAA2B;YAClC,MAAM,EAAE;;;;;;;;;;;;;;8CAcgC;SACzC;KACF;IACD,KAAK,EAAE;QACL,0BAA0B;QAC1B,mCAAmC;QACnC,4BAA4B;QAC5B,iDAAiD;KAClD;IACD,SAAS,EAAE,QAAQ;CACpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SkillDefinition } from './types';
2
+ export declare const dockerSkill: SkillDefinition;
3
+ //# sourceMappingURL=19-docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"19-docker.d.ts","sourceRoot":"","sources":["../../src/skills/19-docker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,WAAW,EAAE,eAoWzB,CAAC"}
@@ -0,0 +1,360 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dockerSkill = void 0;
4
+ exports.dockerSkill = {
5
+ id: 'docker',
6
+ name: 'Docker 容器化',
7
+ nameEn: 'docker',
8
+ order: 19,
9
+ category: '执行侧',
10
+ description: '编写生产级 Dockerfile,实现多阶段构建、镜像优化和 docker-compose 编排',
11
+ descriptionEn: 'Write production-grade Dockerfiles with multi-stage builds, image optimization, docker-compose orchestration, and security scanning',
12
+ detailDescription: `系统指导 Docker 容器化实践,涵盖 Dockerfile 最佳实践、多阶段构建减小镜像体积、
13
+ 镜像安全扫描、docker-compose 服务编排和容器运行时安全配置,帮助将应用安全高效地容器化。`,
14
+ triggers: [
15
+ 'Docker',
16
+ 'docker',
17
+ '容器化',
18
+ 'containerization',
19
+ 'Dockerfile',
20
+ 'dockerfile',
21
+ 'docker-compose',
22
+ '镜像优化',
23
+ 'image optimization',
24
+ '多阶段构建',
25
+ 'multi-stage build',
26
+ '容器安全',
27
+ '@ethan docker',
28
+ ],
29
+ steps: [
30
+ {
31
+ title: '1. Dockerfile 基础最佳实践',
32
+ content: `**基础规则清单**
33
+
34
+ \`\`\`dockerfile
35
+ # ✅ 使用具体版本标签,避免 latest(不可复现)
36
+ FROM node:20.11-alpine3.19
37
+
38
+ # ✅ 设置工作目录(避免在根目录操作)
39
+ WORKDIR /app
40
+
41
+ # ✅ 先复制依赖文件,利用层缓存
42
+ # 依赖文件不变时,npm install 层直接复用缓存
43
+ COPY package*.json ./
44
+ RUN npm ci --only=production
45
+
46
+ # ✅ 再复制源码(源码改变不影响依赖缓存)
47
+ COPY . .
48
+
49
+ # ✅ 使用非 root 用户运行(安全最佳实践)
50
+ RUN addgroup -S appgroup && adduser -S appuser -G appgroup
51
+ USER appuser
52
+
53
+ # ✅ 仅暴露必要端口
54
+ EXPOSE 3000
55
+
56
+ # ✅ 使用 ENTRYPOINT + CMD 组合(更灵活)
57
+ ENTRYPOINT ["node"]
58
+ CMD ["dist/index.js"]
59
+ \`\`\`
60
+
61
+ **层缓存优化原则**
62
+ \`\`\`
63
+ 构建缓存命中规则:指令 + 参数 + 上下文文件 都相同才命中缓存
64
+
65
+ 优化策略:
66
+ 1. 变化频率低的指令放前面(基础镜像、系统依赖)
67
+ 2. 变化频率高的指令放后面(应用代码)
68
+ 3. 合并 RUN 指令减少层数
69
+
70
+ # ❌ 多个 RUN 产生多个层
71
+ RUN apt-get update
72
+ RUN apt-get install -y curl
73
+ RUN apt-get clean
74
+
75
+ # ✅ 合并为一个 RUN,减少层数 + 及时清理缓存
76
+ RUN apt-get update && apt-get install -y curl \
77
+ && rm -rf /var/lib/apt/lists/*
78
+ \`\`\``,
79
+ },
80
+ {
81
+ title: '2. 多阶段构建(Multi-Stage Build)',
82
+ content: `多阶段构建将构建环境与运行环境分离,显著减小生产镜像体积:
83
+
84
+ **Node.js 应用示例**
85
+ \`\`\`dockerfile
86
+ # ===== Stage 1: Build =====
87
+ FROM node:20.11-alpine3.19 AS builder
88
+ WORKDIR /app
89
+
90
+ # 安装所有依赖(含 devDependencies)
91
+ COPY package*.json ./
92
+ RUN npm ci
93
+
94
+ # 编译 TypeScript
95
+ COPY . .
96
+ RUN npm run build
97
+
98
+ # ===== Stage 2: Dependencies =====
99
+ FROM node:20.11-alpine3.19 AS deps
100
+ WORKDIR /app
101
+ COPY package*.json ./
102
+ # 只安装生产依赖
103
+ RUN npm ci --only=production
104
+
105
+ # ===== Stage 3: Production =====
106
+ FROM node:20.11-alpine3.19 AS production
107
+ WORKDIR /app
108
+
109
+ # 只从前两个阶段复制必要文件
110
+ COPY --from=deps /app/node_modules ./node_modules
111
+ COPY --from=builder /app/dist ./dist
112
+
113
+ # 非 root 用户
114
+ RUN addgroup -S app && adduser -S app -G app
115
+ USER app
116
+
117
+ EXPOSE 3000
118
+ HEALTHCHECK --interval=30s --timeout=3s CMD wget -qO- http://localhost:3000/health || exit 1
119
+ CMD ["node", "dist/index.js"]
120
+ \`\`\`
121
+
122
+ **效果对比**
123
+ \`\`\`
124
+ 单阶段构建(含 devDeps + 源码): ~800 MB
125
+ 多阶段构建(只含运行时): ~120 MB
126
+ 体积减少约 85%
127
+ \`\`\`
128
+
129
+ **Go 应用(静态二进制最小镜像)**
130
+ \`\`\`dockerfile
131
+ FROM golang:1.22-alpine AS builder
132
+ WORKDIR /app
133
+ COPY go.mod go.sum ./
134
+ RUN go mod download
135
+ COPY . .
136
+ RUN CGO_ENABLED=0 GOOS=linux go build -o server .
137
+
138
+ # 使用 scratch(空镜像)或 distroless
139
+ FROM gcr.io/distroless/static-debian12
140
+ COPY --from=builder /app/server /server
141
+ EXPOSE 8080
142
+ ENTRYPOINT ["/server"]
143
+ # 最终镜像仅 ~10MB
144
+ \`\`\``,
145
+ },
146
+ {
147
+ title: '3. .dockerignore 与镜像安全',
148
+ content: `**配置 .dockerignore**
149
+ \`\`\`dockerignore
150
+ # 排除不需要的文件,减小构建上下文
151
+ node_modules
152
+ npm-debug.log
153
+ .git
154
+ .gitignore
155
+ .env
156
+ .env.*
157
+ *.md
158
+ .DS_Store
159
+ coverage/
160
+ dist/
161
+ .nyc_output
162
+ __tests__
163
+ *.test.ts
164
+ Dockerfile*
165
+ docker-compose*
166
+ \`\`\`
167
+
168
+ **镜像安全扫描**
169
+ \`\`\`bash
170
+ # Trivy(推荐,免费开源)
171
+ docker pull aquasec/trivy
172
+ trivy image --severity HIGH,CRITICAL myapp:latest
173
+
174
+ # 输出示例:
175
+ # CRITICAL: CVE-2024-xxxx in openssl 3.0.0 → 升级到 3.0.13
176
+
177
+ # 集成到 CI(GitHub Actions)
178
+ - name: Scan Docker image
179
+ uses: aquasecurity/trivy-action@master
180
+ with:
181
+ image-ref: 'myapp:\${{ github.sha }}'
182
+ severity: 'CRITICAL,HIGH'
183
+ exit-code: '1' # 发现高危漏洞时 CI 失败
184
+ \`\`\`
185
+
186
+ **容器运行时安全配置**
187
+ \`\`\`bash
188
+ # 禁止 root 运行(Dockerfile 中已设置 USER,运行时再确认)
189
+ docker run --user 1001:1001 myapp:latest
190
+
191
+ # 只读文件系统(防止容器内写文件)
192
+ docker run --read-only --tmpfs /tmp myapp:latest
193
+
194
+ # 限制资源
195
+ docker run --memory="256m" --cpus="0.5" myapp:latest
196
+
197
+ # 丢弃不需要的 Linux Capabilities
198
+ docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp:latest
199
+
200
+ # 禁止权限提升
201
+ docker run --security-opt no-new-privileges myapp:latest
202
+ \`\`\``,
203
+ },
204
+ {
205
+ title: '4. Docker Compose 服务编排',
206
+ content: `**生产级 docker-compose.yml 示例**
207
+ \`\`\`yaml
208
+ version: '3.9'
209
+
210
+ services:
211
+ app:
212
+ build:
213
+ context: .
214
+ dockerfile: Dockerfile
215
+ target: production # 指定多阶段构建的目标阶段
216
+ image: myapp:\${APP_VERSION:-latest}
217
+ restart: unless-stopped
218
+ ports:
219
+ - "3000:3000"
220
+ environment:
221
+ NODE_ENV: production
222
+ DATABASE_URL: \${DATABASE_URL} # 从 .env 文件读取,不硬编码
223
+ env_file:
224
+ - .env.production
225
+ depends_on:
226
+ db:
227
+ condition: service_healthy # 等待健康检查通过
228
+ redis:
229
+ condition: service_healthy
230
+ healthcheck:
231
+ test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
232
+ interval: 30s
233
+ timeout: 5s
234
+ retries: 3
235
+ start_period: 40s
236
+ deploy:
237
+ resources:
238
+ limits:
239
+ cpus: '1.0'
240
+ memory: 512M
241
+ networks:
242
+ - app-network
243
+
244
+ db:
245
+ image: postgres:16-alpine
246
+ restart: unless-stopped
247
+ environment:
248
+ POSTGRES_DB: \${DB_NAME}
249
+ POSTGRES_USER: \${DB_USER}
250
+ POSTGRES_PASSWORD: \${DB_PASSWORD}
251
+ volumes:
252
+ - postgres-data:/var/lib/postgresql/data
253
+ - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
254
+ healthcheck:
255
+ test: ["CMD-SHELL", "pg_isready -U \${DB_USER}"]
256
+ interval: 10s
257
+ timeout: 5s
258
+ retries: 5
259
+ networks:
260
+ - app-network
261
+
262
+ redis:
263
+ image: redis:7-alpine
264
+ restart: unless-stopped
265
+ command: redis-server --requirepass \${REDIS_PASSWORD}
266
+ volumes:
267
+ - redis-data:/data
268
+ healthcheck:
269
+ test: ["CMD", "redis-cli", "ping"]
270
+ interval: 10s
271
+ networks:
272
+ - app-network
273
+
274
+ networks:
275
+ app-network:
276
+ driver: bridge
277
+
278
+ volumes:
279
+ postgres-data:
280
+ redis-data:
281
+ \`\`\`
282
+
283
+ **常用 Compose 命令**
284
+ \`\`\`bash
285
+ docker compose up -d # 后台启动
286
+ docker compose up -d --build # 重新构建并启动
287
+ docker compose logs -f app # 实时查看日志
288
+ docker compose exec app sh # 进入容器 shell
289
+ docker compose ps # 查看服务状态
290
+ docker compose down -v # 停止并删除 volume
291
+ \`\`\``,
292
+ },
293
+ {
294
+ title: '5. 镜像优化与发布',
295
+ content: `**镜像大小优化总结**
296
+
297
+ | 优化手段 | 效果 |
298
+ |---------|------|
299
+ | 使用 Alpine 基础镜像 | node:20 → node:20-alpine,1.1GB → 150MB |
300
+ | 多阶段构建 | 去除构建工具 & devDependencies |
301
+ | .dockerignore | 减小构建上下文 |
302
+ | 合并 RUN 清理缓存 | 减少层数和大小 |
303
+ | distroless/scratch | Go/Rust 应用极小镜像 |
304
+
305
+ **镜像打标签规范**
306
+ \`\`\`bash
307
+ # 语义化版本 + git commit hash
308
+ docker build -t myapp:1.2.3 -t myapp:1.2.3-abc1234 .
309
+
310
+ # CI 中自动打标签
311
+ docker build \
312
+ -t myregistry/myapp:\${VERSION} \
313
+ -t myregistry/myapp:latest \
314
+ --label "git.commit=\${GIT_SHA}" \
315
+ --label "build.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
316
+ .
317
+ \`\`\`
318
+
319
+ **镜像推送到 Registry**
320
+ \`\`\`bash
321
+ # 登录到 GitHub Container Registry
322
+ echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
323
+
324
+ # 推送
325
+ docker push ghcr.io/org/myapp:1.2.3
326
+
327
+ # 使用 Docker BuildKit(并行构建,更快)
328
+ DOCKER_BUILDKIT=1 docker build .
329
+
330
+ # 多平台构建(兼容 ARM Mac 和 x86 服务器)
331
+ docker buildx build --platform linux/amd64,linux/arm64 \
332
+ -t myapp:latest --push .
333
+ \`\`\``,
334
+ },
335
+ ],
336
+ outputFormat: 'Markdown 容器化方案,含优化后的 Dockerfile、.dockerignore、docker-compose.yml 配置和安全加固建议',
337
+ examples: [
338
+ {
339
+ input: '帮我给 Node.js TypeScript 项目写一个生产级 Dockerfile',
340
+ output: `## 生产级 Node.js Dockerfile
341
+
342
+ 使用三阶段构建(builder → deps → production),最终镜像约 120MB。
343
+
344
+ 关键优化点:
345
+ 1. Alpine 基础镜像减小体积
346
+ 2. builder 阶段编译 TS,deps 阶段只装生产依赖
347
+ 3. production 阶段只复制必要文件,非 root 用户运行
348
+ 4. HEALTHCHECK 支持容器健康检查
349
+ 5. .dockerignore 排除测试文件、.env、.git`,
350
+ },
351
+ ],
352
+ notes: [
353
+ '生产镜像绝不使用 :latest 标签,始终用具体版本号确保可复现',
354
+ '绝不在 Dockerfile 中写入密钥或密码,使用环境变量或 Docker Secrets',
355
+ '每次发版前用 Trivy 扫描镜像漏洞,CRITICAL 漏洞不上线',
356
+ 'docker-compose 仅用于本地开发和小规模部署,生产大规模编排推荐 Kubernetes',
357
+ ],
358
+ nextSkill: 'cicd',
359
+ };
360
+ //# sourceMappingURL=19-docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"19-docker.js","sourceRoot":"","sources":["../../src/skills/19-docker.ts"],"names":[],"mappings":";;;AAEa,QAAA,WAAW,GAAoB;IAC1C,EAAE,EAAE,QAAQ;IACZ,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,kDAAkD;IAC/D,aAAa,EAAE,qIAAqI;IACpJ,iBAAiB,EAAE;oDAC+B;IAClD,QAAQ,EAAE;QACR,QAAQ;QACR,QAAQ;QACR,KAAK;QACL,kBAAkB;QAClB,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,MAAM;QACN,oBAAoB;QACpB,OAAO;QACP,mBAAmB;QACnB,MAAM;QACN,eAAe;KAChB;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,sBAAsB;YAC7B,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CR;SACF;QACD;YACE,KAAK,EAAE,6BAA6B;YACpC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8DR;SACF;QACD;YACE,KAAK,EAAE,wBAAwB;YAC/B,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsDR;SACF;QACD;YACE,KAAK,EAAE,wBAAwB;YAC/B,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqFR;SACF;QACD;YACE,KAAK,EAAE,YAAY;YACnB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCR;SACF;KACF;IACD,YAAY,EACV,4EAA4E;IAC9E,QAAQ,EAAE;QACR;YACE,KAAK,EAAE,4CAA4C;YACnD,MAAM,EAAE;;;;;;;;;kCASoB;SAC7B;KACF;IACD,KAAK,EAAE;QACL,mCAAmC;QACnC,gDAAgD;QAChD,oCAAoC;QACpC,mDAAmD;KACpD;IACD,SAAS,EAAE,MAAM;CAClB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SkillDefinition } from './types';
2
+ export declare const cicdSkill: SkillDefinition;
3
+ //# sourceMappingURL=20-cicd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20-cicd.d.ts","sourceRoot":"","sources":["../../src/skills/20-cicd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,SAAS,EAAE,eAwWvB,CAAC"}