speccore 8.3.158 → 8.3.159
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/README.md +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +34 -72
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +0 -13
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +66 -215
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +1 -2
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +1 -4
- package/dist/commands/update.js.map +1 -1
- package/dist/core/agents/defaults/_INDEX.md +15 -15
- package/dist/core/agents/defaults/code-reviewer.md +9 -0
- package/dist/core/agents/defaults/compiler.md +12 -3
- package/dist/core/agents/defaults/dependency-analyst.md +7 -0
- package/dist/core/agents/defaults/doc-sync-agent.md +7 -0
- package/dist/core/agents/defaults/impact-analyst.md +7 -0
- package/dist/core/agents/defaults/interaction-designer.md +17 -0
- package/dist/core/agents/defaults/performance-expert.md +9 -0
- package/dist/core/agents/defaults/regression-tester.md +7 -0
- package/dist/core/agents/defaults/security-reviewer.md +9 -0
- package/dist/core/agents/defaults/test-engineer.md +10 -0
- package/dist/core/agents/defaults/test-reviewer.md +10 -0
- package/dist/core/lock-manager.d.ts.map +1 -1
- package/dist/core/lock-manager.js +2 -0
- package/dist/core/lock-manager.js.map +1 -1
- package/dist/core/rules/defaults/ANALYSIS_QUALITY.md +73 -0
- package/dist/core/rules/defaults/EXECUTION.md +20 -0
- package/dist/core/rules/defaults/ITERATION_QUALITY.md +49 -0
- package/dist/core/rules/defaults/TASK_SPLIT.md +16 -0
- package/dist/core/spec-paths.d.ts.map +1 -1
- package/dist/core/spec-paths.js +2 -1
- package/dist/core/spec-paths.js.map +1 -1
- package/package.json +4 -6
- package/templates/api-design-example.md +0 -338
- package/templates/ci/github-actions.yml +0 -44
- package/templates/dashboard.html +0 -425
- package/templates/database-example.md +0 -223
- package/templates/deploy-docker/README.md +0 -284
- package/templates/deploy-docker/deploy-remote.sh +0 -79
- package/templates/deploy-docker/docker-compose.yml +0 -113
- package/templates/deploy-docker/frontend.Dockerfile +0 -43
- package/templates/deploy-docker/nginx.conf +0 -30
- package/templates/deploy-examples.yaml +0 -436
- package/templates/deploy-java/Dockerfile +0 -50
- package/templates/deploy-java/README.md +0 -212
- package/templates/deploy-java/deploy.sh +0 -120
- package/templates/deploy-java/spring-boot.service +0 -35
- package/templates/html/speccore-ask-explain.html +0 -10
- package/templates/html/speccore-ask-guide.html +0 -10
- package/templates/html/speccore-ask-match.html +0 -10
- package/templates/html/speccore-ask-pipeline.html +0 -1
- package/templates/html/speccore-ask-result.html +0 -10
- package/templates/html/speccore-demo.html +0 -449
- package/templates/html/speccore-dev.html +0 -202
- package/templates/html/speccore-help.html +0 -1
- package/templates/html/speccore-knowledge-graph.html +0 -656
- package/templates/html/speccore-retro-T-001.html +0 -1
- package/templates/html/speccore-setup-guide.html +0 -289
- package/templates/html/speccore-welcome.html +0 -1
- package/templates/security-example.md +0 -226
- package/templates/verify-spec-example.yaml +0 -982
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
# 数据库设计规范示例
|
|
2
|
-
|
|
3
|
-
> 本文件为数据库设计规范示例,涵盖命名、字段、索引、分表等经典规则。
|
|
4
|
-
> 复制到项目后按需修改,或作为 `.speccore/RULES/database.md` 的素材。
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## 1. 命名规范
|
|
9
|
-
|
|
10
|
-
### 1.1 表命名
|
|
11
|
-
|
|
12
|
-
| 规则 | 示例 | 说明 |
|
|
13
|
-
|:---|:---|:---|
|
|
14
|
-
| 小写 + 下划线 | `user_profile` | 全部小写,单词间用 `_` 分隔 |
|
|
15
|
-
| 复数形式 | `orders` `users` | 表名用复数 |
|
|
16
|
-
| 业务前缀 | `oms_order` `cms_article` | 多模块项目加前缀区分 |
|
|
17
|
-
| 禁用保留字 | — | 不要用 `order` `group` `key` 等 SQL 保留字 |
|
|
18
|
-
|
|
19
|
-
### 1.2 字段命名
|
|
20
|
-
|
|
21
|
-
| 规则 | 正例 | 反例 |
|
|
22
|
-
|:---|:---|:---|
|
|
23
|
-
| 小写 + 下划线 | `created_at` | `createdAt` `Created_At` |
|
|
24
|
-
| 外键格式 | `user_id` `order_id` | `uid` `oid` |
|
|
25
|
-
| 布尔字段 | `is_deleted` `is_active` | `deleted` `active` |
|
|
26
|
-
| 状态字段 | `status` + 枚举说明 | `state`(模糊) |
|
|
27
|
-
| 时间字段 | `created_at` `updated_at` | `create_time`(不一致) |
|
|
28
|
-
|
|
29
|
-
### 1.3 索引命名
|
|
30
|
-
|
|
31
|
-
| 类型 | 命名格式 | 示例 |
|
|
32
|
-
|:---|:---|:---|
|
|
33
|
-
| 主键 | `pk_表名` | `pk_users` |
|
|
34
|
-
| 唯一索引 | `uk_表名_字段` | `uk_users_phone` |
|
|
35
|
-
| 普通索引 | `idx_表名_字段` | `idx_orders_user_id` |
|
|
36
|
-
| 联合索引 | `idx_表名_字段1_字段2` | `idx_orders_user_id_status` |
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 2. 字段设计规范
|
|
41
|
-
|
|
42
|
-
### 2.1 必备字段(每张表必须有)
|
|
43
|
-
|
|
44
|
-
| 字段名 | 类型 | 默认值 | 说明 |
|
|
45
|
-
|:---|:---|:---|:---|
|
|
46
|
-
| `id` | `BIGINT UNSIGNED` | 自增 | 主键,建议使用雪花 ID |
|
|
47
|
-
| `created_at` | `DATETIME(3)` | `CURRENT_TIMESTAMP(3)` | 创建时间,毫秒精度 |
|
|
48
|
-
| `updated_at` | `DATETIME(3)` | `CURRENT_TIMESTAMP(3)` | 更新时间,ON UPDATE 自动更新 |
|
|
49
|
-
| `created_by` | `BIGINT UNSIGNED` | `NULL` | 创建人 ID |
|
|
50
|
-
| `updated_by` | `BIGINT UNSIGNED` | `NULL` | 更新人 ID |
|
|
51
|
-
| `deleted_at` | `DATETIME(3)` | `NULL` | 软删除时间,NULL 表示未删除 |
|
|
52
|
-
| `deleted_by` | `BIGINT UNSIGNED` | `NULL` | 删除人 ID |
|
|
53
|
-
| `version` | `INT UNSIGNED` | `0` | 乐观锁版本号 |
|
|
54
|
-
|
|
55
|
-
### 2.2 常用字段类型选择
|
|
56
|
-
|
|
57
|
-
| 场景 | 推荐类型 | 不推荐 | 说明 |
|
|
58
|
-
|:---|:---|:---|:---|
|
|
59
|
-
| 主键 | `BIGINT UNSIGNED` | `INT` | 防止溢出 |
|
|
60
|
-
| 金额 | `BIGINT`(分) | `DECIMAL` `FLOAT` | 整数存储,避免精度问题 |
|
|
61
|
-
| 手机号 | `VARCHAR(20)` | `BIGINT` | 支持国际号码、国家码 |
|
|
62
|
-
| 邮箱 | `VARCHAR(128)` | `TEXT` | 有长度限制,可建索引 |
|
|
63
|
-
| 用户名 | `VARCHAR(64)` | `TEXT` | — |
|
|
64
|
-
| 密码 | `VARCHAR(255)` | `CHAR(32)` | 需兼容 bcrypt 等哈希长度 |
|
|
65
|
-
| 状态枚举 | `TINYINT UNSIGNED` | `VARCHAR` | 节省空间,配合代码枚举 |
|
|
66
|
-
| 大文本 | `TEXT` | `VARCHAR(65535)` | 文章、评论等内容 |
|
|
67
|
-
| JSON 数据 | `JSON` | `TEXT` | MySQL 5.7+ / PostgreSQL 原生支持 |
|
|
68
|
-
| IP 地址 | `VARBINARY(16)` | `VARCHAR(45)` | 兼容 IPv4/IPv6 |
|
|
69
|
-
| 时间戳 | `DATETIME(3)` | `TIMESTAMP` | DATETIME 无时区歧义,范围更大 |
|
|
70
|
-
|
|
71
|
-
### 2.3 字段约束
|
|
72
|
-
|
|
73
|
-
- **NOT NULL 优先:** 尽量不让字段为 NULL,用默认值代替
|
|
74
|
-
- **状态字段必须有注释:** 说明每个值的含义
|
|
75
|
-
- **JSON 字段必须定义结构:** 即使类型是 JSON,也要在文档中定义字段结构
|
|
76
|
-
- **大字段单独表:** TEXT/BLOB 超过 1KB 建议拆到副表
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## 3. 索引设计规范
|
|
81
|
-
|
|
82
|
-
### 3.1 索引原则
|
|
83
|
-
|
|
84
|
-
1. **where 条件字段必建索引** — 特别是高频查询条件
|
|
85
|
-
2. **联合索引最左前缀** — `(a, b, c)` 可以覆盖 `a` `a,b` `a,b,c`,但不能覆盖 `b` `c`
|
|
86
|
-
3. **覆盖索引优先** — 查询字段都在索引中,避免回表
|
|
87
|
-
4. **索引不是越多越好** — 单表索引不超过 5 个,联合索引字段不超过 4 个
|
|
88
|
-
5. **区分度低的字段放前面** — 性别(区分度 2)放前面,创建时间(区分度高)放后面
|
|
89
|
-
6. **冗余索引清理** — `(a)` 和 `(a,b)` 并存时,`(a)` 是冗余的
|
|
90
|
-
|
|
91
|
-
### 3.2 索引示例
|
|
92
|
-
|
|
93
|
-
```sql
|
|
94
|
-
-- 用户表
|
|
95
|
-
CREATE TABLE users (
|
|
96
|
-
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
|
|
97
|
-
phone VARCHAR(20) NOT NULL,
|
|
98
|
-
email VARCHAR(128),
|
|
99
|
-
username VARCHAR(64) NOT NULL,
|
|
100
|
-
status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-正常 2-冻结 3-注销',
|
|
101
|
-
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
102
|
-
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
|
103
|
-
deleted_at DATETIME(3) DEFAULT NULL,
|
|
104
|
-
|
|
105
|
-
UNIQUE KEY uk_users_phone (phone),
|
|
106
|
-
UNIQUE KEY uk_users_email (email),
|
|
107
|
-
UNIQUE KEY uk_users_username (username),
|
|
108
|
-
KEY idx_users_status_created (status, created_at)
|
|
109
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 3.3 索引禁忌
|
|
113
|
-
|
|
114
|
-
- ❌ 不要在低区分度字段上单独建索引(如 `status` 只有 2 个值)
|
|
115
|
-
- ❌ 不要对频繁更新的字段建索引(更新成本 = 数据更新 + 索引更新)
|
|
116
|
-
- ❌ 不要在 WHERE 条件中对字段做函数运算(如 `WHERE DATE(created_at) = '2026-09-10'`)
|
|
117
|
-
- ❌ 不要用 `SELECT *`,只查需要的字段,尽量覆盖索引
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## 4. 分表分库策略
|
|
122
|
-
|
|
123
|
-
### 4.1 何时分表
|
|
124
|
-
|
|
125
|
-
| 条件 | 策略 |
|
|
126
|
-
|:---|:---|
|
|
127
|
-
| 单表数据 > 500 万 | 水平分表 |
|
|
128
|
-
| 单表数据 > 1 亿 | 水平分库 + 分表 |
|
|
129
|
-
| 字段数 > 50 | 垂直拆分(大字段拆副表) |
|
|
130
|
-
| 冷热数据明显 | 归档表(近 3 个月热数据 + 历史归档表) |
|
|
131
|
-
|
|
132
|
-
### 4.2 分表路由键选择
|
|
133
|
-
|
|
134
|
-
| 场景 | 路由键 | 说明 |
|
|
135
|
-
|:---|:---|:---|
|
|
136
|
-
| 用户相关数据 | `user_id` | 按用户维度分片,查询集中在单分片 |
|
|
137
|
-
| 订单数据 | `order_id` 或 `user_id` | 订单号含时间戳可直接路由 |
|
|
138
|
-
| 时间序列数据 | `created_at` | 按时间范围分片,便于归档清理 |
|
|
139
|
-
| 地理位置数据 | `region_code` | 按地区分片,就近访问 |
|
|
140
|
-
|
|
141
|
-
### 4.3 分表示例
|
|
142
|
-
|
|
143
|
-
```sql
|
|
144
|
-
-- 订单表按 user_id % 128 分片
|
|
145
|
-
-- 物理表:order_000 ~ order_127
|
|
146
|
-
-- 路由规则:order_{user_id % 128}
|
|
147
|
-
|
|
148
|
-
CREATE TABLE order_000 (
|
|
149
|
-
id BIGINT UNSIGNED PRIMARY KEY,
|
|
150
|
-
order_no VARCHAR(32) NOT NULL,
|
|
151
|
-
user_id BIGINT UNSIGNED NOT NULL,
|
|
152
|
-
total_amount BIGINT NOT NULL COMMENT '金额(分)',
|
|
153
|
-
status TINYINT UNSIGNED NOT NULL,
|
|
154
|
-
created_at DATETIME(3) NOT NULL,
|
|
155
|
-
|
|
156
|
-
UNIQUE KEY uk_order_no (order_no),
|
|
157
|
-
KEY idx_user_id_created (user_id, created_at)
|
|
158
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## 5. 软删除与数据归档
|
|
164
|
-
|
|
165
|
-
### 5.1 软删除实现
|
|
166
|
-
|
|
167
|
-
```sql
|
|
168
|
-
-- 查询时默认过滤软删除数据
|
|
169
|
-
SELECT * FROM users WHERE deleted_at IS NULL;
|
|
170
|
-
|
|
171
|
-
-- 需要包含已删除数据时显式指定
|
|
172
|
-
SELECT * FROM users WHERE deleted_at IS NOT NULL;
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### 5.2 数据归档策略
|
|
176
|
-
|
|
177
|
-
| 数据类型 | 保留时间 | 归档方式 |
|
|
178
|
-
|:---|:---|:---|
|
|
179
|
-
| 操作日志 | 90 天 | 超过后迁移到归档表或 OSS |
|
|
180
|
-
| 订单数据 | 3 年 | 冷数据归档到历史库 |
|
|
181
|
-
| 系统日志 | 30 天 | ELK 设置过期策略 |
|
|
182
|
-
| 审计日志 | 3 年 | 单独存储,不可删除 |
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
## 6. SQL 编写规范
|
|
187
|
-
|
|
188
|
-
### 6.1 SELECT
|
|
189
|
-
|
|
190
|
-
- 必须指定字段,禁止 `SELECT *`
|
|
191
|
-
- 分页查询必须带 `ORDER BY`,否则结果不稳定
|
|
192
|
-
- 大批量查询使用 `LIMIT + 游标`,避免深分页 `OFFSET 1000000`
|
|
193
|
-
|
|
194
|
-
### 6.2 INSERT/UPDATE/DELETE
|
|
195
|
-
|
|
196
|
-
- INSERT 必须指定字段名:`INSERT INTO t (a, b) VALUES (?, ?)`
|
|
197
|
-
- UPDATE 必须带 WHERE 条件,禁止全表更新
|
|
198
|
-
- DELETE 必须带 WHERE 条件,生产环境建议用软删除代替
|
|
199
|
-
|
|
200
|
-
### 6.3 事务
|
|
201
|
-
|
|
202
|
-
- 事务尽量短,不要在事务中调外部接口
|
|
203
|
-
- 更新多个表时,按相同顺序加锁,避免死锁
|
|
204
|
-
- 批量操作使用 `INSERT ... ON DUPLICATE KEY UPDATE` 或 `REPLACE INTO`
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## 7. 数据库评审清单
|
|
209
|
-
|
|
210
|
-
新建或修改表时必须检查:
|
|
211
|
-
|
|
212
|
-
- [ ] 表名符合命名规范(小写 + 下划线 + 复数)
|
|
213
|
-
- [ ] 包含必备字段(id, created_at, updated_at, deleted_at, version)
|
|
214
|
-
- [ ] 主键使用 BIGINT UNSIGNED
|
|
215
|
-
- [ ] 金额字段用 BIGINT(分)存储
|
|
216
|
-
- [ ] 状态字段有注释说明每个值的含义
|
|
217
|
-
- [ ] 外键字段建立索引
|
|
218
|
-
- [ ] WHERE 条件字段建立索引
|
|
219
|
-
- [ ] 联合索引符合最左前缀原则
|
|
220
|
-
- [ ] 单表索引数量 ≤ 5
|
|
221
|
-
- [ ] 表和字段都有 COMMENT 注释
|
|
222
|
-
- [ ] 字符集使用 utf8mb4
|
|
223
|
-
- [ ] 引擎使用 InnoDB
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
# Docker 部署指南
|
|
2
|
-
|
|
3
|
-
> 本目录提供前后端 Docker 部署的模板和示例,涵盖本地构建、镜像仓库推送、远程服务器拉取运行全流程。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 目录结构
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
deploy-docker/
|
|
11
|
-
├── frontend.Dockerfile # 前端 Nginx 多阶段构建示例
|
|
12
|
-
├── nginx.conf # Nginx 自定义配置(SPA 路由 + API 代理 + 静态缓存)
|
|
13
|
-
├── docker-compose.yml # 前后端 + MySQL + Redis 编排示例
|
|
14
|
-
├── deploy-remote.sh # 服务器端 Docker 部署脚本
|
|
15
|
-
└── README.md # 本文件
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 核心问题解答
|
|
21
|
-
|
|
22
|
-
### Q1: Docker 部署是否需要上传文件?
|
|
23
|
-
|
|
24
|
-
**不需要传统意义上的 SCP 文件上传**,但有三种等价的"文件传输"方式:
|
|
25
|
-
|
|
26
|
-
| 方式 | 说明 | 适用场景 |
|
|
27
|
-
|------|------|----------|
|
|
28
|
-
| **镜像仓库**(推荐) | `docker build` → `docker push` → 远程 `docker pull` | 有私有 registry(Harbor/Nexus/阿里云 ACR) |
|
|
29
|
-
| **docker save + scp** | `docker save` 导出 tar → scp 到服务器 → `docker load` | 无 registry 的内网环境 |
|
|
30
|
-
| **远程 build** | SSH 到服务器,在服务器上 `docker build` | 服务器性能强于本地 |
|
|
31
|
-
|
|
32
|
-
speccore `docker` 类型默认采用**镜像仓库方式**(推荐)。
|
|
33
|
-
|
|
34
|
-
### Q2: 远程服务器上如何部署?
|
|
35
|
-
|
|
36
|
-
speccore `docker` 类型现已支持 `host` 字段,部署流程如下:
|
|
37
|
-
|
|
38
|
-
```yaml
|
|
39
|
-
deploy:
|
|
40
|
-
staging:
|
|
41
|
-
type: docker
|
|
42
|
-
dockerfile: ./Dockerfile
|
|
43
|
-
registry: registry.example.com # 镜像仓库(远程部署必填)
|
|
44
|
-
image: my-project/order-service
|
|
45
|
-
tag: staging
|
|
46
|
-
host: deployer@staging-server.com # 远程服务器(新增支持)
|
|
47
|
-
key: ~/.ssh/id_rsa
|
|
48
|
-
# script: 自定义远程命令(可选,默认执行 pull → stop → rm → run)
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
执行流程:
|
|
52
|
-
1. **本地** `docker build`
|
|
53
|
-
2. **本地** `docker push registry.example.com/my-project/order-service:staging`
|
|
54
|
-
3. **SSH 远程** `docker pull && docker stop && docker rm && docker run`
|
|
55
|
-
|
|
56
|
-
### Q3: 前端 + 后端都有 Docker,怎么一起部署?
|
|
57
|
-
|
|
58
|
-
**方式 A:分别部署(推荐,解耦前后端发布节奏)**
|
|
59
|
-
|
|
60
|
-
```yaml
|
|
61
|
-
# PROJECT.yaml
|
|
62
|
-
platforms:
|
|
63
|
-
- name: admin-web
|
|
64
|
-
type: frontend
|
|
65
|
-
code_path: ./admin-web
|
|
66
|
-
deploy:
|
|
67
|
-
staging:
|
|
68
|
-
type: docker
|
|
69
|
-
dockerfile: ./Dockerfile
|
|
70
|
-
registry: registry.example.com
|
|
71
|
-
image: my-project/admin-web
|
|
72
|
-
tag: staging
|
|
73
|
-
host: deployer@staging-server.com
|
|
74
|
-
key: ~/.ssh/id_rsa
|
|
75
|
-
# 自定义端口映射
|
|
76
|
-
script: "docker pull registry.example.com/my-project/admin-web:staging && docker stop admin-web 2>/dev/null; docker rm admin-web 2>/dev/null; docker run -d --name admin-web --restart always -p 80:80 registry.example.com/my-project/admin-web:staging"
|
|
77
|
-
|
|
78
|
-
- name: order-service
|
|
79
|
-
type: backend
|
|
80
|
-
code_path: ./order-service
|
|
81
|
-
deploy:
|
|
82
|
-
staging:
|
|
83
|
-
type: docker
|
|
84
|
-
dockerfile: ./Dockerfile
|
|
85
|
-
registry: registry.example.com
|
|
86
|
-
image: my-project/order-service
|
|
87
|
-
tag: staging
|
|
88
|
-
host: deployer@staging-server.com
|
|
89
|
-
key: ~/.ssh/id_rsa
|
|
90
|
-
script: "docker pull registry.example.com/my-project/order-service:staging && docker stop order-service 2>/dev/null; docker rm order-service 2>/dev/null; docker run -d --name order-service --restart always -p 8080:8080 registry.example.com/my-project/order-service:staging"
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
分别执行:
|
|
94
|
-
```bash
|
|
95
|
-
speccore deploy --env staging --platform admin-web
|
|
96
|
-
speccore deploy --env staging --platform order-service
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
**方式 B:Docker Compose 统一部署**
|
|
100
|
-
|
|
101
|
-
将 `docker-compose.yml` 放到服务器,speccore 负责 push 镜像,服务器端执行 compose:
|
|
102
|
-
|
|
103
|
-
```yaml
|
|
104
|
-
# PROJECT.yaml
|
|
105
|
-
platforms:
|
|
106
|
-
- name: fullstack
|
|
107
|
-
type: infra
|
|
108
|
-
code_path: ./infra/docker
|
|
109
|
-
deploy:
|
|
110
|
-
staging:
|
|
111
|
-
type: script
|
|
112
|
-
script: ./scripts/deploy-compose.sh
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
# scripts/deploy-compose.sh(在服务器上执行)
|
|
117
|
-
docker-compose -f /opt/deploy/docker-compose.yml pull
|
|
118
|
-
docker-compose -f /opt/deploy/docker-compose.yml up -d
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## 各文件说明
|
|
124
|
-
|
|
125
|
-
### frontend.Dockerfile
|
|
126
|
-
|
|
127
|
-
前端多阶段构建:
|
|
128
|
-
- **阶段 1**(Node):`npm ci && npm run build`
|
|
129
|
-
- **阶段 2**(Nginx):托管 `dist/` 静态资源
|
|
130
|
-
|
|
131
|
-
支持通过 `BUILD_ENV` 构建参数切换环境:
|
|
132
|
-
```bash
|
|
133
|
-
docker build --build-arg BUILD_ENV=staging -t admin-web:staging .
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### nginx.conf
|
|
137
|
-
|
|
138
|
-
- SPA 路由回退(`try_files`)
|
|
139
|
-
- 静态资源长期缓存
|
|
140
|
-
- `/api/` 代理到后端容器
|
|
141
|
-
|
|
142
|
-
### docker-compose.yml
|
|
143
|
-
|
|
144
|
-
完整编排示例,包含:
|
|
145
|
-
- `frontend`(Nginx)
|
|
146
|
-
- `backend`(Spring Boot / Node)
|
|
147
|
-
- `mysql`(数据库,可选)
|
|
148
|
-
- `redis`(缓存,可选)
|
|
149
|
-
|
|
150
|
-
通过 `.env` 文件注入敏感配置:
|
|
151
|
-
```bash
|
|
152
|
-
# .env
|
|
153
|
-
REGISTRY=registry.example.com
|
|
154
|
-
TAG=staging
|
|
155
|
-
PROFILE=staging
|
|
156
|
-
DB_PASSWORD=your-db-pass
|
|
157
|
-
REDIS_PASSWORD=your-redis-pass
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### deploy-remote.sh
|
|
161
|
-
|
|
162
|
-
服务器端容器管理脚本:
|
|
163
|
-
- 拉取最新镜像
|
|
164
|
-
- 停止并删除旧容器
|
|
165
|
-
- 清理旧镜像(保留最近 3 个标签)
|
|
166
|
-
- 启动新容器
|
|
167
|
-
- 状态检查
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## 快速开始
|
|
172
|
-
|
|
173
|
-
### 场景 1:前端 Docker 部署到远程服务器
|
|
174
|
-
|
|
175
|
-
```bash
|
|
176
|
-
# 1. 复制 Dockerfile
|
|
177
|
-
cp templates/deploy-docker/frontend.Dockerfile admin-web/Dockerfile
|
|
178
|
-
cp templates/deploy-docker/nginx.conf admin-web/nginx.conf
|
|
179
|
-
|
|
180
|
-
# 2. 配置 PROJECT.yaml
|
|
181
|
-
# type: docker, host: 服务器地址, registry: 镜像仓库
|
|
182
|
-
|
|
183
|
-
# 3. 部署
|
|
184
|
-
speccore deploy --env staging --platform admin-web
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### 场景 2:后端 Java Docker 部署
|
|
188
|
-
|
|
189
|
-
见 `templates/deploy-java/Dockerfile`(已包含多阶段构建)。
|
|
190
|
-
|
|
191
|
-
### 场景 3:前后端 + 数据库一次性启动
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
# 在服务器上
|
|
195
|
-
scp templates/deploy-docker/docker-compose.yml deployer@server:/opt/deploy/
|
|
196
|
-
scp templates/deploy-docker/.env deployer@server:/opt/deploy/
|
|
197
|
-
|
|
198
|
-
ssh deployer@server "cd /opt/deploy && docker-compose up -d"
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## 数据库 / Redis 配置
|
|
204
|
-
|
|
205
|
-
### 方式 1:独立数据库(推荐生产环境)
|
|
206
|
-
|
|
207
|
-
数据库和 Redis 由运维独立维护,应用通过环境变量连接:
|
|
208
|
-
|
|
209
|
-
```yaml
|
|
210
|
-
# docker-compose.yml 中 backend 的 environment
|
|
211
|
-
- DB_HOST=prod-mysql.internal
|
|
212
|
-
- DB_PORT=3306
|
|
213
|
-
- DB_NAME=order_db
|
|
214
|
-
- DB_USER=order_user
|
|
215
|
-
- DB_PASS=${DB_PASSWORD}
|
|
216
|
-
- REDIS_HOST=prod-redis.internal
|
|
217
|
-
- REDIS_PORT=6379
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### 方式 2:Docker Compose 内置数据库(推荐测试环境)
|
|
221
|
-
|
|
222
|
-
直接使用 `docker-compose.yml` 中的 `mysql` 和 `redis` 服务,应用通过服务名连接:
|
|
223
|
-
|
|
224
|
-
```yaml
|
|
225
|
-
# backend 的 environment
|
|
226
|
-
- DB_HOST=mysql # Docker 网络内服务名即主机名
|
|
227
|
-
- REDIS_HOST=redis
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
### 方式 3:Spring Boot 多环境配置
|
|
231
|
-
|
|
232
|
-
```yaml
|
|
233
|
-
# src/main/resources/application-staging.yml
|
|
234
|
-
spring:
|
|
235
|
-
datasource:
|
|
236
|
-
url: jdbc:mysql://${DB_HOST:mysql}:${DB_PORT:3306}/${DB_NAME:order_db}
|
|
237
|
-
username: ${DB_USER:root}
|
|
238
|
-
password: ${DB_PASS:}
|
|
239
|
-
data:
|
|
240
|
-
redis:
|
|
241
|
-
host: ${REDIS_HOST:redis}
|
|
242
|
-
port: ${REDIS_PORT:6379}
|
|
243
|
-
password: ${REDIS_PASS:}
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
## 常见问题
|
|
249
|
-
|
|
250
|
-
**Q: 没有镜像仓库怎么办?**
|
|
251
|
-
|
|
252
|
-
使用 `docker save + scp + docker load`:
|
|
253
|
-
|
|
254
|
-
```bash
|
|
255
|
-
# 本地
|
|
256
|
-
docker build -t order-service:staging .
|
|
257
|
-
docker save order-service:staging | gzip > order-service-staging.tar.gz
|
|
258
|
-
scp order-service-staging.tar.gz deployer@server:/tmp/
|
|
259
|
-
|
|
260
|
-
# 远程
|
|
261
|
-
ssh deployer@server "gunzip -c /tmp/order-service-staging.tar.gz | docker load"
|
|
262
|
-
ssh deployer@server "docker stop order-service; docker rm order-service; docker run -d --name order-service -p 8080:8080 order-service:staging"
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
或改用 `script` 类型,将上述命令写入脚本由 speccore 执行。
|
|
266
|
-
|
|
267
|
-
**Q: 如何查看远程容器日志?**
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
ssh deployer@server "docker logs -f order-service --tail 100"
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
**Q: 如何回滚?**
|
|
274
|
-
|
|
275
|
-
```bash
|
|
276
|
-
# 重新部署上一个标签
|
|
277
|
-
speccore deploy --env staging --platform order-service --skip-build
|
|
278
|
-
# 然后手动在服务器上 docker run 指定旧标签
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
或保留多个标签版本:
|
|
282
|
-
```bash
|
|
283
|
-
ssh deployer@server "docker stop order-service; docker rm order-service; docker run -d --name order-service order-service:v1.2.3"
|
|
284
|
-
```
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# ═══════════════════════════════════════════════════════════
|
|
3
|
-
# Docker 远程部署脚本(服务器端执行)
|
|
4
|
-
# ═══════════════════════════════════════════════════════════
|
|
5
|
-
#
|
|
6
|
-
# 用法:
|
|
7
|
-
# ./deploy-remote.sh <image> <container-name> [run-args]
|
|
8
|
-
#
|
|
9
|
-
# 示例:
|
|
10
|
-
# ./deploy-remote.sh registry.example.com/order-service:staging order-service "-p 8080:8080 -e SPRING_PROFILES_ACTIVE=staging"
|
|
11
|
-
#
|
|
12
|
-
# 该脚本用于服务器端手动更新容器,也可作为 speccore deploy script 的远程命令。
|
|
13
|
-
# ═══════════════════════════════════════════════════════════
|
|
14
|
-
|
|
15
|
-
set -euo pipefail
|
|
16
|
-
|
|
17
|
-
IMAGE="${1:-}"
|
|
18
|
-
NAME="${2:-}"
|
|
19
|
-
RUN_ARGS="${3:-}"
|
|
20
|
-
|
|
21
|
-
if [ -z "$IMAGE" ] || [ -z "$NAME" ]; then
|
|
22
|
-
echo "用法: $0 <image> <container-name> [run-args]"
|
|
23
|
-
echo "示例: $0 registry.example.com/order-service:staging order-service \"-p 8080:8080\""
|
|
24
|
-
exit 1
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
echo "========================================"
|
|
28
|
-
echo "Docker 远程部署"
|
|
29
|
-
echo "镜像: $IMAGE"
|
|
30
|
-
echo "容器: $NAME"
|
|
31
|
-
echo "========================================"
|
|
32
|
-
|
|
33
|
-
# ── 1. 拉取最新镜像 ──
|
|
34
|
-
echo "📥 拉取镜像..."
|
|
35
|
-
docker pull "$IMAGE"
|
|
36
|
-
|
|
37
|
-
# ── 2. 停止并删除旧容器 ──
|
|
38
|
-
if docker ps -a --format '{{.Names}}' | grep -q "^${NAME}$"; then
|
|
39
|
-
echo "🛑 停止旧容器: $NAME"
|
|
40
|
-
docker stop "$NAME" || true
|
|
41
|
-
echo "🗑️ 删除旧容器: $NAME"
|
|
42
|
-
docker rm "$NAME" || true
|
|
43
|
-
else
|
|
44
|
-
echo "ℹ️ 无旧容器需要清理"
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
# ── 3. 清理旧镜像(保留最近 3 个标签) ──
|
|
48
|
-
echo "🧹 清理旧镜像..."
|
|
49
|
-
IMAGE_BASE=$(echo "$IMAGE" | cut -d: -f1)
|
|
50
|
-
docker images "$IMAGE_BASE" --format '{{.Repository}}:{{.Tag}}' | tail -n +4 | xargs -r docker rmi || true
|
|
51
|
-
|
|
52
|
-
# ── 4. 启动新容器 ──
|
|
53
|
-
echo "🚀 启动新容器..."
|
|
54
|
-
if [ -n "$RUN_ARGS" ]; then
|
|
55
|
-
# shellcheck disable=SC2086
|
|
56
|
-
docker run -d --name "$NAME" --restart always $RUN_ARGS "$IMAGE"
|
|
57
|
-
else
|
|
58
|
-
docker run -d --name "$NAME" --restart always "$IMAGE"
|
|
59
|
-
fi
|
|
60
|
-
|
|
61
|
-
# ── 5. 等待并检查状态 ──
|
|
62
|
-
echo "⏳ 等待容器启动..."
|
|
63
|
-
sleep 3
|
|
64
|
-
|
|
65
|
-
if docker ps --format '{{.Names}}' | grep -q "^${NAME}$"; then
|
|
66
|
-
echo "✅ 容器已启动: $NAME"
|
|
67
|
-
else
|
|
68
|
-
echo "❌ 容器启动失败"
|
|
69
|
-
echo "📋 日志:"
|
|
70
|
-
docker logs "$NAME" --tail 50 || true
|
|
71
|
-
exit 1
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
# ── 6. 显示状态 ──
|
|
75
|
-
echo ""
|
|
76
|
-
echo "========================================"
|
|
77
|
-
echo "📋 部署完成"
|
|
78
|
-
echo "========================================"
|
|
79
|
-
docker ps --filter "name=$NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# ═══════════════════════════════════════════════════════════
|
|
2
|
-
# 前后端 Docker Compose 编排示例
|
|
3
|
-
# ═══════════════════════════════════════════════════════════
|
|
4
|
-
#
|
|
5
|
-
# 适用场景:一台服务器上同时部署前端 + 后端 + 数据库/Redis
|
|
6
|
-
#
|
|
7
|
-
# 用法:
|
|
8
|
-
# 1. 将本文件复制到服务器上的部署目录
|
|
9
|
-
# 2. 配置 .env 文件(数据库密码等敏感信息)
|
|
10
|
-
# 3. 执行: docker-compose up -d
|
|
11
|
-
#
|
|
12
|
-
# 与 speccore deploy 结合:
|
|
13
|
-
# - speccore 负责 build && push 镜像
|
|
14
|
-
# - 服务器端手动或通过 CI 执行 docker-compose pull && up -d
|
|
15
|
-
# - 也可将 docker-compose 作为 speccore 的 script 部署方式执行
|
|
16
|
-
# ═══════════════════════════════════════════════════════════
|
|
17
|
-
|
|
18
|
-
version: "3.8"
|
|
19
|
-
|
|
20
|
-
services:
|
|
21
|
-
# ── 前端 ──
|
|
22
|
-
frontend:
|
|
23
|
-
image: ${REGISTRY:-registry.example.com}/my-project/admin-web:${TAG:-staging}
|
|
24
|
-
container_name: admin-web
|
|
25
|
-
restart: unless-stopped
|
|
26
|
-
ports:
|
|
27
|
-
- "80:80"
|
|
28
|
-
networks:
|
|
29
|
-
- app-network
|
|
30
|
-
depends_on:
|
|
31
|
-
- backend
|
|
32
|
-
healthcheck:
|
|
33
|
-
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/"]
|
|
34
|
-
interval: 30s
|
|
35
|
-
timeout: 3s
|
|
36
|
-
retries: 3
|
|
37
|
-
start_period: 10s
|
|
38
|
-
|
|
39
|
-
# ── 后端 ──
|
|
40
|
-
backend:
|
|
41
|
-
image: ${REGISTRY:-registry.example.com}/my-project/order-service:${TAG:-staging}
|
|
42
|
-
container_name: order-service
|
|
43
|
-
restart: unless-stopped
|
|
44
|
-
ports:
|
|
45
|
-
- "8080:8080"
|
|
46
|
-
environment:
|
|
47
|
-
- SPRING_PROFILES_ACTIVE=${PROFILE:-staging}
|
|
48
|
-
- JAVA_OPTS=-Xms512m -Xmx1024m
|
|
49
|
-
# 数据库连接(建议通过 .env 或 Docker Secrets 注入密码)
|
|
50
|
-
- DB_HOST=mysql
|
|
51
|
-
- DB_PORT=3306
|
|
52
|
-
- DB_NAME=order_db
|
|
53
|
-
- DB_USER=root
|
|
54
|
-
- DB_PASS=${DB_PASSWORD:-secret}
|
|
55
|
-
# Redis 连接
|
|
56
|
-
- REDIS_HOST=redis
|
|
57
|
-
- REDIS_PORT=6379
|
|
58
|
-
- REDIS_PASS=${REDIS_PASSWORD:-}
|
|
59
|
-
networks:
|
|
60
|
-
- app-network
|
|
61
|
-
depends_on:
|
|
62
|
-
mysql:
|
|
63
|
-
condition: service_healthy
|
|
64
|
-
redis:
|
|
65
|
-
condition: service_started
|
|
66
|
-
healthcheck:
|
|
67
|
-
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/actuator/health"]
|
|
68
|
-
interval: 30s
|
|
69
|
-
timeout: 5s
|
|
70
|
-
retries: 5
|
|
71
|
-
start_period: 60s
|
|
72
|
-
|
|
73
|
-
# ── MySQL(如需内置数据库,否则删除此段) ──
|
|
74
|
-
mysql:
|
|
75
|
-
image: mysql:8.0
|
|
76
|
-
container_name: mysql
|
|
77
|
-
restart: unless-stopped
|
|
78
|
-
environment:
|
|
79
|
-
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD:-secret}
|
|
80
|
-
- MYSQL_DATABASE=order_db
|
|
81
|
-
ports:
|
|
82
|
-
- "3306:3306"
|
|
83
|
-
volumes:
|
|
84
|
-
- mysql-data:/var/lib/mysql
|
|
85
|
-
# - ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
|
86
|
-
networks:
|
|
87
|
-
- app-network
|
|
88
|
-
healthcheck:
|
|
89
|
-
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
90
|
-
interval: 10s
|
|
91
|
-
timeout: 5s
|
|
92
|
-
retries: 5
|
|
93
|
-
|
|
94
|
-
# ── Redis(如需内置缓存,否则删除此段) ──
|
|
95
|
-
redis:
|
|
96
|
-
image: redis:7-alpine
|
|
97
|
-
container_name: redis
|
|
98
|
-
restart: unless-stopped
|
|
99
|
-
command: redis-server --requirepass ${REDIS_PASSWORD:-}
|
|
100
|
-
ports:
|
|
101
|
-
- "6379:6379"
|
|
102
|
-
volumes:
|
|
103
|
-
- redis-data:/data
|
|
104
|
-
networks:
|
|
105
|
-
- app-network
|
|
106
|
-
|
|
107
|
-
networks:
|
|
108
|
-
app-network:
|
|
109
|
-
driver: bridge
|
|
110
|
-
|
|
111
|
-
volumes:
|
|
112
|
-
mysql-data:
|
|
113
|
-
redis-data:
|