@devflow-tools/plugin-docker 0.12.6 → 0.13.1
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/dist/analyzers/dockerize.d.ts +3 -0
- package/dist/analyzers/dockerize.d.ts.map +1 -0
- package/dist/analyzers/dockerize.js +70 -0
- package/dist/analyzers/dockerize.js.map +1 -0
- package/dist/analyzers/types.d.ts +19 -0
- package/dist/analyzers/types.d.ts.map +1 -0
- package/dist/analyzers/types.js +2 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1531 -0
- package/dist/index.js.map +1 -0
- package/package.json +3 -3
package/dist/index.js
ADDED
|
@@ -0,0 +1,1531 @@
|
|
|
1
|
+
const structuredOutputSchema = {
|
|
2
|
+
type: "object",
|
|
3
|
+
additionalProperties: true,
|
|
4
|
+
};
|
|
5
|
+
const readOnlyAnnotations = {
|
|
6
|
+
readOnlyHint: true,
|
|
7
|
+
idempotentHint: true,
|
|
8
|
+
};
|
|
9
|
+
export const dockerPlugin = {
|
|
10
|
+
meta: {
|
|
11
|
+
name: "docker",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
description: "Docker 专家 — 镜像优化、Compose 编排、安全扫描、多阶段构建",
|
|
14
|
+
icon: "🐳",
|
|
15
|
+
tags: ["devops", "docker", "container", "compose", "security"],
|
|
16
|
+
},
|
|
17
|
+
knowledge: {
|
|
18
|
+
sources: [
|
|
19
|
+
{
|
|
20
|
+
name: "docker-docs",
|
|
21
|
+
urls: [
|
|
22
|
+
"https://docs.docker.com/reference/",
|
|
23
|
+
"https://docs.docker.com/compose/compose-file/",
|
|
24
|
+
"https://docs.docker.com/build/building/best-practices/",
|
|
25
|
+
],
|
|
26
|
+
pluginName: "docker",
|
|
27
|
+
version: "26.0.0",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
memory: {
|
|
32
|
+
project: {
|
|
33
|
+
stack: ["Docker", "Docker Compose", "Nginx", "Node.js 18"],
|
|
34
|
+
conventions: [
|
|
35
|
+
{ key: "images", value: "使用官方基础镜像,固定版本标签避免 latest", source: "manual", confidence: 0.95 },
|
|
36
|
+
{ key: "multi-stage", value: "使用多阶段构建减小镜像体积", source: "manual", confidence: 0.9 },
|
|
37
|
+
{ key: "layer", value: "合理利用层缓存:先 COPY package.json,再 npm install,最后 COPY 源码", source: "manual", confidence: 0.9 },
|
|
38
|
+
{ key: "compose", value: "每个服务一个 docker-compose.yml,使用 profiles 区分环境", source: "manual", confidence: 0.8 },
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
global: [
|
|
42
|
+
{
|
|
43
|
+
id: "docker:dockerfile-best-practices",
|
|
44
|
+
source: "docker",
|
|
45
|
+
title: "Dockerfile 最佳实践",
|
|
46
|
+
content: "使用多阶段构建分离构建和运行环境。利用层缓存优化构建速度。使用 .dockerignore 排除无用文件。使用非 root 用户运行应用。添加 HEALTHCHECK。",
|
|
47
|
+
embedding: [],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "docker:compose-patterns",
|
|
51
|
+
source: "docker",
|
|
52
|
+
title: "Compose 编排模式",
|
|
53
|
+
content: "多服务应用使用 docker-compose.yml 定义服务、网络、卷。depends_on 控制启动顺序。profiles 区分环境。环境变量通过 .env 文件和 environment 字段注入。",
|
|
54
|
+
embedding: [],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "docker:security",
|
|
58
|
+
source: "docker",
|
|
59
|
+
title: "Docker 安全最佳实践",
|
|
60
|
+
content: "使用非 root 用户运行容器。定期扫描镜像漏洞(docker scout)。不将敏感信息写入镜像层。使用 --read-only 挂载只读根文件系统。限制容器资源。使用 secrets 管理敏感配置。",
|
|
61
|
+
embedding: [],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "docker:layer-optimization",
|
|
65
|
+
source: "docker",
|
|
66
|
+
title: "层缓存优化策略",
|
|
67
|
+
content: "Docker 按指令顺序创建层,变更的层及之后所有层重建。COPY package.json → RUN npm ci → COPY . 的顺序确保依赖不变时不重新安装。.dockerignore 排除 node_modules、.git、dist。",
|
|
68
|
+
embedding: [],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
workflow: {
|
|
73
|
+
steps: [],
|
|
74
|
+
templates: [
|
|
75
|
+
// ── dockerize ──
|
|
76
|
+
{
|
|
77
|
+
name: "dockerize",
|
|
78
|
+
description: "项目 Docker 化:分析项目 → 多阶段 Dockerfile → Compose → 构建验证",
|
|
79
|
+
version: "2.0.0",
|
|
80
|
+
steps: [
|
|
81
|
+
{
|
|
82
|
+
id: "analyze-project",
|
|
83
|
+
title: "分析项目结构",
|
|
84
|
+
instruction: [
|
|
85
|
+
"## 分析项目结构(语言、框架、端口、数据库依赖)",
|
|
86
|
+
"",
|
|
87
|
+
"扫描项目根目录和 package.json / go.mod / requirements.txt 等清单文件,提取关键信息。",
|
|
88
|
+
"",
|
|
89
|
+
"**执行动作**:",
|
|
90
|
+
"1. 列出项目根目录文件,识别清单文件:",
|
|
91
|
+
" ```bash",
|
|
92
|
+
" ls -1 | grep -E 'package.json|go.mod|requirements.txt|pom.xml|Gemfile|Cargo.toml|mix.exs'",
|
|
93
|
+
" ```",
|
|
94
|
+
"2. 读取清单文件,提取:",
|
|
95
|
+
" - 语言 / 运行时版本(node 18 / go 1.21 / python 3.11)",
|
|
96
|
+
" - 框架(express / next / nest / django / fastapi)",
|
|
97
|
+
" - 启动命令(`npm start` / `go run` / `uvicorn`)",
|
|
98
|
+
"3. 查找端口配置:",
|
|
99
|
+
" ```bash",
|
|
100
|
+
" grep -rnE 'PORT|port.*[:=]|listen\\(' src/ --include='*.ts' --include='*.js' --include='*.go' --include='*.py' | head -20",
|
|
101
|
+
" ```",
|
|
102
|
+
"4. 查找数据库 / 缓存依赖(redis / postgres / mysql / mongo):",
|
|
103
|
+
" ```bash",
|
|
104
|
+
" grep -rniE 'redis|postgres|mysql|mongodb|sqlite|prisma|sequelize|typeorm' package.json go.mod requirements.txt | head -20",
|
|
105
|
+
" ```",
|
|
106
|
+
"5. 查找环境变量依赖:",
|
|
107
|
+
" ```bash",
|
|
108
|
+
" grep -rn 'process.env\\.' src/ --include='*.ts' --include='*.js' | head -20",
|
|
109
|
+
" ```",
|
|
110
|
+
"",
|
|
111
|
+
"**产出格式**:",
|
|
112
|
+
"```",
|
|
113
|
+
"language: node",
|
|
114
|
+
"runtime_version: 18-alpine",
|
|
115
|
+
"framework: nestjs",
|
|
116
|
+
"start_command: npm run start:prod",
|
|
117
|
+
"port: 3000",
|
|
118
|
+
"db_dependency: postgres (via typeorm)",
|
|
119
|
+
"cache_dependency: redis",
|
|
120
|
+
"env_vars: ['DATABASE_URL', 'REDIS_URL', 'JWT_SECRET']",
|
|
121
|
+
"build_required: true (typescript → javascript)",
|
|
122
|
+
"```",
|
|
123
|
+
].join("\n"),
|
|
124
|
+
suggestedTools: ["Bash", "Read"],
|
|
125
|
+
output: "项目语言、框架、启动命令、端口、数据库/缓存依赖、环境变量清单",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: "choose-base-image",
|
|
129
|
+
title: "选择最优基础镜像",
|
|
130
|
+
instruction: [
|
|
131
|
+
"## 选择最优基础镜像(Alpine vs Slim vs 官方)",
|
|
132
|
+
"",
|
|
133
|
+
"根据 `analyze-project` 的语言、框架和构建需求,选择体积最小且兼容的基础镜像。",
|
|
134
|
+
"",
|
|
135
|
+
"**执行动作**:",
|
|
136
|
+
"1. 若项目含原生依赖(如 node-gyp、sharp、bcrypt),优先选择 `slim` 而不是 `alpine`(musl vs glibc 兼容问题):",
|
|
137
|
+
" ```bash",
|
|
138
|
+
" grep -E 'sharp|bcrypt|canvas|node-sass|sqlite3' package.json",
|
|
139
|
+
" ```",
|
|
140
|
+
"2. 镜像尺寸优先级(从小到大):",
|
|
141
|
+
" - `node:18-alpine`(~50MB)—— 无原生依赖",
|
|
142
|
+
" - `node:18-slim`(~80MB)—— 有原生依赖",
|
|
143
|
+
" - `node:18`(~350MB)—— 不推荐生产",
|
|
144
|
+
"3. 多语言场景基础镜像选择:",
|
|
145
|
+
" - Go:`golang:1.21-alpine`(build)+ `alpine:3.18`(prod)",
|
|
146
|
+
" - Python:`python:3.11-slim`(build+prod)或 `python:3.11-alpine`",
|
|
147
|
+
" - Java:`eclipse-temurin:17-jdk-alpine`(build)+ `eclipse-temurin:17-jre-alpine`(prod)",
|
|
148
|
+
"4. 固定具体版本标签,禁止使用 `latest`:",
|
|
149
|
+
" - ✅ `node:18.18.2-alpine3.18`",
|
|
150
|
+
" - ❌ `node:latest` / `node:18`",
|
|
151
|
+
"5. 检查镜像是否有已知 CVE:",
|
|
152
|
+
" ```bash",
|
|
153
|
+
" docker scout cves node:18-alpine 2>/dev/null | head -30",
|
|
154
|
+
" ```",
|
|
155
|
+
"",
|
|
156
|
+
"**产出格式**:",
|
|
157
|
+
"```",
|
|
158
|
+
"chosen_image: node:18.18.2-alpine3.18",
|
|
159
|
+
"rationale: no native deps, smallest footprint",
|
|
160
|
+
"build_image: node:18.18.2-alpine3.18",
|
|
161
|
+
"prod_image: node:18.18.2-alpine3.18",
|
|
162
|
+
"cve_status: 0 critical, 2 high (accepted)",
|
|
163
|
+
"```",
|
|
164
|
+
].join("\n"),
|
|
165
|
+
suggestedTools: ["Bash", "Read"],
|
|
166
|
+
output: "选定的基础镜像标签、选择理由、构建与运行阶段镜像",
|
|
167
|
+
depends: ["analyze-project"],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "create-dockerfile",
|
|
171
|
+
title: "创建多阶段 Dockerfile",
|
|
172
|
+
instruction: [
|
|
173
|
+
"## 创建多阶段 Dockerfile(build + prod 阶段)",
|
|
174
|
+
"",
|
|
175
|
+
"基于 `choose-base-image` 选择的镜像,创建多阶段 Dockerfile。",
|
|
176
|
+
"",
|
|
177
|
+
"**执行动作**:",
|
|
178
|
+
"1. 创建 `Dockerfile`,结构如下:",
|
|
179
|
+
" ```dockerfile",
|
|
180
|
+
" # syntax=docker/dockerfile:1.6",
|
|
181
|
+
" FROM node:18.18.2-alpine3.18 AS build",
|
|
182
|
+
" WORKDIR /app",
|
|
183
|
+
" # 依赖层缓存(package.json 变化才重新安装)",
|
|
184
|
+
" COPY package.json package-lock.json ./",
|
|
185
|
+
" RUN npm ci --omit=dev",
|
|
186
|
+
" # 复制源码并构建",
|
|
187
|
+
" COPY . .",
|
|
188
|
+
" RUN npm run build",
|
|
189
|
+
" ",
|
|
190
|
+
" FROM node:18.18.2-alpine3.18 AS prod",
|
|
191
|
+
" WORKDIR /app",
|
|
192
|
+
" # 只复制生产依赖",
|
|
193
|
+
" COPY --from=build /app/package.json /app/package-lock.json ./",
|
|
194
|
+
" RUN npm ci --omit=dev && npm cache clean --force",
|
|
195
|
+
" COPY --from=build /app/dist ./dist",
|
|
196
|
+
" # 非 root 用户",
|
|
197
|
+
" RUN addgroup -g 1001 -S nodejs && \\",
|
|
198
|
+
" adduser -S appuser -u 1001 -G nodejs",
|
|
199
|
+
" USER appuser",
|
|
200
|
+
" EXPOSE 3000",
|
|
201
|
+
" HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\",
|
|
202
|
+
" CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1",
|
|
203
|
+
" CMD [\"node\", \"dist/main.js\"]",
|
|
204
|
+
" ```",
|
|
205
|
+
"2. 关键原则:",
|
|
206
|
+
" - 依赖安装放在 `COPY .` 之前,利用层缓存",
|
|
207
|
+
" - build 阶段包含 devDependencies 用于构建",
|
|
208
|
+
" - prod 阶段只安装生产依赖",
|
|
209
|
+
" - 非 root 用户运行(`USER appuser`)",
|
|
210
|
+
" - `HEALTHCHECK` 必须存在",
|
|
211
|
+
" - 使用 `npm ci` 而非 `npm install`(确定性构建)",
|
|
212
|
+
"3. 若项目是 monorepo,使用 `--workspace` 过滤:",
|
|
213
|
+
" ```dockerfile",
|
|
214
|
+
" RUN npm ci --workspace=packages/api --omit=dev",
|
|
215
|
+
" ```",
|
|
216
|
+
"",
|
|
217
|
+
"**产出格式**:",
|
|
218
|
+
"```",
|
|
219
|
+
"file: Dockerfile",
|
|
220
|
+
"stages: [build, prod]",
|
|
221
|
+
"base_image: node:18.18.2-alpine3.18",
|
|
222
|
+
"non_root_user: appuser (1001)",
|
|
223
|
+
"healthcheck: wget http://localhost:3000/health",
|
|
224
|
+
"exposed_port: 3000",
|
|
225
|
+
"```",
|
|
226
|
+
].join("\n"),
|
|
227
|
+
suggestedTools: ["Write", "Read"],
|
|
228
|
+
output: "生成的多阶段 Dockerfile 文件路径",
|
|
229
|
+
depends: ["choose-base-image"],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
id: "create-dockerignore",
|
|
233
|
+
title: "创建 .dockerignore",
|
|
234
|
+
instruction: [
|
|
235
|
+
"## 创建 .dockerignore 排除无用文件",
|
|
236
|
+
"",
|
|
237
|
+
"创建 `.dockerignore` 文件,避免将无用/敏感文件复制到镜像。",
|
|
238
|
+
"",
|
|
239
|
+
"**执行动作**:",
|
|
240
|
+
"1. 创建 `.dockerignore` 文件,内容如下:",
|
|
241
|
+
" ```",
|
|
242
|
+
" # 依赖/构建产物(容器内重新安装)",
|
|
243
|
+
" node_modules",
|
|
244
|
+
" dist",
|
|
245
|
+
" build",
|
|
246
|
+
" .next",
|
|
247
|
+
" .nuxt",
|
|
248
|
+
" ",
|
|
249
|
+
" # VCS 和编辑器",
|
|
250
|
+
" .git",
|
|
251
|
+
" .gitignore",
|
|
252
|
+
" .vscode",
|
|
253
|
+
" .idea",
|
|
254
|
+
" *.swp",
|
|
255
|
+
" ",
|
|
256
|
+
" # Docker 自身配置",
|
|
257
|
+
" Dockerfile",
|
|
258
|
+
" docker-compose*.yml",
|
|
259
|
+
" .dockerignore",
|
|
260
|
+
" ",
|
|
261
|
+
" # 文档/测试/CI",
|
|
262
|
+
" README*",
|
|
263
|
+
" CHANGELOG*",
|
|
264
|
+
" LICENSE",
|
|
265
|
+
" docs/",
|
|
266
|
+
" __tests__/",
|
|
267
|
+
" coverage/",
|
|
268
|
+
" .github/",
|
|
269
|
+
" .gitlab-ci.yml",
|
|
270
|
+
" ",
|
|
271
|
+
" # 环境变量和敏感文件",
|
|
272
|
+
" .env*",
|
|
273
|
+
" *.pem",
|
|
274
|
+
" *.key",
|
|
275
|
+
" secrets/",
|
|
276
|
+
" ```",
|
|
277
|
+
"2. 根据项目类型添加特定条目:",
|
|
278
|
+
" - Python:`__pycache__/`、`*.pyc`、`.venv/`",
|
|
279
|
+
" - Go:`vendor/`(如使用 go modules)",
|
|
280
|
+
" - Java:`target/`、`.gradle/`",
|
|
281
|
+
"3. 验证 `.dockerignore` 是否排除了大文件:",
|
|
282
|
+
" ```bash",
|
|
283
|
+
" du -sh node_modules dist .git 2>/dev/null",
|
|
284
|
+
" ```",
|
|
285
|
+
"",
|
|
286
|
+
"**产出格式**:",
|
|
287
|
+
"```",
|
|
288
|
+
"file: .dockerignore",
|
|
289
|
+
"entries_count: 25",
|
|
290
|
+
"excluded_sizes: { node_modules: '500MB', .git: '120MB', dist: '50MB' }",
|
|
291
|
+
"```",
|
|
292
|
+
].join("\n"),
|
|
293
|
+
suggestedTools: ["Write", "Read"],
|
|
294
|
+
output: "生成的 .dockerignore 文件",
|
|
295
|
+
depends: ["create-dockerfile"],
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
id: "create-compose",
|
|
299
|
+
title: "创建 docker-compose.yml",
|
|
300
|
+
instruction: [
|
|
301
|
+
"## 创建 docker-compose.yml(开发 + 生产 profiles)",
|
|
302
|
+
"",
|
|
303
|
+
"基于 `analyze-project` 发现的数据库/缓存依赖,创建 compose 编排文件。",
|
|
304
|
+
"",
|
|
305
|
+
"**执行动作**:",
|
|
306
|
+
"1. 创建 `docker-compose.yml`,使用 profiles 区分环境:",
|
|
307
|
+
" ```yaml",
|
|
308
|
+
" version: '3.9'",
|
|
309
|
+
" services:",
|
|
310
|
+
" api:",
|
|
311
|
+
" build:",
|
|
312
|
+
" context: .",
|
|
313
|
+
" dockerfile: Dockerfile",
|
|
314
|
+
" ports:",
|
|
315
|
+
" - '${API_PORT:-3000}:3000'",
|
|
316
|
+
" environment:",
|
|
317
|
+
" - DATABASE_URL=postgres://app:secret@db:5432/app",
|
|
318
|
+
" - REDIS_URL=redis://cache:6379",
|
|
319
|
+
" depends_on:",
|
|
320
|
+
" db:",
|
|
321
|
+
" condition: service_healthy",
|
|
322
|
+
" cache:",
|
|
323
|
+
" condition: service_healthy",
|
|
324
|
+
" networks: [backend]",
|
|
325
|
+
" profiles: [dev, staging, prod]",
|
|
326
|
+
" ",
|
|
327
|
+
" db:",
|
|
328
|
+
" image: postgres:16-alpine",
|
|
329
|
+
" environment:",
|
|
330
|
+
" POSTGRES_USER: app",
|
|
331
|
+
" POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}",
|
|
332
|
+
" POSTGRES_DB: app",
|
|
333
|
+
" volumes:",
|
|
334
|
+
" - pgdata:/var/lib/postgresql/data",
|
|
335
|
+
" healthcheck:",
|
|
336
|
+
" test: ['CMD-SHELL', 'pg_isready -U app']",
|
|
337
|
+
" interval: 10s",
|
|
338
|
+
" timeout: 5s",
|
|
339
|
+
" retries: 5",
|
|
340
|
+
" networks: [backend]",
|
|
341
|
+
" profiles: [dev, staging]",
|
|
342
|
+
" ",
|
|
343
|
+
" cache:",
|
|
344
|
+
" image: redis:7-alpine",
|
|
345
|
+
" healthcheck:",
|
|
346
|
+
" test: ['CMD', 'redis-cli', 'ping']",
|
|
347
|
+
" interval: 10s",
|
|
348
|
+
" timeout: 5s",
|
|
349
|
+
" retries: 5",
|
|
350
|
+
" networks: [backend]",
|
|
351
|
+
" profiles: [dev, staging]",
|
|
352
|
+
" ",
|
|
353
|
+
" networks:",
|
|
354
|
+
" backend:",
|
|
355
|
+
" driver: bridge",
|
|
356
|
+
" ",
|
|
357
|
+
" volumes:",
|
|
358
|
+
" pgdata:",
|
|
359
|
+
" ```",
|
|
360
|
+
"2. 创建 `.env.example` 列出所有环境变量:",
|
|
361
|
+
" ```",
|
|
362
|
+
" API_PORT=3000",
|
|
363
|
+
" DB_PASSWORD=changeme",
|
|
364
|
+
" ```",
|
|
365
|
+
"3. 生产环境提示:",
|
|
366
|
+
" - 生产环境数据库使用托管服务(RDS、Cloud SQL)而非 compose 卷",
|
|
367
|
+
" - 使用 `profiles: [prod]` 时不启动本地数据库",
|
|
368
|
+
"",
|
|
369
|
+
"**产出格式**:",
|
|
370
|
+
"```",
|
|
371
|
+
"file: docker-compose.yml",
|
|
372
|
+
"services: [api, db, cache]",
|
|
373
|
+
"networks: [backend]",
|
|
374
|
+
"volumes: [pgdata]",
|
|
375
|
+
"profiles: [dev, staging, prod]",
|
|
376
|
+
"env_example: .env.example",
|
|
377
|
+
"```",
|
|
378
|
+
].join("\n"),
|
|
379
|
+
suggestedTools: ["Write", "Read"],
|
|
380
|
+
output: "生成的 docker-compose.yml 和 .env.example",
|
|
381
|
+
depends: ["create-dockerfile"],
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
id: "build-verify",
|
|
385
|
+
title: "构建镜像并验证容器启动",
|
|
386
|
+
instruction: [
|
|
387
|
+
"## 构建镜像并验证容器启动",
|
|
388
|
+
"",
|
|
389
|
+
"使用 docker compose 构建镜像并启动容器,验证应用可访问。",
|
|
390
|
+
"",
|
|
391
|
+
"**执行动作**:",
|
|
392
|
+
"1. 构建镜像:",
|
|
393
|
+
" ```bash",
|
|
394
|
+
" docker compose build --no-cache",
|
|
395
|
+
" ```",
|
|
396
|
+
"2. 启动服务(后台模式):",
|
|
397
|
+
" ```bash",
|
|
398
|
+
" docker compose up -d --profile dev",
|
|
399
|
+
" ```",
|
|
400
|
+
"3. 等待容器启动并检查状态:",
|
|
401
|
+
" ```bash",
|
|
402
|
+
" sleep 10 && docker compose ps",
|
|
403
|
+
" ```",
|
|
404
|
+
"4. 查看容器日志(若有问题):",
|
|
405
|
+
" ```bash",
|
|
406
|
+
" docker compose logs --tail=50 api",
|
|
407
|
+
" ```",
|
|
408
|
+
"5. 验证端口监听:",
|
|
409
|
+
" ```bash",
|
|
410
|
+
" curl -sf http://localhost:3000/health || echo 'health check failed'",
|
|
411
|
+
" ```",
|
|
412
|
+
"6. 验证镜像大小:",
|
|
413
|
+
" ```bash",
|
|
414
|
+
" docker images --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.Size}}' | grep -E 'api|<none>'",
|
|
415
|
+
" ```",
|
|
416
|
+
"7. 清理:",
|
|
417
|
+
" ```bash",
|
|
418
|
+
" docker compose down",
|
|
419
|
+
" ```",
|
|
420
|
+
"",
|
|
421
|
+
"**产出格式**:",
|
|
422
|
+
"```",
|
|
423
|
+
"build_status: success",
|
|
424
|
+
"image_size: 142MB",
|
|
425
|
+
"container_status: running (healthy)",
|
|
426
|
+
"health_check: http://localhost:3000/health → 200 OK",
|
|
427
|
+
"startup_time: 3.2s",
|
|
428
|
+
"```",
|
|
429
|
+
].join("\n"),
|
|
430
|
+
suggestedTools: ["Bash"],
|
|
431
|
+
output: "镜像构建状态、镜像大小、容器运行状态、健康检查结果",
|
|
432
|
+
depends: ["create-dockerfile", "create-compose"],
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
id: "size-report",
|
|
436
|
+
title: "输出镜像大小和层缓存命中率报告",
|
|
437
|
+
instruction: [
|
|
438
|
+
"## 输出镜像大小和层缓存命中率报告",
|
|
439
|
+
"",
|
|
440
|
+
"分析镜像层结构和大小,生成优化报告。",
|
|
441
|
+
"",
|
|
442
|
+
"**执行动作**:",
|
|
443
|
+
"1. 查看镜像层详情:",
|
|
444
|
+
" ```bash",
|
|
445
|
+
" docker history <image> --format 'table {{.Size}}\\t{{.CreatedBy}}' --no-trunc",
|
|
446
|
+
" ```",
|
|
447
|
+
"2. 使用 `dive` 工具分析(若已安装):",
|
|
448
|
+
" ```bash",
|
|
449
|
+
" dive <image> 2>/dev/null || echo 'dive not installed'",
|
|
450
|
+
" ```",
|
|
451
|
+
"3. 统计各层大小,识别最大层:",
|
|
452
|
+
" ```bash",
|
|
453
|
+
" docker history <image> --format '{{.Size}} {{.CreatedBy}}' | sort -hr | head -10",
|
|
454
|
+
" ```",
|
|
455
|
+
"4. 对比基础镜像大小:",
|
|
456
|
+
" ```bash",
|
|
457
|
+
" docker images node:18.18.2-alpine3.18 --format '{{.Size}}'",
|
|
458
|
+
" ```",
|
|
459
|
+
"5. 检查层缓存命中率(二次构建是否复用):",
|
|
460
|
+
" ```bash",
|
|
461
|
+
" docker compose build 2>&1 | grep -E 'CACHED|DONE|Layer'",
|
|
462
|
+
" ```",
|
|
463
|
+
"",
|
|
464
|
+
"**产出格式**:",
|
|
465
|
+
"```",
|
|
466
|
+
"image: myapp:latest",
|
|
467
|
+
"total_size: 142MB",
|
|
468
|
+
"base_image_size: 50MB",
|
|
469
|
+
"app_layer_size: 92MB",
|
|
470
|
+
"largest_layers:",
|
|
471
|
+
" - 45MB: npm ci (node_modules)",
|
|
472
|
+
" - 30MB: COPY dist",
|
|
473
|
+
" - 17MB: system packages",
|
|
474
|
+
"cache_hit_rate: 85% (on rebuild without source changes)",
|
|
475
|
+
"optimization_suggestions:",
|
|
476
|
+
" - move devDependencies to build stage only",
|
|
477
|
+
" - clean npm cache in same RUN layer",
|
|
478
|
+
"```",
|
|
479
|
+
].join("\n"),
|
|
480
|
+
suggestedTools: ["Bash"],
|
|
481
|
+
output: "镜像总大小、各层大小、缓存命中率、优化建议",
|
|
482
|
+
depends: ["build-verify"],
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
triggers: [{ type: "cli", command: "dockerize" }, { type: "mcp", tool: "dockerize_project" }],
|
|
486
|
+
},
|
|
487
|
+
// ── image-optimize ──
|
|
488
|
+
{
|
|
489
|
+
name: "image-optimize",
|
|
490
|
+
description: "镜像优化:体积分析 → 层优化 → 多阶段重构",
|
|
491
|
+
version: "2.0.0",
|
|
492
|
+
steps: [
|
|
493
|
+
{
|
|
494
|
+
id: "analyze-image",
|
|
495
|
+
title: "分析镜像大小和层结构",
|
|
496
|
+
instruction: [
|
|
497
|
+
"## 分析镜像大小和层结构(docker history)",
|
|
498
|
+
"",
|
|
499
|
+
"使用 docker 命令分析现有镜像的体积和层结构。",
|
|
500
|
+
"",
|
|
501
|
+
"**执行动作**:",
|
|
502
|
+
"1. 查看镜像基本信息:",
|
|
503
|
+
" ```bash",
|
|
504
|
+
" docker images <image> --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.Size}}\\t{{.CreatedAt}}'",
|
|
505
|
+
" ```",
|
|
506
|
+
"2. 列出镜像所有层(按时间倒序):",
|
|
507
|
+
" ```bash",
|
|
508
|
+
" docker history <image> --no-trunc --format 'table {{.Size}}\\t{{.CreatedBy}}'",
|
|
509
|
+
" ```",
|
|
510
|
+
"3. 按大小排序找出最大层:",
|
|
511
|
+
" ```bash",
|
|
512
|
+
" docker history <image> --format '{{.Size}}\\t{{.CreatedBy}}' | sort -hr | head -15",
|
|
513
|
+
" ```",
|
|
514
|
+
"4. 对比基础镜像大小(是否用了 slim/alpine):",
|
|
515
|
+
" ```bash",
|
|
516
|
+
" docker images node:18 --format '{{.Size}}'",
|
|
517
|
+
" docker images node:18-slim --format '{{.Size}}'",
|
|
518
|
+
" docker images node:18-alpine --format '{{.Size}}'",
|
|
519
|
+
" ```",
|
|
520
|
+
"5. 若可用 dive 工具,运行深度分析:",
|
|
521
|
+
" ```bash",
|
|
522
|
+
" dive <image> 2>/dev/null || echo 'install dive: https://github.com/wagoodman/dive'",
|
|
523
|
+
" ```",
|
|
524
|
+
"",
|
|
525
|
+
"**产出格式**:",
|
|
526
|
+
"```",
|
|
527
|
+
"image: myapp:latest",
|
|
528
|
+
"total_size: 850MB",
|
|
529
|
+
"layer_count: 18",
|
|
530
|
+
"base_image: node:18 (350MB) — suboptimal, should use alpine",
|
|
531
|
+
"largest_layers:",
|
|
532
|
+
" - 200MB: npm install (includes devDependencies)",
|
|
533
|
+
" - 150MB: COPY . (includes node_modules and .git)",
|
|
534
|
+
" - 80MB: apt-get install build-essential",
|
|
535
|
+
" - 70MB: system cache (/var/cache/apt)",
|
|
536
|
+
"wasted_estimate: ~500MB",
|
|
537
|
+
"```",
|
|
538
|
+
].join("\n"),
|
|
539
|
+
suggestedTools: ["Bash"],
|
|
540
|
+
output: "镜像总大小、各层大小、基础镜像类型、浪费空间估算",
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
id: "find-fat-layers",
|
|
544
|
+
title: "识别大体积层",
|
|
545
|
+
instruction: [
|
|
546
|
+
"## 识别大体积层(node_modules、缓存文件、不必要依赖)",
|
|
547
|
+
"",
|
|
548
|
+
"定位镜像中浪费空间的具体文件和目录。",
|
|
549
|
+
"",
|
|
550
|
+
"**执行动作**:",
|
|
551
|
+
"1. 创建临时容器并检查文件系统:",
|
|
552
|
+
" ```bash",
|
|
553
|
+
" docker run --rm <image> sh -c 'du -sh /* 2>/dev/null | sort -hr | head -20'",
|
|
554
|
+
" ```",
|
|
555
|
+
"2. 检查是否包含 devDependencies:",
|
|
556
|
+
" ```bash",
|
|
557
|
+
" docker run --rm <image> sh -c 'ls /app/node_modules | wc -l'",
|
|
558
|
+
" docker run --rm <image> sh -c 'cat /app/package.json | grep -A5 devDependencies'",
|
|
559
|
+
" ```",
|
|
560
|
+
"3. 检查是否误打包了 .git、docs、tests:",
|
|
561
|
+
" ```bash",
|
|
562
|
+
" docker run --rm <image> sh -c 'du -sh /app/.git /app/docs /app/__tests__ /app/coverage 2>/dev/null'",
|
|
563
|
+
" ```",
|
|
564
|
+
"4. 检查 apt / npm 缓存:",
|
|
565
|
+
" ```bash",
|
|
566
|
+
" docker run --rm <image> sh -c 'du -sh /var/cache/apt /root/.npm /root/.cache 2>/dev/null'",
|
|
567
|
+
" ```",
|
|
568
|
+
"5. 检查是否有敏感文件:",
|
|
569
|
+
" ```bash",
|
|
570
|
+
" docker run --rm <image> sh -c 'find /app -name \".env*\" -o -name \"*.pem\" -o -name \"*.key\" 2>/dev/null'",
|
|
571
|
+
" ```",
|
|
572
|
+
"",
|
|
573
|
+
"**产出格式**:",
|
|
574
|
+
"```",
|
|
575
|
+
"fat_layers:",
|
|
576
|
+
" - 200MB: /app/node_modules (includes devDependencies like typescript, jest)",
|
|
577
|
+
" - 150MB: /app/.git (should be in .dockerignore)",
|
|
578
|
+
" - 50MB: /var/cache/apt (should be cleaned in same RUN layer)",
|
|
579
|
+
" - 30MB: /app/coverage (test artifacts)",
|
|
580
|
+
" - 20MB: /root/.npm (npm cache)",
|
|
581
|
+
"secrets_leaked:",
|
|
582
|
+
" - /app/.env.production",
|
|
583
|
+
"total_reclaimable: 450MB",
|
|
584
|
+
"```",
|
|
585
|
+
].join("\n"),
|
|
586
|
+
suggestedTools: ["Bash"],
|
|
587
|
+
output: "大体积层列表、可回收空间、泄露的敏感文件",
|
|
588
|
+
depends: ["analyze-image"],
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
id: "optimize-order",
|
|
592
|
+
title: "优化 COPY/RUN 顺序最大化缓存命中",
|
|
593
|
+
instruction: [
|
|
594
|
+
"## 优化 COPY/RUN 顺序最大化缓存命中",
|
|
595
|
+
"",
|
|
596
|
+
"根据 Docker 层缓存机制,调整 Dockerfile 指令顺序。",
|
|
597
|
+
"",
|
|
598
|
+
"**执行动作**:",
|
|
599
|
+
"1. 分析当前 Dockerfile 的层结构:",
|
|
600
|
+
" ```bash",
|
|
601
|
+
" grep -nE '^(FROM|COPY|RUN|ADD)' Dockerfile",
|
|
602
|
+
" ```",
|
|
603
|
+
"2. 应用层缓存优化规则(按变更频率排序):",
|
|
604
|
+
" - 最少变化 → 最多变化",
|
|
605
|
+
" - `FROM` 基础镜像(几乎不变)",
|
|
606
|
+
" - `COPY package.json package-lock.json`(仅依赖变化时重建)",
|
|
607
|
+
" - `RUN npm ci`(依赖安装,慢)",
|
|
608
|
+
" - `COPY tsconfig.json`(配置变化较少)",
|
|
609
|
+
" - `COPY src/`(源码,频繁变化)",
|
|
610
|
+
" - `RUN npm run build`",
|
|
611
|
+
"3. 检查现有顺序是否符合规则:",
|
|
612
|
+
" ```bash",
|
|
613
|
+
" awk '/^COPY|^RUN|^FROM/' Dockerfile",
|
|
614
|
+
" ```",
|
|
615
|
+
"4. 常见错误修复:",
|
|
616
|
+
" - ❌ `COPY . .` 后 `RUN npm install`(源码变化导致重装依赖)",
|
|
617
|
+
" - ✅ `COPY package*.json ./` → `RUN npm ci` → `COPY . .`",
|
|
618
|
+
" - ❌ 多个 `RUN apt-get install` 分层",
|
|
619
|
+
" - ✅ 合并为单个 `RUN apt-get update && apt-get install -y ... && rm -rf /var/lib/apt/lists/*`",
|
|
620
|
+
"",
|
|
621
|
+
"**产出格式**:",
|
|
622
|
+
"```",
|
|
623
|
+
"before_order:",
|
|
624
|
+
" - COPY . . # 每次源码变化触发后续所有层重建",
|
|
625
|
+
" - RUN npm install # 重装依赖(慢)",
|
|
626
|
+
" - RUN npm run build",
|
|
627
|
+
"after_order:",
|
|
628
|
+
" - COPY package*.json ./ # 仅依赖变化时触发",
|
|
629
|
+
" - RUN npm ci # 慢但确定性安装",
|
|
630
|
+
" - COPY . . # 源码变化只触发本层及之后",
|
|
631
|
+
" - RUN npm run build",
|
|
632
|
+
"cache_hit_improvement: ~70% → ~95%",
|
|
633
|
+
"```",
|
|
634
|
+
].join("\n"),
|
|
635
|
+
suggestedTools: ["Read", "Bash"],
|
|
636
|
+
output: "Dockerfile 指令优化顺序、缓存命中率提升估算",
|
|
637
|
+
depends: ["analyze-image"],
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
id: "slim-deps",
|
|
641
|
+
title: "移除生产不需要的 devDependencies 和缓存",
|
|
642
|
+
instruction: [
|
|
643
|
+
"## 移除生产不需要的 devDependencies 和缓存",
|
|
644
|
+
"",
|
|
645
|
+
"识别并剥离生产环境不需要的依赖和构建产物。",
|
|
646
|
+
"",
|
|
647
|
+
"**执行动作**:",
|
|
648
|
+
"1. 列出 devDependencies:",
|
|
649
|
+
" ```bash",
|
|
650
|
+
" node -e \"console.log(Object.keys(require('./package.json').devDependencies || {}).join('\\n'))\"",
|
|
651
|
+
" ```",
|
|
652
|
+
"2. 检查生产依赖是否需要构建:",
|
|
653
|
+
" - TypeScript → 编译为 JS 后不需要 typescript、ts-node",
|
|
654
|
+
" - Jest/Vitest → 测试框架不需要在生产",
|
|
655
|
+
" - ESLint/Prettier → 代码检查不需要",
|
|
656
|
+
"3. 在多阶段构建中,仅在生产阶段安装生产依赖:",
|
|
657
|
+
" ```dockerfile",
|
|
658
|
+
" # 生产阶段",
|
|
659
|
+
" RUN npm ci --omit=dev && npm cache clean --force",
|
|
660
|
+
" ```",
|
|
661
|
+
"4. 清理各种缓存:",
|
|
662
|
+
" ```dockerfile",
|
|
663
|
+
" # Node",
|
|
664
|
+
" RUN npm cache clean --force",
|
|
665
|
+
" # Python",
|
|
666
|
+
" RUN pip cache purge",
|
|
667
|
+
" # apt",
|
|
668
|
+
" RUN apt-get clean && rm -rf /var/lib/apt/lists/*",
|
|
669
|
+
" # yarn",
|
|
670
|
+
" RUN yarn cache clean",
|
|
671
|
+
" ```",
|
|
672
|
+
"5. 使用 `--no-install-recommends` 减少 apt 包:",
|
|
673
|
+
" ```dockerfile",
|
|
674
|
+
" RUN apt-get update && apt-get install -y --no-install-recommends \\",
|
|
675
|
+
" curl \\",
|
|
676
|
+
" && rm -rf /var/lib/apt/lists/*",
|
|
677
|
+
" ```",
|
|
678
|
+
"",
|
|
679
|
+
"**产出格式**:",
|
|
680
|
+
"```",
|
|
681
|
+
"dev_dependencies_removed: [typescript, jest, eslint, prettier, @types/node]",
|
|
682
|
+
"dev_deps_size_saved: 180MB",
|
|
683
|
+
"cache_cleaned: [npm, apt]",
|
|
684
|
+
"cache_size_saved: 50MB",
|
|
685
|
+
"total_savings: 230MB",
|
|
686
|
+
"```",
|
|
687
|
+
].join("\n"),
|
|
688
|
+
suggestedTools: ["Read", "Bash"],
|
|
689
|
+
output: "剥离的 devDependencies 清单、清理的缓存、节省的体积",
|
|
690
|
+
depends: ["find-fat-layers"],
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
id: "refactor-multistage",
|
|
694
|
+
title: "重构为多阶段构建",
|
|
695
|
+
instruction: [
|
|
696
|
+
"## 重构为多阶段构建(build stage + production stage)",
|
|
697
|
+
"",
|
|
698
|
+
"将现有 Dockerfile 重构为多阶段构建,分离构建环境与运行环境。",
|
|
699
|
+
"",
|
|
700
|
+
"**执行动作**:",
|
|
701
|
+
"1. 重写 Dockerfile 使用多阶段:",
|
|
702
|
+
" ```dockerfile",
|
|
703
|
+
" # syntax=docker/dockerfile:1.6",
|
|
704
|
+
" ",
|
|
705
|
+
" # ── 构建阶段 ──",
|
|
706
|
+
" FROM node:18.18.2-alpine3.18 AS build",
|
|
707
|
+
" WORKDIR /app",
|
|
708
|
+
" # 安装所有依赖(含 devDependencies 用于构建)",
|
|
709
|
+
" COPY package.json package-lock.json ./",
|
|
710
|
+
" RUN npm ci",
|
|
711
|
+
" # 复制源码并构建",
|
|
712
|
+
" COPY . .",
|
|
713
|
+
" RUN npm run build",
|
|
714
|
+
" ",
|
|
715
|
+
" # ── 生产阶段 ──",
|
|
716
|
+
" FROM node:18.18.2-alpine3.18 AS prod",
|
|
717
|
+
" WORKDIR /app",
|
|
718
|
+
" # 只复制构建产物",
|
|
719
|
+
" COPY --from=build /app/package.json /app/package-lock.json ./",
|
|
720
|
+
" RUN npm ci --omit=dev && npm cache clean --force",
|
|
721
|
+
" COPY --from=build /app/dist ./dist",
|
|
722
|
+
" # 非 root 用户",
|
|
723
|
+
" RUN addgroup -g 1001 -S nodejs && \\",
|
|
724
|
+
" adduser -S appuser -u 1001 -G nodejs",
|
|
725
|
+
" USER appuser",
|
|
726
|
+
" EXPOSE 3000",
|
|
727
|
+
" CMD [\"node\", \"dist/main.js\"]",
|
|
728
|
+
" ```",
|
|
729
|
+
"2. 多阶段核心原则:",
|
|
730
|
+
" - build 阶段:包含构建所需所有工具(typescript、webpack 等)",
|
|
731
|
+
" - prod 阶段:只包含运行所需文件",
|
|
732
|
+
" - 构建工具不会进入最终镜像",
|
|
733
|
+
"3. 若有原生依赖需要编译(如 sharp、bcrypt),在 build 阶段安装 build 工具:",
|
|
734
|
+
" ```dockerfile",
|
|
735
|
+
" FROM node:18.18.2-alpine3.18 AS build",
|
|
736
|
+
" RUN apk add --no-cache python3 make g++",
|
|
737
|
+
" ```",
|
|
738
|
+
"4. 验证多阶段构建:",
|
|
739
|
+
" ```bash",
|
|
740
|
+
" docker build --target prod -t myapp:slim .",
|
|
741
|
+
" ```",
|
|
742
|
+
"",
|
|
743
|
+
"**产出格式**:",
|
|
744
|
+
"```",
|
|
745
|
+
"stages: [build, prod]",
|
|
746
|
+
"build_image: node:18.18.2-alpine3.18 (includes typescript, build tools)",
|
|
747
|
+
"prod_image: node:18.18.2-alpine3.18 (only runtime)",
|
|
748
|
+
"prod_excludes: [typescript, jest, eslint, build cache, source maps]",
|
|
749
|
+
"estimated_size_reduction: 400MB → 140MB",
|
|
750
|
+
"```",
|
|
751
|
+
].join("\n"),
|
|
752
|
+
suggestedTools: ["Write", "Read"],
|
|
753
|
+
output: "重构后的多阶段 Dockerfile",
|
|
754
|
+
depends: ["optimize-order", "slim-deps"],
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
id: "rebuild-compare",
|
|
758
|
+
title: "重新构建并对比优化前后体积",
|
|
759
|
+
instruction: [
|
|
760
|
+
"## 重新构建并对比优化前后体积",
|
|
761
|
+
"",
|
|
762
|
+
"构建优化后的镜像,与优化前对比体积。",
|
|
763
|
+
"",
|
|
764
|
+
"**执行动作**:",
|
|
765
|
+
"1. 构建优化后的镜像:",
|
|
766
|
+
" ```bash",
|
|
767
|
+
" docker build -t myapp:optimized .",
|
|
768
|
+
" ```",
|
|
769
|
+
"2. 对比新旧镜像大小:",
|
|
770
|
+
" ```bash",
|
|
771
|
+
" docker images --format 'table {{.Repository}}\\t{{.Tag}}\\t{{.Size}}' | grep -E 'myapp|REPOSITORY'",
|
|
772
|
+
" ```",
|
|
773
|
+
"3. 对比层数:",
|
|
774
|
+
" ```bash",
|
|
775
|
+
" docker history myapp:optimized --format '{{.CreatedBy}}' | wc -l",
|
|
776
|
+
" docker history myapp:latest --format '{{.CreatedBy}}' | wc -l",
|
|
777
|
+
" ```",
|
|
778
|
+
"4. 验证镜像可启动:",
|
|
779
|
+
" ```bash",
|
|
780
|
+
" docker run --rm -d --name test myapp:optimized",
|
|
781
|
+
" sleep 5 && docker logs test",
|
|
782
|
+
" docker stop test",
|
|
783
|
+
" ```",
|
|
784
|
+
"5. 生成对比报告:",
|
|
785
|
+
" ```bash",
|
|
786
|
+
" echo \"Before: $(docker inspect myapp:latest --format '{{.Size}}' | awk '{print $1/1024/1024 \"MB\"}')\"",
|
|
787
|
+
" echo \"After: $(docker inspect myapp:optimized --format '{{.Size}}' | awk '{print $1/1024/1024 \"MB\"}')\"",
|
|
788
|
+
" ```",
|
|
789
|
+
"",
|
|
790
|
+
"**产出格式**:",
|
|
791
|
+
"```",
|
|
792
|
+
"before:",
|
|
793
|
+
" image: myapp:latest",
|
|
794
|
+
" size: 850MB",
|
|
795
|
+
" layers: 18",
|
|
796
|
+
"after:",
|
|
797
|
+
" image: myapp:optimized",
|
|
798
|
+
" size: 142MB",
|
|
799
|
+
" layers: 9",
|
|
800
|
+
"reduction: 83% (708MB saved)",
|
|
801
|
+
"build_time: before 120s → after 45s (better caching)",
|
|
802
|
+
"```",
|
|
803
|
+
].join("\n"),
|
|
804
|
+
suggestedTools: ["Bash"],
|
|
805
|
+
output: "优化前后镜像大小对比、层数对比、体积缩减百分比",
|
|
806
|
+
depends: ["refactor-multistage"],
|
|
807
|
+
},
|
|
808
|
+
],
|
|
809
|
+
triggers: [{ type: "cli", command: "optimize:image" }],
|
|
810
|
+
},
|
|
811
|
+
// ── security-scan ──
|
|
812
|
+
{
|
|
813
|
+
name: "security-scan",
|
|
814
|
+
description: "安全扫描:漏洞检测 → 配置审查 → 修复建议",
|
|
815
|
+
version: "2.0.0",
|
|
816
|
+
steps: [
|
|
817
|
+
{
|
|
818
|
+
id: "scan-vulns",
|
|
819
|
+
title: "扫描镜像已知漏洞",
|
|
820
|
+
instruction: [
|
|
821
|
+
"## 扫描镜像已知漏洞(docker scout / trivy)",
|
|
822
|
+
"",
|
|
823
|
+
"使用 docker scout 或 trivy 扫描镜像中的 CVE 漏洞。",
|
|
824
|
+
"",
|
|
825
|
+
"**执行动作**:",
|
|
826
|
+
"1. 优先使用 docker scout(Docker Desktop 内置):",
|
|
827
|
+
" ```bash",
|
|
828
|
+
" docker scout cves <image> 2>&1 | head -50",
|
|
829
|
+
" ```",
|
|
830
|
+
"2. 按严重程度汇总:",
|
|
831
|
+
" ```bash",
|
|
832
|
+
" docker scout cves --summary <image>",
|
|
833
|
+
" ```",
|
|
834
|
+
"3. 若无 docker scout,使用 trivy:",
|
|
835
|
+
" ```bash",
|
|
836
|
+
" trivy image --severity HIGH,CRITICAL <image>",
|
|
837
|
+
" ```",
|
|
838
|
+
"4. 详细输出(含修复建议):",
|
|
839
|
+
" ```bash",
|
|
840
|
+
" docker scout cves --format org.opencontainers.image.selections <image> 2>&1 | head -100",
|
|
841
|
+
" ```",
|
|
842
|
+
"5. 检查是否有官方修复建议:",
|
|
843
|
+
" ```bash",
|
|
844
|
+
" docker scout recommendations <image> 2>&1 | head -30",
|
|
845
|
+
" ```",
|
|
846
|
+
"",
|
|
847
|
+
"**产出格式**:",
|
|
848
|
+
"```",
|
|
849
|
+
"scanner: docker scout / trivy",
|
|
850
|
+
"image: myapp:latest",
|
|
851
|
+
"vulnerabilities:",
|
|
852
|
+
" critical: 2",
|
|
853
|
+
" high: 5",
|
|
854
|
+
" medium: 12",
|
|
855
|
+
" low: 23",
|
|
856
|
+
"top_critical:",
|
|
857
|
+
" - CVE-2024-xxxx: openssl 3.0.8 → 3.0.12 (fix available)",
|
|
858
|
+
" - CVE-2024-yyyy: zlib 1.2.11 → 1.2.13 (fix available)",
|
|
859
|
+
"base_image_cves: 15 (from node:18.18.2-alpine3.18)",
|
|
860
|
+
"app_cves: 27 (from npm dependencies)",
|
|
861
|
+
"```",
|
|
862
|
+
].join("\n"),
|
|
863
|
+
suggestedTools: ["Bash"],
|
|
864
|
+
output: "CVE 漏洞清单(按 Critical/High/Medium/Low 分类)",
|
|
865
|
+
},
|
|
866
|
+
{
|
|
867
|
+
id: "audit-config",
|
|
868
|
+
title: "审查容器配置",
|
|
869
|
+
instruction: [
|
|
870
|
+
"## 审查容器配置(root 用户、特权模式、端口暴露、挂载)",
|
|
871
|
+
"",
|
|
872
|
+
"检查 Dockerfile 和 compose 文件中的不安全配置。",
|
|
873
|
+
"",
|
|
874
|
+
"**执行动作**:",
|
|
875
|
+
"1. 检查是否以 root 用户运行:",
|
|
876
|
+
" ```bash",
|
|
877
|
+
" grep -nE '^USER' Dockerfile",
|
|
878
|
+
" docker run --rm <image> whoami",
|
|
879
|
+
" ```",
|
|
880
|
+
"2. 检查特权模式(compose):",
|
|
881
|
+
" ```bash",
|
|
882
|
+
" grep -nE 'privileged|cap_add|security_opt' docker-compose*.yml",
|
|
883
|
+
" ```",
|
|
884
|
+
"3. 检查端口暴露范围:",
|
|
885
|
+
" ```bash",
|
|
886
|
+
" grep -nE 'ports:' docker-compose*.yml",
|
|
887
|
+
" grep -nE 'EXPOSE' Dockerfile",
|
|
888
|
+
" ```",
|
|
889
|
+
" - 避免绑定到 `0.0.0.0`,应使用 `127.0.0.1:PORT:PORT`",
|
|
890
|
+
"4. 检查卷挂载(避免挂载敏感目录):",
|
|
891
|
+
" ```bash",
|
|
892
|
+
" grep -nE 'volumes:' docker-compose*.yml -A 5",
|
|
893
|
+
" ```",
|
|
894
|
+
"5. 检查 `--read-only` 根文件系统:",
|
|
895
|
+
" ```bash",
|
|
896
|
+
" grep -nE 'read_only' docker-compose*.yml",
|
|
897
|
+
" ```",
|
|
898
|
+
"6. 检查资源限制:",
|
|
899
|
+
" ```bash",
|
|
900
|
+
" grep -nE 'deploy:|resources:|mem_limit|cpus' docker-compose*.yml",
|
|
901
|
+
" ```",
|
|
902
|
+
"",
|
|
903
|
+
"**产出格式**:",
|
|
904
|
+
"```",
|
|
905
|
+
"issues:",
|
|
906
|
+
" - running_as_root: true (no USER directive)",
|
|
907
|
+
" - privileged_mode: false ✓",
|
|
908
|
+
" - port_binding: 0.0.0.0:3000 (should be 127.0.0.1:3000)",
|
|
909
|
+
" - read_only_rootfs: false (should enable)",
|
|
910
|
+
" - resource_limits: not set (should set mem_limit, cpus)",
|
|
911
|
+
" - healthcheck: missing (should add)",
|
|
912
|
+
"risk_level: HIGH",
|
|
913
|
+
"```",
|
|
914
|
+
].join("\n"),
|
|
915
|
+
suggestedTools: ["Read", "Bash"],
|
|
916
|
+
output: "容器配置安全审查清单",
|
|
917
|
+
depends: ["scan-vulns"],
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
id: "check-secrets",
|
|
921
|
+
title: "检查镜像层中是否包含敏感信息",
|
|
922
|
+
instruction: [
|
|
923
|
+
"## 检查镜像层中是否包含敏感信息",
|
|
924
|
+
"",
|
|
925
|
+
"扫描镜像各层,查找泄露的密钥、token、密码等敏感信息。",
|
|
926
|
+
"",
|
|
927
|
+
"**执行动作**:",
|
|
928
|
+
"1. 创建临时容器检查文件系统:",
|
|
929
|
+
" ```bash",
|
|
930
|
+
" docker create --name tmp-scan <image> >/dev/null",
|
|
931
|
+
" docker export tmp-scan | tar -t | grep -iE 'env|secret|key|pem|credentials' | head -20",
|
|
932
|
+
" docker rm tmp-scan >/dev/null",
|
|
933
|
+
" ```",
|
|
934
|
+
"2. 检查 .env 文件是否被打包:",
|
|
935
|
+
" ```bash",
|
|
936
|
+
" docker run --rm <image> sh -c 'find / -maxdepth 4 -name \".env*\" -o -name \"*.env\" 2>/dev/null'",
|
|
937
|
+
" ```",
|
|
938
|
+
"3. 检查 SSH 密钥:",
|
|
939
|
+
" ```bash",
|
|
940
|
+
" docker run --rm <image> sh -c 'find / -maxdepth 4 -name \"id_rsa\" -o -name \"id_ed25519\" -o -name \"*.pem\" 2>/dev/null'",
|
|
941
|
+
" ```",
|
|
942
|
+
"4. 检查 git 配置(可能含 token):",
|
|
943
|
+
" ```bash",
|
|
944
|
+
" docker run --rm <image> sh -c 'cat /root/.gitconfig 2>/dev/null; cat /home/*/.gitconfig 2>/dev/null'",
|
|
945
|
+
" ```",
|
|
946
|
+
"5. 检查镜像层历史命令中是否有敏感信息:",
|
|
947
|
+
" ```bash",
|
|
948
|
+
" docker history --no-trunc <image> | grep -iE 'password|secret|token|api_key|private' | head -10",
|
|
949
|
+
" ```",
|
|
950
|
+
"6. 使用 `dive` 检查各层文件(若已安装):",
|
|
951
|
+
" ```bash",
|
|
952
|
+
" dive <image> 2>/dev/null || echo 'dive not installed'",
|
|
953
|
+
" ```",
|
|
954
|
+
"",
|
|
955
|
+
"**产出格式**:",
|
|
956
|
+
"```",
|
|
957
|
+
"secrets_found:",
|
|
958
|
+
" - /app/.env.production (contains DATABASE_URL, JWT_SECRET)",
|
|
959
|
+
" - /root/.npmrc (contains npm token)",
|
|
960
|
+
"git_history_leaks:",
|
|
961
|
+
" - none detected",
|
|
962
|
+
"risk_level: CRITICAL",
|
|
963
|
+
"remediation:",
|
|
964
|
+
" - add .env* to .dockerignore",
|
|
965
|
+
" - use docker secrets or runtime env injection",
|
|
966
|
+
" - scrub .npmrc (use ENV NPM_TOKEN and build arg)",
|
|
967
|
+
"```",
|
|
968
|
+
].join("\n"),
|
|
969
|
+
suggestedTools: ["Bash"],
|
|
970
|
+
output: "镜像中泄露的敏感信息清单、风险等级、修复建议",
|
|
971
|
+
depends: ["audit-config"],
|
|
972
|
+
},
|
|
973
|
+
{
|
|
974
|
+
id: "check-base-images",
|
|
975
|
+
title: "检查基础镜像是否为官方镜像且版本固定",
|
|
976
|
+
instruction: [
|
|
977
|
+
"## 检查基础镜像是否为官方镜像且版本固定",
|
|
978
|
+
"",
|
|
979
|
+
"审计使用的基础镜像是否符合安全最佳实践。",
|
|
980
|
+
"",
|
|
981
|
+
"**执行动作**:",
|
|
982
|
+
"1. 提取 Dockerfile 中所有 FROM 指令:",
|
|
983
|
+
" ```bash",
|
|
984
|
+
" grep -nE '^FROM' Dockerfile*",
|
|
985
|
+
" ```",
|
|
986
|
+
"2. 提取 compose 文件中所有镜像引用:",
|
|
987
|
+
" ```bash",
|
|
988
|
+
" grep -nE 'image:' docker-compose*.yml",
|
|
989
|
+
" ```",
|
|
990
|
+
"3. 检查是否使用 `latest` 或未固定版本:",
|
|
991
|
+
" ```bash",
|
|
992
|
+
" grep -nE '^FROM' Dockerfile* | grep -E 'latest|:[^0-9]|:$'",
|
|
993
|
+
" ```",
|
|
994
|
+
"4. 验证是否为官方镜像(Docker Hub 官方标志):",
|
|
995
|
+
" ```bash",
|
|
996
|
+
" # 官方镜像通常在 library/ 命名空间",
|
|
997
|
+
" docker pull <image> && docker inspect <image> --format '{{.RepoTags}} {{.Author}}'",
|
|
998
|
+
" ```",
|
|
999
|
+
"5. 检查镜像签名:",
|
|
1000
|
+
" ```bash",
|
|
1001
|
+
" docker scout cves <image> --only-base 2>&1 | head -20",
|
|
1002
|
+
" ```",
|
|
1003
|
+
"6. 列出所有使用的基础镜像及版本:",
|
|
1004
|
+
"",
|
|
1005
|
+
"**产出格式**:",
|
|
1006
|
+
"```",
|
|
1007
|
+
"base_images:",
|
|
1008
|
+
" - Dockerfile: FROM node:18-alpine ✓ (official, pinned minor)",
|
|
1009
|
+
" - Dockerfile: FROM node:18.18.2-alpine3.18 ✓ (official, fully pinned)",
|
|
1010
|
+
" - compose: postgres:16-alpine ✓",
|
|
1011
|
+
" - compose: redis:7-alpine ✓ (could pin to 7.2.3-alpine)",
|
|
1012
|
+
"issues:",
|
|
1013
|
+
" - ubuntu:latest should be ubuntu:22.04",
|
|
1014
|
+
" - python:3 should be python:3.11.5-slim",
|
|
1015
|
+
"official_status: all official ✓",
|
|
1016
|
+
"pinning_status: 1 untagged, rest pinned",
|
|
1017
|
+
"```",
|
|
1018
|
+
].join("\n"),
|
|
1019
|
+
suggestedTools: ["Read", "Bash"],
|
|
1020
|
+
output: "基础镜像清单、版本固定状态、官方镜像验证",
|
|
1021
|
+
depends: ["check-secrets"],
|
|
1022
|
+
},
|
|
1023
|
+
{ id: "generate-report", stepTemplate: "generate-report", depends: ["scan-vulns", "audit-config", "check-secrets", "check-base-images"] },
|
|
1024
|
+
{
|
|
1025
|
+
id: "apply-fixes",
|
|
1026
|
+
title: "应用安全修复",
|
|
1027
|
+
instruction: [
|
|
1028
|
+
"## 应用安全修复",
|
|
1029
|
+
"",
|
|
1030
|
+
"根据 `generate-report` 中的安全问题,按严重程度逐项修复。",
|
|
1031
|
+
"",
|
|
1032
|
+
"**执行动作**:",
|
|
1033
|
+
"1. **Critical 问题(必须修复)**:",
|
|
1034
|
+
" - 以 root 运行 → 添加非 root 用户:",
|
|
1035
|
+
" ```dockerfile",
|
|
1036
|
+
" RUN addgroup -g 1001 -S nodejs && \\",
|
|
1037
|
+
" adduser -S appuser -u 1001 -G nodejs",
|
|
1038
|
+
" USER appuser",
|
|
1039
|
+
" ```",
|
|
1040
|
+
" - 镜像含敏感文件 → 更新 `.dockerignore`:",
|
|
1041
|
+
" ```",
|
|
1042
|
+
" .env*",
|
|
1043
|
+
" *.pem",
|
|
1044
|
+
" *.key",
|
|
1045
|
+
" .npmrc",
|
|
1046
|
+
" ```",
|
|
1047
|
+
" - 基础镜像有 Critical CVE → 升级到修复版本",
|
|
1048
|
+
"2. **High 问题(强烈建议修复)**:",
|
|
1049
|
+
" - 端口绑定到 `0.0.0.0` → 改为 `127.0.0.1:3000:3000`",
|
|
1050
|
+
" - 缺少资源限制 → 添加 `deploy.resources.limits`:",
|
|
1051
|
+
" ```yaml",
|
|
1052
|
+
" deploy:",
|
|
1053
|
+
" resources:",
|
|
1054
|
+
" limits:",
|
|
1055
|
+
" cpus: '1.0'",
|
|
1056
|
+
" memory: 512M",
|
|
1057
|
+
" ```",
|
|
1058
|
+
" - 无 HEALTHCHECK → 添加 HEALTHCHECK 指令",
|
|
1059
|
+
"3. **Medium/Low 问题(酌情修复)**:",
|
|
1060
|
+
" - 启用 `read_only: true` 根文件系统",
|
|
1061
|
+
" - 删除 `setuid` 二进制:",
|
|
1062
|
+
" ```dockerfile",
|
|
1063
|
+
" RUN find / -perm /6000 -type f -exec chmod a-x {} + 2>/dev/null || true",
|
|
1064
|
+
" ```",
|
|
1065
|
+
"4. 验证每项修复:",
|
|
1066
|
+
" ```bash",
|
|
1067
|
+
" docker build -t myapp:fixed .",
|
|
1068
|
+
" docker run --rm myapp:fixed whoami # should not be root",
|
|
1069
|
+
" ```",
|
|
1070
|
+
"",
|
|
1071
|
+
"**产出格式**:",
|
|
1072
|
+
"```",
|
|
1073
|
+
"fixes_applied:",
|
|
1074
|
+
" - [critical] added non-root user (appuser)",
|
|
1075
|
+
" - [critical] removed .env from image",
|
|
1076
|
+
" - [high] pinned port to 127.0.0.1",
|
|
1077
|
+
" - [high] added memory limit (512M)",
|
|
1078
|
+
" - [medium] enabled read_only rootfs",
|
|
1079
|
+
"remaining_issues:",
|
|
1080
|
+
" - [low] 23 low-severity CVEs in base image (awaiting upstream fix)",
|
|
1081
|
+
"```",
|
|
1082
|
+
].join("\n"),
|
|
1083
|
+
suggestedTools: ["Write", "Read", "Bash"],
|
|
1084
|
+
output: "应用的安全修复清单",
|
|
1085
|
+
depends: ["generate-report"],
|
|
1086
|
+
},
|
|
1087
|
+
{
|
|
1088
|
+
id: "rescan",
|
|
1089
|
+
title: "重新扫描验证漏洞已修复",
|
|
1090
|
+
instruction: [
|
|
1091
|
+
"## 重新扫描验证漏洞已修复",
|
|
1092
|
+
"",
|
|
1093
|
+
"修复完成后,重新运行漏洞扫描验证问题已解决。",
|
|
1094
|
+
"",
|
|
1095
|
+
"**执行动作**:",
|
|
1096
|
+
"1. 重新构建镜像:",
|
|
1097
|
+
" ```bash",
|
|
1098
|
+
" docker build -t myapp:secured .",
|
|
1099
|
+
" ```",
|
|
1100
|
+
"2. 重新扫描漏洞:",
|
|
1101
|
+
" ```bash",
|
|
1102
|
+
" docker scout cves myapp:secured --summary 2>&1",
|
|
1103
|
+
" ```",
|
|
1104
|
+
"3. 对比修复前后:",
|
|
1105
|
+
" ```bash",
|
|
1106
|
+
" docker scout cves myapp:latest --summary 2>&1 > /tmp/before.txt",
|
|
1107
|
+
" docker scout cves myapp:secured --summary 2>&1 > /tmp/after.txt",
|
|
1108
|
+
" diff /tmp/before.txt /tmp/after.txt",
|
|
1109
|
+
" ```",
|
|
1110
|
+
"4. 验证容器以非 root 运行:",
|
|
1111
|
+
" ```bash",
|
|
1112
|
+
" docker run --rm myapp:secured whoami",
|
|
1113
|
+
" ```",
|
|
1114
|
+
"5. 验证无敏感文件泄露:",
|
|
1115
|
+
" ```bash",
|
|
1116
|
+
" docker run --rm myapp:secured sh -c 'find / -maxdepth 4 -name \".env*\" -o -name \"*.pem\" 2>/dev/null'",
|
|
1117
|
+
" ```",
|
|
1118
|
+
"6. 生成最终对比报告:",
|
|
1119
|
+
"",
|
|
1120
|
+
"**产出格式**:",
|
|
1121
|
+
"```",
|
|
1122
|
+
"before:",
|
|
1123
|
+
" critical: 2, high: 5, medium: 12, low: 23",
|
|
1124
|
+
"after:",
|
|
1125
|
+
" critical: 0, high: 1, medium: 8, low: 20",
|
|
1126
|
+
"reduction: 100% critical, 80% high, 33% medium",
|
|
1127
|
+
"non_root_user: verified (appuser)",
|
|
1128
|
+
"secrets_leaked: none ✓",
|
|
1129
|
+
"status: PASS",
|
|
1130
|
+
"```",
|
|
1131
|
+
].join("\n"),
|
|
1132
|
+
suggestedTools: ["Bash"],
|
|
1133
|
+
output: "修复前后漏洞对比、验证结果",
|
|
1134
|
+
depends: ["apply-fixes"],
|
|
1135
|
+
},
|
|
1136
|
+
],
|
|
1137
|
+
triggers: [{ type: "cli", command: "scan:security" }],
|
|
1138
|
+
},
|
|
1139
|
+
// ── compose-setup ──
|
|
1140
|
+
{
|
|
1141
|
+
name: "compose-setup",
|
|
1142
|
+
description: "多服务 Compose 编排:依赖分析 → 网络设计 → 环境管理",
|
|
1143
|
+
version: "2.0.0",
|
|
1144
|
+
steps: [
|
|
1145
|
+
{
|
|
1146
|
+
id: "inventory-services",
|
|
1147
|
+
title: "盘点所有服务",
|
|
1148
|
+
instruction: [
|
|
1149
|
+
"## 盘点所有服务(API、数据库、缓存、消息队列、前端)",
|
|
1150
|
+
"",
|
|
1151
|
+
"扫描项目结构和配置文件,列出应用需要的所有服务。",
|
|
1152
|
+
"",
|
|
1153
|
+
"**执行动作**:",
|
|
1154
|
+
"1. 查找现有 compose 文件:",
|
|
1155
|
+
" ```bash",
|
|
1156
|
+
" find . -name 'docker-compose*.yml' -o -name 'compose*.yml' 2>/dev/null | head -10",
|
|
1157
|
+
" ```",
|
|
1158
|
+
"2. 扫描 package.json / requirements.txt / go.mod 查找依赖服务:",
|
|
1159
|
+
" ```bash",
|
|
1160
|
+
" grep -iE 'redis|postgres|mysql|mongo|rabbit|kafka|elastic|memcache' package.json requirements.txt go.mod 2>/dev/null",
|
|
1161
|
+
" ```",
|
|
1162
|
+
"3. 查找代码中连接的外部服务:",
|
|
1163
|
+
" ```bash",
|
|
1164
|
+
" grep -rnE 'REDIS_URL|DATABASE_URL|KAFKA_|RABBITMQ|ELASTIC' src/ --include='*.ts' --include='*.js' --include='*.py' | head -20",
|
|
1165
|
+
" ```",
|
|
1166
|
+
"4. 查找端口配置:",
|
|
1167
|
+
" ```bash",
|
|
1168
|
+
" grep -rnE 'listen|PORT|port.*=' src/ --include='*.ts' --include='*.js' | head -20",
|
|
1169
|
+
" ```",
|
|
1170
|
+
"5. 查找 Dockerfile:",
|
|
1171
|
+
" ```bash",
|
|
1172
|
+
" find . -name 'Dockerfile*' 2>/dev/null | grep -v node_modules | head -10",
|
|
1173
|
+
" ```",
|
|
1174
|
+
"",
|
|
1175
|
+
"**产出格式**:",
|
|
1176
|
+
"```",
|
|
1177
|
+
"services:",
|
|
1178
|
+
" - api: node/nest app (port 3000, has Dockerfile)",
|
|
1179
|
+
" - worker: background jobs (has Dockerfile)",
|
|
1180
|
+
" - web: next.js frontend (port 3001, has Dockerfile)",
|
|
1181
|
+
"data_services:",
|
|
1182
|
+
" - postgres:16 (primary database)",
|
|
1183
|
+
" - redis:7 (cache + sessions)",
|
|
1184
|
+
" - rabbitmq:3-management (job queue)",
|
|
1185
|
+
"env_vars: [DATABASE_URL, REDIS_URL, RABBITMQ_URL, API_URL]",
|
|
1186
|
+
"existing_compose: none",
|
|
1187
|
+
"```",
|
|
1188
|
+
].join("\n"),
|
|
1189
|
+
suggestedTools: ["Bash", "Read"],
|
|
1190
|
+
output: "项目需要的所有服务清单(应用服务 + 数据服务)",
|
|
1191
|
+
},
|
|
1192
|
+
{
|
|
1193
|
+
id: "design-networks",
|
|
1194
|
+
title: "设计服务间网络拓扑和端口映射",
|
|
1195
|
+
instruction: [
|
|
1196
|
+
"## 设计服务间网络拓扑和端口映射",
|
|
1197
|
+
"",
|
|
1198
|
+
"基于 `inventory-services` 的服务清单,设计 Docker 网络拓扑。",
|
|
1199
|
+
"",
|
|
1200
|
+
"**执行动作**:",
|
|
1201
|
+
"1. 根据服务耦合度划分网络:",
|
|
1202
|
+
" - `frontend`:web、nginx(对外暴露端口)",
|
|
1203
|
+
" - `backend`:api、worker(内部通信)",
|
|
1204
|
+
" - `data`:postgres、redis、rabbitmq(仅 backend 可访问)",
|
|
1205
|
+
"2. 端口映射规划:",
|
|
1206
|
+
" - 开发环境:暴露所有端口便于调试",
|
|
1207
|
+
" - web: 3001:3001",
|
|
1208
|
+
" - api: 3000:3000",
|
|
1209
|
+
" - rabbitmq-management: 15672:15672",
|
|
1210
|
+
" - postgres: 5432:5432(可选,仅 dev)",
|
|
1211
|
+
" - 生产环境:只暴露对外服务端口",
|
|
1212
|
+
" - web: 80:80, 443:443",
|
|
1213
|
+
" - 其他服务不暴露(通过内部网络通信)",
|
|
1214
|
+
"3. 创建网络配置:",
|
|
1215
|
+
" ```yaml",
|
|
1216
|
+
" networks:",
|
|
1217
|
+
" frontend:",
|
|
1218
|
+
" driver: bridge",
|
|
1219
|
+
" backend:",
|
|
1220
|
+
" driver: bridge",
|
|
1221
|
+
" internal: true # 不对外暴露",
|
|
1222
|
+
" data:",
|
|
1223
|
+
" driver: bridge",
|
|
1224
|
+
" internal: true",
|
|
1225
|
+
" ```",
|
|
1226
|
+
"4. 服务加入对应网络:",
|
|
1227
|
+
" - api: [frontend, backend]",
|
|
1228
|
+
" - web: [frontend]",
|
|
1229
|
+
" - postgres: [data]",
|
|
1230
|
+
" - redis: [data, backend](worker 需要直接访问)",
|
|
1231
|
+
"",
|
|
1232
|
+
"**产出格式**:",
|
|
1233
|
+
"```",
|
|
1234
|
+
"networks:",
|
|
1235
|
+
" frontend: bridge (public) → web, api, nginx",
|
|
1236
|
+
" backend: bridge (internal) → api, worker, redis",
|
|
1237
|
+
" data: bridge (internal) → postgres, redis, rabbitmq",
|
|
1238
|
+
"port_mapping_dev: [3000, 3001, 5432, 6379, 15672]",
|
|
1239
|
+
"port_mapping_prod: [80, 443]",
|
|
1240
|
+
"```",
|
|
1241
|
+
].join("\n"),
|
|
1242
|
+
suggestedTools: ["Read", "Bash"],
|
|
1243
|
+
output: "网络拓扑设计、端口映射方案",
|
|
1244
|
+
depends: ["inventory-services"],
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
id: "setup-volumes",
|
|
1248
|
+
title: "配置持久化卷",
|
|
1249
|
+
instruction: [
|
|
1250
|
+
"## 配置持久化卷(数据库数据、上传文件、日志)",
|
|
1251
|
+
"",
|
|
1252
|
+
"为需要持久化的数据配置 Docker volumes。",
|
|
1253
|
+
"",
|
|
1254
|
+
"**执行动作**:",
|
|
1255
|
+
"1. 识别需要持久化的数据:",
|
|
1256
|
+
" - 数据库数据:postgres、mysql、mongo 数据目录",
|
|
1257
|
+
" - 上传文件:用户上传的图片、文档",
|
|
1258
|
+
" - 日志:应用日志(若不使用外部日志服务)",
|
|
1259
|
+
" - 缓存:redis 持久化(AOF/RDB,可选)",
|
|
1260
|
+
"2. 配置 named volumes:",
|
|
1261
|
+
" ```yaml",
|
|
1262
|
+
" volumes:",
|
|
1263
|
+
" pgdata:",
|
|
1264
|
+
" driver: local",
|
|
1265
|
+
" uploads:",
|
|
1266
|
+
" driver: local",
|
|
1267
|
+
" redis-data:",
|
|
1268
|
+
" driver: local",
|
|
1269
|
+
" ```",
|
|
1270
|
+
"3. 服务挂载卷:",
|
|
1271
|
+
" ```yaml",
|
|
1272
|
+
" services:",
|
|
1273
|
+
" postgres:",
|
|
1274
|
+
" image: postgres:16-alpine",
|
|
1275
|
+
" volumes:",
|
|
1276
|
+
" - pgdata:/var/lib/postgresql/data",
|
|
1277
|
+
" api:",
|
|
1278
|
+
" volumes:",
|
|
1279
|
+
" - uploads:/app/uploads",
|
|
1280
|
+
" redis:",
|
|
1281
|
+
" volumes:",
|
|
1282
|
+
" - redis-data:/data",
|
|
1283
|
+
" ```",
|
|
1284
|
+
"4. 开发环境可选 bind mount(便于调试):",
|
|
1285
|
+
" ```yaml",
|
|
1286
|
+
" # 只在开发环境挂载源码(通过 profiles)",
|
|
1287
|
+
" api:",
|
|
1288
|
+
" volumes:",
|
|
1289
|
+
" - ./src:/app/src:ro # read-only",
|
|
1290
|
+
" - /app/node_modules # 不覆盖容器内 node_modules",
|
|
1291
|
+
" ```",
|
|
1292
|
+
"5. 卷的备份与清理策略:",
|
|
1293
|
+
" ```bash",
|
|
1294
|
+
" docker volume ls",
|
|
1295
|
+
" docker volume inspect pgdata",
|
|
1296
|
+
" ```",
|
|
1297
|
+
"",
|
|
1298
|
+
"**产出格式**:",
|
|
1299
|
+
"```",
|
|
1300
|
+
"volumes:",
|
|
1301
|
+
" - pgdata: postgres data (/var/lib/postgresql/data)",
|
|
1302
|
+
" - uploads: user uploads (/app/uploads)",
|
|
1303
|
+
" - redis-data: redis persistence (/data)",
|
|
1304
|
+
"dev_bind_mounts:",
|
|
1305
|
+
" - ./src:/app/src:ro (api service)",
|
|
1306
|
+
"backup_strategy: docker volume backup to S3",
|
|
1307
|
+
"```",
|
|
1308
|
+
].join("\n"),
|
|
1309
|
+
suggestedTools: ["Read", "Bash"],
|
|
1310
|
+
output: "持久化卷配置、bind mount 方案",
|
|
1311
|
+
depends: ["inventory-services"],
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
id: "add-healthchecks",
|
|
1315
|
+
title: "为每个服务添加 HEALTHCHECK",
|
|
1316
|
+
instruction: [
|
|
1317
|
+
"## 为每个服务添加 HEALTHCHECK 指令",
|
|
1318
|
+
"",
|
|
1319
|
+
"为 Dockerfile 和 compose 中的每个服务添加健康检查。",
|
|
1320
|
+
"",
|
|
1321
|
+
"**执行动作**:",
|
|
1322
|
+
"1. 对 HTTP 服务(api、web),在 Dockerfile 中添加:",
|
|
1323
|
+
" ```dockerfile",
|
|
1324
|
+
" HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\",
|
|
1325
|
+
" CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1",
|
|
1326
|
+
" ```",
|
|
1327
|
+
" - Alpine 镜像用 `wget`(内置),Debian 镜像用 `curl`",
|
|
1328
|
+
" - 若没有 `/health` 端点,使用 `/` 或添加一个",
|
|
1329
|
+
"2. 对 postgres,使用 `pg_isready`:",
|
|
1330
|
+
" ```yaml",
|
|
1331
|
+
" healthcheck:",
|
|
1332
|
+
" test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-app}']",
|
|
1333
|
+
" interval: 10s",
|
|
1334
|
+
" timeout: 5s",
|
|
1335
|
+
" retries: 5",
|
|
1336
|
+
" start_period: 30s",
|
|
1337
|
+
" ```",
|
|
1338
|
+
"3. 对 redis,使用 `redis-cli ping`:",
|
|
1339
|
+
" ```yaml",
|
|
1340
|
+
" healthcheck:",
|
|
1341
|
+
" test: ['CMD', 'redis-cli', 'ping']",
|
|
1342
|
+
" interval: 10s",
|
|
1343
|
+
" timeout: 5s",
|
|
1344
|
+
" retries: 5",
|
|
1345
|
+
" ```",
|
|
1346
|
+
"4. 对 rabbitmq,使用 `rabbitmq-diagnostics check_port_connectivity`:",
|
|
1347
|
+
" ```yaml",
|
|
1348
|
+
" healthcheck:",
|
|
1349
|
+
" test: ['CMD', 'rabbitmq-diagnostics', '-q', 'ping']",
|
|
1350
|
+
" interval: 15s",
|
|
1351
|
+
" timeout: 10s",
|
|
1352
|
+
" retries: 5",
|
|
1353
|
+
" ```",
|
|
1354
|
+
"5. 在 compose 中使用 `depends_on.condition`:",
|
|
1355
|
+
" ```yaml",
|
|
1356
|
+
" api:",
|
|
1357
|
+
" depends_on:",
|
|
1358
|
+
" postgres:",
|
|
1359
|
+
" condition: service_healthy",
|
|
1360
|
+
" redis:",
|
|
1361
|
+
" condition: service_healthy",
|
|
1362
|
+
" ```",
|
|
1363
|
+
"",
|
|
1364
|
+
"**产出格式**:",
|
|
1365
|
+
"```",
|
|
1366
|
+
"healthchecks:",
|
|
1367
|
+
" - api: wget http://localhost:3000/health (30s interval)",
|
|
1368
|
+
" - postgres: pg_isready (10s interval)",
|
|
1369
|
+
" - redis: redis-cli ping (10s interval)",
|
|
1370
|
+
" - rabbitmq: rabbitmq-diagnostics ping (15s interval)",
|
|
1371
|
+
"depends_on_conditions: all data services use service_healthy",
|
|
1372
|
+
"```",
|
|
1373
|
+
].join("\n"),
|
|
1374
|
+
suggestedTools: ["Write", "Read"],
|
|
1375
|
+
output: "为每个服务配置的 HEALTHCHECK 指令",
|
|
1376
|
+
depends: ["design-networks"],
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
id: "env-profiles",
|
|
1380
|
+
title: "配置 development/staging/production 环境 profiles",
|
|
1381
|
+
instruction: [
|
|
1382
|
+
"## 配置 development/staging/production 环境 profiles",
|
|
1383
|
+
"",
|
|
1384
|
+
"使用 compose profiles 区分不同环境的启动配置。",
|
|
1385
|
+
"",
|
|
1386
|
+
"**执行动作**:",
|
|
1387
|
+
"1. 创建 `.env.development`、`.env.staging`、`.env.production` 文件:",
|
|
1388
|
+
" ```bash",
|
|
1389
|
+
" # .env.development",
|
|
1390
|
+
" NODE_ENV=development",
|
|
1391
|
+
" API_PORT=3000",
|
|
1392
|
+
" LOG_LEVEL=debug",
|
|
1393
|
+
" DB_PASSWORD=dev-password",
|
|
1394
|
+
" ```",
|
|
1395
|
+
" ```bash",
|
|
1396
|
+
" # .env.production",
|
|
1397
|
+
" NODE_ENV=production",
|
|
1398
|
+
" API_PORT=80",
|
|
1399
|
+
" LOG_LEVEL=warn",
|
|
1400
|
+
" DB_PASSWORD=${DB_PASSWORD} # 从 CI/CD 注入",
|
|
1401
|
+
" ```",
|
|
1402
|
+
"2. 在 compose 中为服务分配 profiles:",
|
|
1403
|
+
" ```yaml",
|
|
1404
|
+
" services:",
|
|
1405
|
+
" api:",
|
|
1406
|
+
" profiles: [dev, staging, prod]",
|
|
1407
|
+
" web:",
|
|
1408
|
+
" profiles: [dev, staging, prod]",
|
|
1409
|
+
" postgres:",
|
|
1410
|
+
" profiles: [dev, staging] # prod 使用托管数据库",
|
|
1411
|
+
" redis:",
|
|
1412
|
+
" profiles: [dev, staging] # prod 使用托管 redis",
|
|
1413
|
+
" debug-tools:",
|
|
1414
|
+
" image: nicolaka/netshoot",
|
|
1415
|
+
" profiles: [dev] # 仅开发环境",
|
|
1416
|
+
" ```",
|
|
1417
|
+
"3. 使用 compose override 文件:",
|
|
1418
|
+
" - `docker-compose.yml` — 基础配置(所有环境共用)",
|
|
1419
|
+
" - `docker-compose.override.yml` — 开发环境覆盖(自动加载)",
|
|
1420
|
+
" - `docker-compose.prod.yml` — 生产环境覆盖:",
|
|
1421
|
+
" ```bash",
|
|
1422
|
+
" docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d",
|
|
1423
|
+
" ```",
|
|
1424
|
+
"4. 启动不同环境:",
|
|
1425
|
+
" ```bash",
|
|
1426
|
+
" # 开发环境",
|
|
1427
|
+
" docker compose --profile dev up -d",
|
|
1428
|
+
" # 生产环境(不含本地数据库)",
|
|
1429
|
+
" docker compose --profile prod up -d",
|
|
1430
|
+
" ```",
|
|
1431
|
+
"",
|
|
1432
|
+
"**产出格式**:",
|
|
1433
|
+
"```",
|
|
1434
|
+
"env_files: [.env.development, .env.staging, .env.production]",
|
|
1435
|
+
"profiles:",
|
|
1436
|
+
" dev: [api, web, postgres, redis, debug-tools]",
|
|
1437
|
+
" staging: [api, web, postgres, redis]",
|
|
1438
|
+
" prod: [api, web] (uses managed db/cache)",
|
|
1439
|
+
"override_files: [docker-compose.yml, docker-compose.prod.yml]",
|
|
1440
|
+
"```",
|
|
1441
|
+
].join("\n"),
|
|
1442
|
+
suggestedTools: ["Write", "Read"],
|
|
1443
|
+
output: "环境变量配置、profiles 配置、override 文件",
|
|
1444
|
+
depends: ["design-networks", "setup-volumes"],
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
id: "validate-compose",
|
|
1448
|
+
title: "验证 compose 配置",
|
|
1449
|
+
instruction: [
|
|
1450
|
+
"## docker compose config --quiet 验证配置",
|
|
1451
|
+
"",
|
|
1452
|
+
"验证 compose 配置的语法正确性和可启动性。",
|
|
1453
|
+
"",
|
|
1454
|
+
"**执行动作**:",
|
|
1455
|
+
"1. 语法验证:",
|
|
1456
|
+
" ```bash",
|
|
1457
|
+
" docker compose config --quiet",
|
|
1458
|
+
" ```",
|
|
1459
|
+
" - 若有错误,查看详细信息:",
|
|
1460
|
+
" ```bash",
|
|
1461
|
+
" docker compose config 2>&1 | head -20",
|
|
1462
|
+
" ```",
|
|
1463
|
+
"2. 列出所有配置的服务:",
|
|
1464
|
+
" ```bash",
|
|
1465
|
+
" docker compose config --services",
|
|
1466
|
+
" ```",
|
|
1467
|
+
"3. 按 profile 列出服务:",
|
|
1468
|
+
" ```bash",
|
|
1469
|
+
" docker compose --profile dev config --services",
|
|
1470
|
+
" docker compose --profile prod config --services",
|
|
1471
|
+
" ```",
|
|
1472
|
+
"4. 验证网络配置:",
|
|
1473
|
+
" ```bash",
|
|
1474
|
+
" docker compose config | grep -A 10 'networks:'",
|
|
1475
|
+
" ```",
|
|
1476
|
+
"5. 验证卷配置:",
|
|
1477
|
+
" ```bash",
|
|
1478
|
+
" docker compose config | grep -A 10 'volumes:'",
|
|
1479
|
+
" ```",
|
|
1480
|
+
"6. 实际启动测试(开发环境):",
|
|
1481
|
+
" ```bash",
|
|
1482
|
+
" docker compose --profile dev up -d",
|
|
1483
|
+
" sleep 15 && docker compose ps",
|
|
1484
|
+
" docker compose logs --tail=30 2>&1 | grep -iE 'error|fail|warn'",
|
|
1485
|
+
" docker compose down",
|
|
1486
|
+
" ```",
|
|
1487
|
+
"",
|
|
1488
|
+
"**产出格式**:",
|
|
1489
|
+
"```",
|
|
1490
|
+
"validation_status: PASS",
|
|
1491
|
+
"services_validated: [api, web, postgres, redis, rabbitmq]",
|
|
1492
|
+
"profiles_validated: [dev, staging, prod]",
|
|
1493
|
+
"networks: [frontend, backend, data]",
|
|
1494
|
+
"volumes: [pgdata, uploads, redis-data]",
|
|
1495
|
+
"startup_test: all services healthy within 30s",
|
|
1496
|
+
"```",
|
|
1497
|
+
].join("\n"),
|
|
1498
|
+
suggestedTools: ["Bash"],
|
|
1499
|
+
output: "compose 配置验证结果",
|
|
1500
|
+
depends: ["env-profiles", "add-healthchecks"],
|
|
1501
|
+
},
|
|
1502
|
+
],
|
|
1503
|
+
triggers: [{ type: "cli", command: "setup:compose" }],
|
|
1504
|
+
},
|
|
1505
|
+
],
|
|
1506
|
+
},
|
|
1507
|
+
prompt: {
|
|
1508
|
+
system: "你是一个 Docker 专家。使用多阶段构建优化镜像,遵循安全和性能最佳实践。遇到问题先查官方文档。",
|
|
1509
|
+
rules: [
|
|
1510
|
+
"使用多阶段构建减小镜像体积",
|
|
1511
|
+
"基础镜像固定版本标签(不使用 latest)",
|
|
1512
|
+
"利用层缓存优化构建顺序",
|
|
1513
|
+
"使用非 root 用户运行应用",
|
|
1514
|
+
"使用 .dockerignore 排除无用文件",
|
|
1515
|
+
"添加 HEALTHCHECK 监控容器健康状态",
|
|
1516
|
+
"不在镜像层中写入敏感信息",
|
|
1517
|
+
"修复安全问题时先查 Docker 官方文档确认方案",
|
|
1518
|
+
],
|
|
1519
|
+
},
|
|
1520
|
+
tools: [
|
|
1521
|
+
{
|
|
1522
|
+
name: "docker_dockerize_project",
|
|
1523
|
+
description: "项目 Docker 化:分析项目 → 多阶段 Dockerfile → Compose → 构建验证",
|
|
1524
|
+
inputSchema: { type: "object", properties: { projectRoot: { type: "string" } }, required: ["projectRoot"] },
|
|
1525
|
+
outputSchema: structuredOutputSchema,
|
|
1526
|
+
annotations: readOnlyAnnotations,
|
|
1527
|
+
handler: async (input) => { const { dockerize } = await import('./analyzers/dockerize.js'); return dockerize(input.projectRoot); },
|
|
1528
|
+
},
|
|
1529
|
+
],
|
|
1530
|
+
};
|
|
1531
|
+
//# sourceMappingURL=index.js.map
|