继续清理不需要文件
This commit is contained in:
@@ -1,256 +0,0 @@
|
||||
# 管理员查询逻辑优化分析报告
|
||||
|
||||
## 📊 优化概述
|
||||
|
||||
本次优化主要针对 `sys_user` 表的管理员查询逻辑进行了全面重构,重点解决了性能瓶颈和查询效率问题。
|
||||
|
||||
## 🔍 原始实现分析
|
||||
|
||||
### 原始代码问题
|
||||
|
||||
**文件位置**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/system/service/impl/SysUserServiceImpl.java`
|
||||
|
||||
#### 1. 管理员判断的性能问题
|
||||
```java
|
||||
// 原始代码 - 性能瓶颈
|
||||
List<SysUser> filteredUsers = allUsers.stream()
|
||||
.filter(user -> {
|
||||
boolean isAdmin = isAdminUser(user.getId()); // ❌ 每个用户都执行一次数据库查询
|
||||
return !isAdmin;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
```
|
||||
|
||||
**问题分析**:
|
||||
- 对每个用户执行 `isAdminUser(user.getId())` 方法
|
||||
- `isAdminUser()` 方法内部执行 `this.getById(userId)` 查询单个用户
|
||||
- **性能影响**: 如果查询100个用户,需要执行101次数据库查询(1次批量查询 + 100次单个查询)
|
||||
|
||||
#### 2. 组织层级查询效率问题
|
||||
```java
|
||||
// 原始代码 - 复杂的递归查询
|
||||
List<SysOrgUnits> descendants = sysOrgUnitsService.listAllDescendants(Collections.singletonList(orgId));
|
||||
List<SysUser> allUsers = baseMapper.getUsersByOrgIds(orgIds);
|
||||
```
|
||||
|
||||
**问题分析**:
|
||||
- 没有使用优化的组织闭包表
|
||||
- 递归查询效率较低
|
||||
- 缺少缓存机制
|
||||
|
||||
## 🚀 优化方案实施
|
||||
|
||||
### 1. 基于 user_type 字段的管理员过滤
|
||||
|
||||
#### 优化前 (N+1 查询问题)
|
||||
```java
|
||||
// 每个用户都要单独查询数据库判断是否管理员
|
||||
.filter(user -> {
|
||||
boolean isAdmin = isAdminUser(user.getId()); // 单独SQL查询
|
||||
return !isAdmin;
|
||||
})
|
||||
```
|
||||
**数据库查询次数**: `1 + N` (N为用户数量)
|
||||
|
||||
#### 优化后 (单次SQL完成)
|
||||
```java
|
||||
// 直接在SQL中过滤,一次查询完成
|
||||
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<SysUser>()
|
||||
.in(SysUser::getOrgId, orgIds)
|
||||
.eq(SysUser::getCustomerId, customerId)
|
||||
.and(wrapper -> wrapper
|
||||
.isNull(SysUser::getUserType) // user_type 为 null
|
||||
.or()
|
||||
.eq(SysUser::getUserType, 0) // 或者 user_type = 0 (普通用户)
|
||||
);
|
||||
```
|
||||
**数据库查询次数**: `1` (仅一次查询)
|
||||
|
||||
### 2. 使用组织闭包表优化层级查询
|
||||
|
||||
#### 优化前
|
||||
```java
|
||||
// 使用递归查询,效率较低
|
||||
List<SysOrgUnits> descendants = sysOrgUnitsService.listAllDescendants(Collections.singletonList(orgId));
|
||||
```
|
||||
|
||||
#### 优化后
|
||||
```java
|
||||
// 使用高效的闭包表,带缓存
|
||||
List<SysOrgUnits> descendants = sysOrgClosureService.findAllDescendants(orgId, customerId);
|
||||
```
|
||||
|
||||
**优势**:
|
||||
- 使用 `sys_org_closure` 闭包表,预计算组织层级关系
|
||||
- 内置 `@Cacheable` 缓存机制
|
||||
- 性能监控和日志记录
|
||||
|
||||
### 3. 接口方法重构
|
||||
|
||||
#### 新增优化的接口方法
|
||||
```java
|
||||
// 核心方法:仅查询普通用户
|
||||
List<SysUser> getUsersByOrgId(Long orgId, Long customerId);
|
||||
|
||||
// 扩展方法:查询所有用户(包含管理员)
|
||||
List<SysUser> getAllUsersByOrgId(Long orgId, Long customerId);
|
||||
|
||||
// 灵活方法:按用户类型查询
|
||||
List<SysUser> getUsersByOrgIdAndUserType(Long orgId, Long customerId, Integer userType);
|
||||
```
|
||||
|
||||
## 📈 性能提升分析
|
||||
|
||||
### 数据库查询次数对比
|
||||
|
||||
| 场景 | 用户数量 | 优化前查询次数 | 优化后查询次数 | 性能提升 |
|
||||
|------|----------|----------------|----------------|----------|
|
||||
| 小型组织 | 10人 | 11次 (1+10) | 1次 | **91%** 减少 |
|
||||
| 中型组织 | 50人 | 51次 (1+50) | 1次 | **98%** 减少 |
|
||||
| 大型组织 | 200人 | 201次 (1+200) | 1次 | **99.5%** 减少 |
|
||||
|
||||
### SQL执行效率对比
|
||||
|
||||
#### 优化前的SQL执行
|
||||
```sql
|
||||
-- 第1次:批量查询用户
|
||||
SELECT * FROM sys_user WHERE org_id IN (1,2,3,4,5);
|
||||
|
||||
-- 第2-N次:逐个查询用户判断管理员身份
|
||||
SELECT * FROM sys_user WHERE id = 1;
|
||||
SELECT * FROM sys_user WHERE id = 2;
|
||||
SELECT * FROM sys_user WHERE id = 3;
|
||||
-- ... 重复N次
|
||||
```
|
||||
|
||||
#### 优化后的SQL执行
|
||||
```sql
|
||||
-- 仅1次:直接过滤查询
|
||||
SELECT * FROM sys_user
|
||||
WHERE org_id IN (1,2,3,4,5)
|
||||
AND customer_id = 123
|
||||
AND (user_type IS NULL OR user_type = 0);
|
||||
```
|
||||
|
||||
### 网络开销分析
|
||||
|
||||
| 指标 | 优化前 | 优化后 | 改善 |
|
||||
|------|-------|-------|------|
|
||||
| 数据库连接次数 | N+1 | 1 | 减少 99%+ |
|
||||
| 网络往返次数 | N+1 | 1 | 减少 99%+ |
|
||||
| 数据传输量 | 高 | 低 | 显著减少 |
|
||||
|
||||
## 🔧 代码质量提升
|
||||
|
||||
### 1. 类型安全和参数校验
|
||||
```java
|
||||
// 添加了完整的异常处理
|
||||
try {
|
||||
// 业务逻辑
|
||||
return users;
|
||||
} catch (Exception e) {
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.error("❌ getUsersByOrgId 执行失败,耗时: {}ms", endTime - startTime, e);
|
||||
throw new BizException("查询组织用户失败: " + e.getMessage());
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 性能监控和日志
|
||||
```java
|
||||
long startTime = System.currentTimeMillis();
|
||||
// ... 业务处理 ...
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("✅ 从数据库查询到的普通用户数量: {}, 耗时: {}ms", users.size(), endTime - startTime);
|
||||
```
|
||||
|
||||
### 3. 清晰的方法职责分离
|
||||
- `getUsersByOrgId()`: 仅查询普通用户
|
||||
- `getAllUsersByOrgId()`: 查询所有用户
|
||||
- `getUsersByOrgIdAndUserType()`: 按类型查询用户
|
||||
|
||||
## 🎯 业务逻辑优化
|
||||
|
||||
### 用户类型定义标准化
|
||||
```java
|
||||
/**
|
||||
* 用户类型枚举
|
||||
* 0 = 普通用户
|
||||
* 1 = 部门管理员
|
||||
* 2 = 租户管理员
|
||||
* 3 = 超级管理员
|
||||
*/
|
||||
```
|
||||
|
||||
### 组织架构查询优化
|
||||
- 利用 `sys_org_closure` 闭包表的预计算优势
|
||||
- 支持缓存机制,减少重复查询
|
||||
- 精确的租户隔离 (`customerId`)
|
||||
|
||||
## ⚡ 预期性能提升
|
||||
|
||||
### 响应时间改善
|
||||
- **小型查询** (10-50用户): 从 200-500ms 降至 10-50ms
|
||||
- **中型查询** (50-200用户): 从 500ms-2s 降至 50-200ms
|
||||
- **大型查询** (200+用户): 从 2s+ 降至 200ms内
|
||||
|
||||
### 数据库负载减轻
|
||||
- 查询频率降低 90%+
|
||||
- 连接池压力显著减少
|
||||
- 并发处理能力大幅提升
|
||||
|
||||
### 内存使用优化
|
||||
- 减少冗余对象创建
|
||||
- 降低 GC 压力
|
||||
- 更高效的数据流处理
|
||||
|
||||
## 🧪 测试建议
|
||||
|
||||
### 1. 功能测试
|
||||
```bash
|
||||
# 测试普通用户查询
|
||||
GET /sys_user/get_users_by_org_id?orgId=1939964806110937090&customerId=0
|
||||
|
||||
# 测试管理员过滤是否正确
|
||||
# 验证返回的用户都是 user_type = 0 或 null
|
||||
```
|
||||
|
||||
### 2. 性能测试
|
||||
- 对比优化前后的响应时间
|
||||
- 监控数据库查询日志
|
||||
- 压力测试并发查询能力
|
||||
|
||||
### 3. 边界条件测试
|
||||
- 空组织测试
|
||||
- 大量用户组织测试
|
||||
- 深层级组织结构测试
|
||||
|
||||
## 📋 部署注意事项
|
||||
|
||||
### 1. 数据库要求
|
||||
确保以下字段和索引存在:
|
||||
```sql
|
||||
-- sys_user 表必需字段
|
||||
ALTER TABLE sys_user ADD COLUMN user_type INT DEFAULT 0 COMMENT '用户类型';
|
||||
ALTER TABLE sys_user ADD COLUMN customer_id BIGINT COMMENT '租户ID';
|
||||
|
||||
-- 性能优化索引
|
||||
CREATE INDEX idx_user_org_customer_type ON sys_user(org_id, customer_id, user_type);
|
||||
CREATE INDEX idx_user_customer_type ON sys_user(customer_id, user_type);
|
||||
```
|
||||
|
||||
### 2. 接口兼容性
|
||||
- 新接口增加了 `customerId` 参数
|
||||
- 前端调用需要相应更新
|
||||
- 建议先保持向后兼容,逐步迁移
|
||||
|
||||
## 🎉 优化总结
|
||||
|
||||
本次管理员查询逻辑优化实现了:
|
||||
|
||||
✅ **性能提升 90%+**: 从N+1查询优化到单次查询
|
||||
✅ **代码质量提升**: 清晰的职责分离和异常处理
|
||||
✅ **可维护性提升**: 标准化的用户类型管理
|
||||
✅ **可扩展性提升**: 灵活的查询接口设计
|
||||
✅ **监控能力提升**: 完整的性能日志和错误追踪
|
||||
|
||||
这次优化不仅解决了当前的性能问题,还为未来的功能扩展奠定了良好的基础。
|
||||
@@ -1,320 +0,0 @@
|
||||
# Ollama AI 健康预测集成指南
|
||||
|
||||
## 概述
|
||||
|
||||
本文档详细介绍了如何在 ljwx-boot 健康管理系统中集成 Ollama AI 模型 `ljwx-health-enhanced:latest` 来实现智能健康预测和建议功能。
|
||||
|
||||
## 架构图
|
||||
|
||||
```
|
||||
前端 (ljwx-admin) 后端 (ljwx-boot) AI模型服务
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ AI模型管理界面 │──→│ THealthPrediction│──→│ Ollama Service │
|
||||
│ /health/ai-models│ │ Controller │ │ :3333 │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ ┌─────────────────┐ │
|
||||
└─────────────→│ OllamaHealth │←─────────────┘
|
||||
│ PredictionService│
|
||||
└─────────────────┘
|
||||
│
|
||||
┌─────────────────┐
|
||||
│ 健康数据查询 │
|
||||
│ UserHealthData │
|
||||
│ HealthBaseline │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. 健康预测 (Health Prediction)
|
||||
- **接口**: `POST /t_health_prediction/ai/predict`
|
||||
- **功能**: 基于用户历史健康数据预测未来趋势
|
||||
- **参数**:
|
||||
- `userId`: 用户ID
|
||||
- `days`: 预测天数 (默认7天)
|
||||
- **返回**: 健康趋势、风险因子、关键指标、置信度等
|
||||
|
||||
### 2. 健康建议 (Health Advice)
|
||||
- **接口**: `POST /t_health_prediction/ai/advice`
|
||||
- **功能**: 生成个性化健康改善建议
|
||||
- **参数**:
|
||||
- `userId`: 用户ID
|
||||
- `healthIssues`: 特定健康问题 (可选)
|
||||
- **返回**: 生活方式建议、风险预防、短期计划、长期目标等
|
||||
|
||||
### 3. 批量预测 (Batch Prediction)
|
||||
- **接口**: `POST /t_health_prediction/ai/batch-predict`
|
||||
- **功能**: 为多个用户批量生成健康预测
|
||||
- **参数**:
|
||||
- `userIds`: 用户ID列表
|
||||
- `days`: 预测天数
|
||||
- **返回**: 用户ID到预测结果的映射
|
||||
|
||||
### 4. 模型管理 (Model Management)
|
||||
- **接口**: `GET /t_health_prediction/ai/models`
|
||||
- **功能**: 获取可用AI模型列表
|
||||
- **接口**: `GET /t_health_prediction/ai/health`
|
||||
- **功能**: 检查AI服务健康状态
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 后端组件
|
||||
|
||||
#### 1. OllamaHealthPredictionService
|
||||
```java
|
||||
@Service
|
||||
public class OllamaHealthPredictionService {
|
||||
|
||||
// 配置参数
|
||||
@Value("${ollama.api.url:http://192.168.1.83:3333}")
|
||||
private String ollamaApiUrl;
|
||||
|
||||
@Value("${ollama.model.name:ljwx-health-enhanced:latest}")
|
||||
private String modelName;
|
||||
|
||||
// 核心方法
|
||||
public HealthPredictionResult generateHealthPrediction(Long userId, Integer days);
|
||||
public HealthAdviceResult generateHealthAdvice(Long userId, List<String> healthIssues);
|
||||
public boolean checkOllamaHealth();
|
||||
public List<String> getAvailableModels();
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 数据收集和处理
|
||||
- **UserHealthContext**: 用户健康数据上下文
|
||||
- **数据源**: UserHealthData (健康数据) + HealthBaseline (健康基线)
|
||||
- **统计计算**: 平均值、范围、趋势分析
|
||||
|
||||
#### 3. AI 提示词构建
|
||||
- 结构化的医学专业提示词
|
||||
- 包含用户基本信息、健康数据统计、基线信息
|
||||
- 要求返回JSON格式的结构化结果
|
||||
|
||||
### 前端组件
|
||||
|
||||
#### 1. AI 模型管理界面
|
||||
- **路径**: `/src/views/health/ai-models/index.vue`
|
||||
- **功能**:
|
||||
- 服务状态监控
|
||||
- 可用模型列表显示
|
||||
- 预测和建议功能测试
|
||||
- 结果可视化展示
|
||||
|
||||
#### 2. API 服务层
|
||||
```typescript
|
||||
// /src/service/api/health/ai-prediction.ts
|
||||
export const aiPredictionApi = {
|
||||
predict: (userId: number, days: number = 7),
|
||||
advice: (userId: number, healthIssues?: string[]),
|
||||
getAvailableModels: (),
|
||||
checkHealth: (),
|
||||
batchPredict: (userIds: number[], days: number = 7)
|
||||
};
|
||||
```
|
||||
|
||||
#### 3. 集成点
|
||||
- 在健康预测页面 (`/health/prediction`) 添加 "AI预测" 按钮
|
||||
- 点击按钮打开模型管理弹窗
|
||||
- 支持实时测试和结果查看
|
||||
|
||||
## 配置文件
|
||||
|
||||
### application.yml
|
||||
```yaml
|
||||
# Ollama 健康预测配置
|
||||
ollama:
|
||||
api:
|
||||
url: ${OLLAMA_API_URL:http://192.168.1.83:3333}
|
||||
model:
|
||||
name: ${OLLAMA_MODEL_NAME:ljwx-health-enhanced:latest}
|
||||
prediction:
|
||||
timeout: ${OLLAMA_PREDICTION_TIMEOUT:30000}
|
||||
connection:
|
||||
timeout: ${OLLAMA_CONNECTION_TIMEOUT:30000}
|
||||
read:
|
||||
timeout: ${OLLAMA_READ_TIMEOUT:60000}
|
||||
```
|
||||
|
||||
### 环境变量支持
|
||||
- `OLLAMA_API_URL`: Ollama 服务地址
|
||||
- `OLLAMA_MODEL_NAME`: 使用的模型名称
|
||||
- `OLLAMA_PREDICTION_TIMEOUT`: 预测超时时间
|
||||
- `OLLAMA_CONNECTION_TIMEOUT`: 连接超时时间
|
||||
- `OLLAMA_READ_TIMEOUT`: 读取超时时间
|
||||
|
||||
## 部署和使用
|
||||
|
||||
### 1. 前置条件
|
||||
- Ollama 服务运行在 `http://192.168.1.83:11434` (标准端口)
|
||||
- 模型 `ljwx-health-enhanced:latest` 已加载 ✅
|
||||
- ljwx-boot 系统正常运行 ✅
|
||||
|
||||
### 2. 启动服务
|
||||
```bash
|
||||
# 启动后端服务
|
||||
cd ljwx-boot
|
||||
./run-local.sh start
|
||||
|
||||
# 启动前端服务
|
||||
cd ljwx-admin
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 3. 访问功能
|
||||
1. 登录 ljwx-admin 管理系统
|
||||
2. 导航到 "健康管理" → "健康预测"
|
||||
3. 点击 "AI预测" 按钮
|
||||
4. 在弹出的模型管理界面中:
|
||||
- 查看服务状态
|
||||
- 测试预测功能
|
||||
- 查看建议结果
|
||||
|
||||
### 4. 快速测试
|
||||
```bash
|
||||
# 运行AI集成测试脚本
|
||||
cd /Users/brunogao/work/codes/917/release
|
||||
./test_ai_integration.sh
|
||||
|
||||
# 手动API测试
|
||||
curl -X GET "http://localhost:9998/t_health_prediction/ai/health"
|
||||
curl -X POST "http://localhost:9998/t_health_prediction/ai/predict?userId=1&days=7"
|
||||
curl -X POST "http://localhost:9998/t_health_prediction/ai/advice?userId=1"
|
||||
|
||||
# 基础测试接口
|
||||
curl -X GET "http://localhost:9998/ai_test/ping"
|
||||
curl -X POST "http://localhost:9998/ai_test/mock-predict?userId=1&days=7"
|
||||
|
||||
# 直接测试Ollama模型
|
||||
curl -X POST http://192.168.1.83:11434/api/generate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model": "ljwx-health-enhanced:latest", "prompt": "你好", "stream": false}'
|
||||
```
|
||||
|
||||
## 数据流程
|
||||
|
||||
### 预测流程
|
||||
1. **数据收集**: 从数据库收集用户最近30天健康数据
|
||||
2. **上下文构建**: 计算统计信息,获取健康基线
|
||||
3. **提示词生成**: 构建医学专业的AI提示词
|
||||
4. **模型调用**: 调用Ollama模型进行推理
|
||||
5. **结果解析**: 解析JSON结果,提取关键信息
|
||||
6. **响应返回**: 返回结构化的预测结果
|
||||
|
||||
### 建议流程
|
||||
1. **健康评估**: 分析用户当前健康状态
|
||||
2. **问题识别**: 识别潜在健康风险和改善点
|
||||
3. **方案生成**: 生成个性化的改善建议
|
||||
4. **计划制定**: 制定短期和长期健康计划
|
||||
5. **优先级排序**: 根据重要性和可行性排序
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 常见错误
|
||||
1. **连接失败**: Ollama服务不可用
|
||||
- 检查服务状态: `curl http://192.168.1.83:3333/api/tags`
|
||||
- 检查网络连接
|
||||
|
||||
2. **模型未找到**: 指定的模型不存在
|
||||
- 确认模型已正确加载
|
||||
- 检查模型名称配置
|
||||
|
||||
3. **数据不足**: 用户健康数据太少
|
||||
- 提示用户需要更多数据
|
||||
- 使用默认建议
|
||||
|
||||
4. **解析失败**: AI返回格式不正确
|
||||
- 使用原始响应作为后备
|
||||
- 记录详细错误日志
|
||||
|
||||
### 日志监控
|
||||
```bash
|
||||
# 查看相关日志
|
||||
tail -f logs/ljwx-boot.log | grep -E "(Ollama|AI|🔮|📝)"
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 1. 缓存策略
|
||||
- 用户健康数据缓存30分钟
|
||||
- 健康基线缓存1小时
|
||||
- AI预测结果缓存6小时
|
||||
|
||||
### 2. 批量处理
|
||||
- 支持批量用户预测
|
||||
- 避免重复数据查询
|
||||
- 并发控制防止过载
|
||||
|
||||
### 3. 超时控制
|
||||
- 连接超时: 30秒
|
||||
- 读取超时: 60秒
|
||||
- 预测超时: 30秒
|
||||
|
||||
## 扩展性
|
||||
|
||||
### 1. 多模型支持
|
||||
- 配置多个AI模型
|
||||
- 模型负载均衡
|
||||
- A/B测试支持
|
||||
|
||||
### 2. 自定义提示词
|
||||
- 可配置的提示词模板
|
||||
- 特定场景的专用提示词
|
||||
- 多语言支持
|
||||
|
||||
### 3. 结果后处理
|
||||
- 医学知识库验证
|
||||
- 建议可行性评估
|
||||
- 个性化调整
|
||||
|
||||
## 安全考虑
|
||||
|
||||
### 1. 数据隐私
|
||||
- 敏感信息脱敏
|
||||
- 最小化数据传输
|
||||
- 访问权限控制
|
||||
|
||||
### 2. API安全
|
||||
- 身份验证和授权
|
||||
- 请求频率限制
|
||||
- 输入参数验证
|
||||
|
||||
### 3. 模型安全
|
||||
- 提示词注入防护
|
||||
- 输出内容检查
|
||||
- 错误信息过滤
|
||||
|
||||
## 维护和监控
|
||||
|
||||
### 1. 健康检查
|
||||
- 定期检查AI服务状态
|
||||
- 监控响应时间和成功率
|
||||
- 自动故障切换
|
||||
|
||||
### 2. 数据质量
|
||||
- 监控预测准确性
|
||||
- 用户反馈收集
|
||||
- 模型效果评估
|
||||
|
||||
### 3. 系统监控
|
||||
- API调用统计
|
||||
- 错误率监控
|
||||
- 性能指标追踪
|
||||
|
||||
## 总结
|
||||
|
||||
本集成实现了 ljwx-boot 健康管理系统与 Ollama AI 模型的深度融合,提供了:
|
||||
|
||||
✅ **完整的API接口**: 支持预测、建议、批量处理等功能
|
||||
✅ **友好的管理界面**: 可视化的模型管理和测试工具
|
||||
✅ **灵活的配置**: 支持环境变量和动态配置
|
||||
✅ **健壮的错误处理**: 完善的异常处理和降级方案
|
||||
✅ **良好的扩展性**: 支持多模型和自定义扩展
|
||||
|
||||
通过这个集成,用户可以:
|
||||
- 获得基于AI的个性化健康预测
|
||||
- 接收智能的健康改善建议
|
||||
- 进行批量的健康风险评估
|
||||
- 实时监控AI服务状态
|
||||
|
||||
这为ljwx健康管理平台增加了强大的AI能力,提升了用户体验和健康管理的智能化水平。
|
||||
@@ -1,151 +0,0 @@
|
||||
# 告警配置多租户三标签页实现总结
|
||||
|
||||
## ✅ 已完成的工作
|
||||
|
||||
### 1. 前端实现 (100% 完成)
|
||||
|
||||
#### 📁 文件结构
|
||||
```
|
||||
ljwx-admin/src/views/alert/config/
|
||||
├── index.vue # ✅ 主页面(三标签页)
|
||||
└── modules/
|
||||
├── alertconfigwechat-search.vue # ✅ 微信配置搜索
|
||||
├── alert-config-wechat-operate-drawer.vue # ✅ 微信配置操作抽屉
|
||||
├── message-config-search.vue # ✅ 消息配置搜索
|
||||
└── message-config-operate-drawer.vue # ✅ 消息配置操作抽屉
|
||||
```
|
||||
|
||||
#### 🎯 功能特性
|
||||
- ✅ 企业微信配置标签页
|
||||
- ✅ 微信公众号配置标签页
|
||||
- ✅ 消息配置标签页(短信/邮件/Webhook/站内消息)
|
||||
- ✅ 完整的CRUD操作(新增、编辑、删除、搜索、分页)
|
||||
- ✅ 多租户支持(通过customer_id过滤)
|
||||
- ✅ 响应式设计
|
||||
- ✅ TypeScript类型安全
|
||||
|
||||
#### 🔧 API服务
|
||||
- ✅ 更新了 `src/service/api/health/alert-config-wechat.ts`
|
||||
- ✅ 新增消息配置相关API接口
|
||||
- ✅ 创建了独立的类型定义文件 `src/typings/api/health/alert-config.d.ts`
|
||||
|
||||
#### 💻 Vue组件特性
|
||||
- ✅ 三标签页架构,每个标签独立管理
|
||||
- ✅ 动态表单(企业微信vs公众号不同字段)
|
||||
- ✅ 计算属性解决v-model条件绑定问题
|
||||
- ✅ 统一使用customerId进行多租户过滤
|
||||
- ✅ 全局组件TableHeaderOperation支持
|
||||
|
||||
### 2. 数据库设计 (100% 完成)
|
||||
|
||||
#### 📊 表结构
|
||||
- ✅ `t_wechat_alert_config` - 微信告警配置表
|
||||
- ✅ `t_message_config` - 消息配置表
|
||||
- ✅ 统一使用 `customer_id` 字段进行多租户支持
|
||||
- ✅ 完整的索引优化
|
||||
- ✅ 示例数据插入
|
||||
|
||||
#### 📜 SQL脚本
|
||||
- ✅ `fix_table_structure_customer_id.sql` - 数据库修复脚本
|
||||
- ✅ 自动创建表结构和示例数据
|
||||
|
||||
## ⚠️ 待完成的工作
|
||||
|
||||
### 后端实现 (需要Spring Boot开发)
|
||||
|
||||
根据错误日志,需要完成以下后端工作:
|
||||
|
||||
#### 1. 微信配置相关
|
||||
- 🔄 修改 `TWechatAlertConfig` 实体类:`tenantId` → `customerId`
|
||||
- 🔄 更新 Mapper XML 查询字段
|
||||
- 🔄 修改 Service 层过滤条件
|
||||
|
||||
#### 2. 消息配置相关
|
||||
- 🔄 创建 `TMessageConfig` 实体类
|
||||
- 🔄 创建 `TMessageConfigMapper`
|
||||
- 🔄 实现 `TMessageConfigService`
|
||||
- 🔄 创建 `TMessageConfigController`
|
||||
|
||||
## 📋 详细修复指南
|
||||
|
||||
已创建完整的后端修复指南:
|
||||
- 📄 `BACKEND_FIX_GUIDE.md` - 包含所有必要的代码修改
|
||||
|
||||
## 🎨 前端页面预览
|
||||
|
||||
访问地址:`http://localhost:3333/alert/config`
|
||||
|
||||
### 标签页功能
|
||||
1. **企业微信配置**
|
||||
- 企业ID、应用ID、应用Secret配置
|
||||
- 模板ID设置
|
||||
- 启用/禁用状态
|
||||
|
||||
2. **微信公众号配置**
|
||||
- AppID、AppSecret配置
|
||||
- 模板ID设置
|
||||
- 启用/禁用状态
|
||||
|
||||
3. **消息配置**
|
||||
- 短信配置:Access Key、Secret Key、模板ID
|
||||
- 邮件配置:SMTP服务器、密码
|
||||
- Webhook配置:请求方法、认证Token
|
||||
- 站内消息配置
|
||||
|
||||
### 操作功能
|
||||
- ✅ 新增配置
|
||||
- ✅ 编辑配置
|
||||
- ✅ 删除配置(单条/批量)
|
||||
- ✅ 条件搜索
|
||||
- ✅ 分页显示
|
||||
- ✅ 多租户数据隔离
|
||||
|
||||
## 🔐 权限设计
|
||||
|
||||
需要配置的权限点:
|
||||
```
|
||||
t:wechat:alarm:config:add # 新增微信配置
|
||||
t:wechat:alarm:config:update # 编辑微信配置
|
||||
t:wechat:alarm:config:delete # 删除微信配置
|
||||
t:message:config:add # 新增消息配置
|
||||
t:message:config:update # 编辑消息配置
|
||||
t:message:config:delete # 删除消息配置
|
||||
```
|
||||
|
||||
## 📈 技术亮点
|
||||
|
||||
### 1. 架构设计
|
||||
- 模块化组件结构
|
||||
- 类型安全的API设计
|
||||
- 多租户数据隔离
|
||||
- 响应式UI布局
|
||||
|
||||
### 2. 用户体验
|
||||
- 直观的标签页界面
|
||||
- 动态表单根据类型显示不同字段
|
||||
- 完整的错误处理和反馈
|
||||
- 移动端适配
|
||||
|
||||
### 3. 代码质量
|
||||
- TypeScript类型定义完整
|
||||
- Vue3 Composition API
|
||||
- ESLint规范检查通过
|
||||
- 计算属性优化性能
|
||||
|
||||
## 🚀 下一步计划
|
||||
|
||||
1. **后端实现** - 根据修复指南完成Spring Boot接口
|
||||
2. **测试验证** - 全功能测试
|
||||
3. **权限配置** - 配置菜单和按钮权限
|
||||
4. **文档完善** - 用户使用说明
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如果在后端实现过程中遇到问题,可以参考:
|
||||
- `BACKEND_FIX_GUIDE.md` - 详细的修复步骤
|
||||
- `fix_table_structure_customer_id.sql` - 数据库脚本
|
||||
- 前端实现的完整代码作为API接口参考
|
||||
|
||||
---
|
||||
|
||||
**总结**:前端实现已100%完成,具备完整的三标签页告警配置管理功能,支持多租户和完整的CRUD操作。后端只需要根据修复指南完成对应的Spring Boot实现即可。
|
||||
@@ -1,233 +0,0 @@
|
||||
# 告警配置多租户三标签页实现方案
|
||||
|
||||
## 项目概述
|
||||
|
||||
为ljwx-admin系统实现了一个全新的告警配置管理页面,支持企业微信、微信公众号、消息配置三个标签页的独立管理,并具备完整的多租户支持。
|
||||
|
||||
## 🎯 功能特性
|
||||
|
||||
### 1. 三标签页架构
|
||||
- **企业微信配置**:管理企业微信告警通知配置
|
||||
- **微信公众号配置**:管理微信公众号告警通知配置
|
||||
- **消息配置**:管理短信、邮件、Webhook、站内消息等通知配置
|
||||
|
||||
### 2. 多租户支持
|
||||
- 所有配置表都支持`customer_id`字段进行租户隔离
|
||||
- 自动根据当前登录用户的`customerId`进行数据过滤
|
||||
- 确保不同租户间的配置完全隔离
|
||||
|
||||
### 3. 完整CRUD操作
|
||||
- 新增配置:支持各种类型的告警配置创建
|
||||
- 编辑配置:可修改现有配置信息
|
||||
- 删除配置:支持单条和批量删除
|
||||
- 查询配置:支持条件搜索和分页
|
||||
|
||||
## 📁 文件结构
|
||||
|
||||
```
|
||||
ljwx-admin/src/views/alert/config/
|
||||
├── index.vue # 主页面(三标签页容器)
|
||||
└── modules/
|
||||
├── alertconfigwechat-search.vue # 微信配置搜索组件
|
||||
├── alert-config-wechat-operate-drawer.vue # 微信配置操作抽屉
|
||||
├── message-config-search.vue # 消息配置搜索组件
|
||||
└── message-config-operate-drawer.vue # 消息配置操作抽屉
|
||||
```
|
||||
|
||||
## 🗄️ 数据库表结构
|
||||
|
||||
### 1. 微信告警配置表 (t_wechat_alarm_config)
|
||||
|
||||
```sql
|
||||
CREATE TABLE `t_wechat_alarm_config` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`tenant_id` bigint NOT NULL COMMENT '租户ID',
|
||||
`customer_id` bigint DEFAULT NULL COMMENT '客户ID(多租户标识)',
|
||||
`type` varchar(20) NOT NULL COMMENT '微信类型: enterprise/official',
|
||||
`corp_id` varchar(100) DEFAULT NULL COMMENT '企业微信企业ID',
|
||||
`agent_id` varchar(50) DEFAULT NULL COMMENT '企业微信应用ID',
|
||||
`secret` varchar(100) DEFAULT NULL COMMENT '企业微信应用Secret',
|
||||
`appid` varchar(100) DEFAULT NULL COMMENT '微信公众号AppID',
|
||||
`appsecret` varchar(100) DEFAULT NULL COMMENT '微信公众号AppSecret',
|
||||
`template_id` varchar(100) DEFAULT NULL COMMENT '微信模板ID',
|
||||
`enabled` tinyint(1) DEFAULT '1' COMMENT '是否启用',
|
||||
-- 标准字段
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_customer_id` (`customer_id`),
|
||||
KEY `idx_type` (`type`)
|
||||
);
|
||||
```
|
||||
|
||||
### 2. 消息配置表 (t_message_config)
|
||||
|
||||
```sql
|
||||
CREATE TABLE `t_message_config` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`customer_id` bigint NOT NULL COMMENT '客户ID(租户ID)',
|
||||
`name` varchar(100) NOT NULL COMMENT '配置名称',
|
||||
`type` varchar(20) NOT NULL COMMENT '消息类型: sms/email/webhook/internal',
|
||||
`endpoint` varchar(500) NOT NULL COMMENT '接收地址',
|
||||
`access_key` varchar(200) DEFAULT NULL COMMENT 'Access Key',
|
||||
`secret_key` varchar(200) DEFAULT NULL COMMENT 'Secret Key',
|
||||
`template_id` varchar(100) DEFAULT NULL COMMENT '模板ID',
|
||||
`enabled` tinyint(1) DEFAULT '1' COMMENT '是否启用',
|
||||
`description` text DEFAULT NULL COMMENT '备注描述',
|
||||
-- 标准字段
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_customer_id` (`customer_id`),
|
||||
KEY `idx_type` (`type`)
|
||||
);
|
||||
```
|
||||
|
||||
## 🔧 API接口设计
|
||||
|
||||
### 微信配置相关接口
|
||||
```typescript
|
||||
// 获取微信配置列表
|
||||
GET /t_wechat_alarm_config/page
|
||||
// 新增微信配置
|
||||
POST /t_wechat_alarm_config/
|
||||
// 更新微信配置
|
||||
PUT /t_wechat_alarm_config/
|
||||
// 删除微信配置
|
||||
DELETE /t_wechat_alarm_config/
|
||||
```
|
||||
|
||||
### 消息配置相关接口
|
||||
```typescript
|
||||
// 获取消息配置列表
|
||||
GET /t_message_config/page
|
||||
// 新增消息配置
|
||||
POST /t_message_config/
|
||||
// 更新消息配置
|
||||
PUT /t_message_config/
|
||||
// 删除消息配置
|
||||
DELETE /t_message_config/
|
||||
```
|
||||
|
||||
## 💻 前端实现要点
|
||||
|
||||
### 1. 三标签页架构
|
||||
```vue
|
||||
<NTabs v-model:value="activeTab" type="line" @update:value="handleTabChange">
|
||||
<NTabPane name="enterprise" tab="企业微信配置">
|
||||
<!-- 企业微信配置表格 -->
|
||||
</NTabPane>
|
||||
<NTabPane name="official" tab="微信公众号配置">
|
||||
<!-- 微信公众号配置表格 -->
|
||||
</NTabPane>
|
||||
<NTabPane name="message" tab="消息配置">
|
||||
<!-- 消息配置表格 -->
|
||||
</NTabPane>
|
||||
</NTabs>
|
||||
```
|
||||
|
||||
### 2. 多表格管理
|
||||
- 每个标签页都有独立的表格状态管理
|
||||
- 独立的搜索参数、分页、选中状态
|
||||
- 独立的CRUD操作和数据刷新
|
||||
|
||||
### 3. 动态表单
|
||||
- 企业微信:企业ID、应用ID、应用Secret
|
||||
- 微信公众号:AppID、AppSecret
|
||||
- 消息配置:根据类型显示不同字段
|
||||
|
||||
### 4. 多租户过滤
|
||||
```typescript
|
||||
const customerId = authStore.userInfo?.customerId;
|
||||
|
||||
// API调用时自动包含customer_id过滤
|
||||
apiParams: {
|
||||
customerId: customerId,
|
||||
type: 'enterprise'
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 TypeScript类型定义
|
||||
|
||||
```typescript
|
||||
declare namespace Api.Health {
|
||||
// 微信配置
|
||||
interface AlertConfigWechat extends Common.CommonRecord {
|
||||
tenantId?: number;
|
||||
customerId?: number;
|
||||
type: 'enterprise' | 'official';
|
||||
corpId?: string;
|
||||
agentId?: string;
|
||||
secret?: string;
|
||||
appid?: string;
|
||||
appsecret?: string;
|
||||
templateId?: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
// 消息配置
|
||||
interface MessageConfig extends Common.CommonRecord {
|
||||
customerId: number;
|
||||
name: string;
|
||||
type: 'sms' | 'email' | 'webhook' | 'internal';
|
||||
endpoint: string;
|
||||
accessKey?: string;
|
||||
secretKey?: string;
|
||||
templateId?: string;
|
||||
enabled: boolean;
|
||||
description?: string;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 部署说明
|
||||
|
||||
### 1. 数据库迁移
|
||||
```bash
|
||||
# 执行数据库迁移脚本
|
||||
mysql -u root -p < migration_alert_config_multi_tenant.sql
|
||||
```
|
||||
|
||||
### 2. 前端组件
|
||||
- 已创建完整的前端组件结构
|
||||
- 所有组件都支持响应式设计
|
||||
- 具备完整的错误处理和用户反馈
|
||||
|
||||
### 3. 权限配置
|
||||
```typescript
|
||||
// 需要配置的权限点
|
||||
't:wechat:alarm:config:add' // 新增微信配置
|
||||
't:wechat:alarm:config:update' // 编辑微信配置
|
||||
't:wechat:alarm:config:delete' // 删除微信配置
|
||||
't:message:config:add' // 新增消息配置
|
||||
't:message:config:update' // 编辑消息配置
|
||||
't:message:config:delete' // 删除消息配置
|
||||
```
|
||||
|
||||
## ✅ 验证清单
|
||||
|
||||
- [x] 三标签页正确显示和切换
|
||||
- [x] 企业微信配置CRUD操作
|
||||
- [x] 微信公众号配置CRUD操作
|
||||
- [x] 消息配置CRUD操作
|
||||
- [x] 多租户数据隔离
|
||||
- [x] 权限控制
|
||||
- [x] 响应式布局
|
||||
- [x] 表单验证
|
||||
- [x] 错误处理
|
||||
|
||||
## 🔄 后续扩展
|
||||
|
||||
1. **告警规则关联**:配置可与告警规则进行关联
|
||||
2. **消息模板管理**:支持自定义消息模板
|
||||
3. **发送测试功能**:支持配置测试发送
|
||||
4. **统计报表**:配置使用情况统计
|
||||
5. **导入导出**:批量配置导入导出功能
|
||||
|
||||
## 📝 技术总结
|
||||
|
||||
这个实现方案充分体现了现代Web应用的设计理念:
|
||||
|
||||
- **模块化架构**:清晰的组件分离和复用
|
||||
- **类型安全**:完整的TypeScript类型定义
|
||||
- **多租户支持**:企业级应用的基础要求
|
||||
- **用户体验**:直观的标签页界面和操作反馈
|
||||
- **可扩展性**:为后续功能扩展预留接口
|
||||
|
||||
通过这个方案,ljwx-admin系统现在具备了完整的告警配置管理能力,支持多种通知渠道和多租户场景。
|
||||
@@ -1,255 +0,0 @@
|
||||
# 后端修复指南
|
||||
|
||||
## 问题概述
|
||||
|
||||
前端已经完成了告警配置三标签页的实现,但后端还需要进行以下修复:
|
||||
|
||||
### 1. 数据库问题
|
||||
- 后端代码查询 `t_wechat_alert_config` 表,但使用了 `tenant_id` 字段
|
||||
- 需要统一使用 `customer_id` 字段
|
||||
|
||||
### 2. 接口问题
|
||||
- 消息配置接口 `/t_message_config/page` 不存在
|
||||
|
||||
## 🔧 修复步骤
|
||||
|
||||
### 步骤1:执行数据库修复脚本
|
||||
|
||||
```bash
|
||||
# 执行数据库修复脚本
|
||||
mysql -u root -p < fix_table_structure_customer_id.sql
|
||||
```
|
||||
|
||||
### 步骤2:修改后端实体类
|
||||
|
||||
需要修改 `TWechatAlertConfig` 实体类,将 `tenantId` 改为 `customerId`:
|
||||
|
||||
**文件位置**:`ljwx-boot-modules/src/main/java/.../entity/TWechatAlertConfig.java`
|
||||
|
||||
```java
|
||||
@TableName("t_wechat_alert_config")
|
||||
public class TWechatAlertConfig {
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
// 将 tenantId 改为 customerId
|
||||
@TableField("customer_id")
|
||||
private Long customerId; // 原来是 tenantId
|
||||
|
||||
@TableField("type")
|
||||
private String type;
|
||||
|
||||
// ... 其他字段保持不变
|
||||
}
|
||||
```
|
||||
|
||||
### 步骤3:修改Mapper XML
|
||||
|
||||
**文件位置**:`ljwx-boot-modules/src/main/resources/mapper/TWechatAlertConfigMapper.xml`
|
||||
|
||||
将所有的 `tenant_id` 替换为 `customer_id`:
|
||||
|
||||
```xml
|
||||
<!-- 修改查询字段 -->
|
||||
<select id="selectList" resultType="...">
|
||||
SELECT id, customer_id, type, corp_id, agent_id, secret,
|
||||
appid, appsecret, template_id, enabled,
|
||||
create_user, create_user_id, create_time,
|
||||
update_user, update_user_id, update_time, is_deleted
|
||||
FROM t_wechat_alert_config
|
||||
WHERE is_deleted = 0
|
||||
<if test="customerId != null">
|
||||
AND customer_id = #{customerId}
|
||||
</if>
|
||||
</select>
|
||||
```
|
||||
|
||||
### 步骤4:修改Service层
|
||||
|
||||
**文件位置**:`ljwx-boot-modules/src/main/java/.../service/impl/TWechatAlertConfigServiceImpl.java`
|
||||
|
||||
```java
|
||||
@Override
|
||||
public IPage<TWechatAlertConfig> listTWechatAlertConfigPage(TWechatAlertConfigPageReqVO reqVO) {
|
||||
LambdaQueryWrapper<TWechatAlertConfig> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 将 tenantId 改为 customerId
|
||||
wrapper.eq(reqVO.getCustomerId() != null, TWechatAlertConfig::getCustomerId, reqVO.getCustomerId());
|
||||
wrapper.eq(StringUtils.hasText(reqVO.getType()), TWechatAlertConfig::getType, reqVO.getType());
|
||||
wrapper.eq(reqVO.getEnabled() != null, TWechatAlertConfig::getEnabled, reqVO.getEnabled());
|
||||
wrapper.eq(TWechatAlertConfig::getIsDeleted, false);
|
||||
|
||||
return this.page(new Page<>(reqVO.getPage(), reqVO.getPageSize()), wrapper);
|
||||
}
|
||||
```
|
||||
|
||||
### 步骤5:创建消息配置相关类
|
||||
|
||||
#### 5.1 创建实体类
|
||||
|
||||
**文件位置**:`ljwx-boot-modules/src/main/java/.../entity/TMessageConfig.java`
|
||||
|
||||
```java
|
||||
@Data
|
||||
@TableName("t_message_config")
|
||||
public class TMessageConfig extends BaseEntity {
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@TableField("customer_id")
|
||||
private Long customerId;
|
||||
|
||||
@TableField("name")
|
||||
private String name;
|
||||
|
||||
@TableField("type")
|
||||
private String type;
|
||||
|
||||
@TableField("endpoint")
|
||||
private String endpoint;
|
||||
|
||||
@TableField("access_key")
|
||||
private String accessKey;
|
||||
|
||||
@TableField("secret_key")
|
||||
private String secretKey;
|
||||
|
||||
@TableField("template_id")
|
||||
private String templateId;
|
||||
|
||||
@TableField("enabled")
|
||||
private Boolean enabled;
|
||||
|
||||
@TableField("description")
|
||||
private String description;
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.2 创建Mapper
|
||||
|
||||
**文件位置**:`ljwx-boot-modules/src/main/java/.../mapper/TMessageConfigMapper.java`
|
||||
|
||||
```java
|
||||
@Mapper
|
||||
public interface TMessageConfigMapper extends BaseMapper<TMessageConfig> {
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.3 创建Service
|
||||
|
||||
**文件位置**:`ljwx-boot-modules/src/main/java/.../service/TMessageConfigService.java`
|
||||
|
||||
```java
|
||||
public interface TMessageConfigService extends IService<TMessageConfig> {
|
||||
IPage<TMessageConfig> listTMessageConfigPage(TMessageConfigPageReqVO reqVO);
|
||||
}
|
||||
```
|
||||
|
||||
**实现类**:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class TMessageConfigServiceImpl extends ServiceImpl<TMessageConfigMapper, TMessageConfig>
|
||||
implements TMessageConfigService {
|
||||
|
||||
@Override
|
||||
public IPage<TMessageConfig> listTMessageConfigPage(TMessageConfigPageReqVO reqVO) {
|
||||
LambdaQueryWrapper<TMessageConfig> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(reqVO.getCustomerId() != null, TMessageConfig::getCustomerId, reqVO.getCustomerId());
|
||||
wrapper.like(StringUtils.hasText(reqVO.getName()), TMessageConfig::getName, reqVO.getName());
|
||||
wrapper.eq(StringUtils.hasText(reqVO.getType()), TMessageConfig::getType, reqVO.getType());
|
||||
wrapper.eq(reqVO.getEnabled() != null, TMessageConfig::getEnabled, reqVO.getEnabled());
|
||||
wrapper.eq(TMessageConfig::getIsDeleted, false);
|
||||
wrapper.orderByDesc(TMessageConfig::getCreateTime);
|
||||
|
||||
return this.page(new Page<>(reqVO.getPage(), reqVO.getPageSize()), wrapper);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.4 创建Controller
|
||||
|
||||
**文件位置**:`ljwx-boot-admin/src/main/java/.../controller/TMessageConfigController.java`
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/t_message_config")
|
||||
@RequiredArgsConstructor
|
||||
public class TMessageConfigController {
|
||||
|
||||
private final TMessageConfigService messageConfigService;
|
||||
|
||||
@GetMapping("/page")
|
||||
public Result<PageResult<TMessageConfig>> page(TMessageConfigPageReqVO reqVO) {
|
||||
IPage<TMessageConfig> page = messageConfigService.listTMessageConfigPage(reqVO);
|
||||
return Result.success(PageResult.of(page));
|
||||
}
|
||||
|
||||
@PostMapping("/")
|
||||
public Result<Boolean> create(@RequestBody TMessageConfigCreateReqVO reqVO) {
|
||||
TMessageConfig entity = BeanUtils.copyProperties(reqVO, TMessageConfig.class);
|
||||
return Result.success(messageConfigService.save(entity));
|
||||
}
|
||||
|
||||
@PutMapping("/")
|
||||
public Result<Boolean> update(@RequestBody TMessageConfigUpdateReqVO reqVO) {
|
||||
TMessageConfig entity = BeanUtils.copyProperties(reqVO, TMessageConfig.class);
|
||||
return Result.success(messageConfigService.updateById(entity));
|
||||
}
|
||||
|
||||
@DeleteMapping("/")
|
||||
public Result<Boolean> delete(@RequestBody DeleteReqVO reqVO) {
|
||||
return Result.success(messageConfigService.removeByIds(reqVO.getIds()));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 步骤6:修改前端API参数名称
|
||||
|
||||
确保前端API调用使用正确的参数名:
|
||||
|
||||
**文件位置**:前端已经修改完成,使用 `customerId` 而不是 `tenantId`
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
### 1. 数据库验证
|
||||
```sql
|
||||
-- 检查表结构
|
||||
DESCRIBE t_wechat_alert_config;
|
||||
DESCRIBE t_message_config;
|
||||
|
||||
-- 检查数据
|
||||
SELECT * FROM t_wechat_alert_config WHERE customer_id = 1;
|
||||
SELECT * FROM t_message_config WHERE customer_id = 1;
|
||||
```
|
||||
|
||||
### 2. API测试
|
||||
```bash
|
||||
# 测试微信配置接口
|
||||
curl -X GET "http://localhost:9998/t_wechat_alarm_config/page?customerId=1"
|
||||
|
||||
# 测试消息配置接口
|
||||
curl -X GET "http://localhost:9998/t_message_config/page?customerId=1"
|
||||
```
|
||||
|
||||
### 3. 前端测试
|
||||
访问 `http://localhost:3333/alert/config` 验证三个标签页都能正常加载数据。
|
||||
|
||||
## 📝 检查清单
|
||||
|
||||
- [ ] 数据库脚本已执行
|
||||
- [ ] TWechatAlertConfig实体类已修改
|
||||
- [ ] Mapper XML已更新
|
||||
- [ ] Service层已修改
|
||||
- [ ] TMessageConfig相关类已创建
|
||||
- [ ] Controller接口已实现
|
||||
- [ ] API测试通过
|
||||
- [ ] 前端页面正常显示
|
||||
|
||||
## 🔍 常见问题
|
||||
|
||||
1. **字段映射错误**:确保实体类字段名与数据库列名一致
|
||||
2. **权限问题**:确保用户有对应的接口访问权限
|
||||
3. **参数校验**:检查请求参数是否正确传递
|
||||
|
||||
完成以上修复后,告警配置页面应该能够正常工作。
|
||||
@@ -1,156 +0,0 @@
|
||||
# 构建部署快速指南
|
||||
|
||||
## 🎯 简洁用法(推荐)
|
||||
|
||||
### 三阶段操作
|
||||
|
||||
```bash
|
||||
# 1️⃣ 构建镜像(仅构建,不推送)
|
||||
./build-and-push.sh -b bigscreen
|
||||
|
||||
# 2️⃣ 推送镜像到 Registry
|
||||
./build-and-push.sh -p bigscreen
|
||||
|
||||
# 3️⃣ 部署服务
|
||||
./build-and-push.sh -d # Docker Compose 部署所有服务
|
||||
./build-and-push.sh -d bigscreen # K8s 部署单个组件
|
||||
```
|
||||
|
||||
## 📦 完整流程示例
|
||||
|
||||
### 场景一:开发测试(仅本地构建)
|
||||
```bash
|
||||
# 仅构建,不推送到 Registry
|
||||
./build-and-push.sh -b bigscreen
|
||||
./build-and-push.sh -b boot
|
||||
./build-and-push.sh -b admin
|
||||
```
|
||||
|
||||
### 场景二:生产发布(构建+推送+部署)
|
||||
```bash
|
||||
# 步骤1: 构建所有应用镜像
|
||||
./build-and-push.sh -b mysql redis boot bigscreen admin
|
||||
|
||||
# 步骤2: 推送到 Registry
|
||||
./build-and-push.sh -p mysql redis boot bigscreen admin
|
||||
|
||||
# 步骤3: Docker Compose 部署
|
||||
./build-and-push.sh -d
|
||||
```
|
||||
|
||||
### 场景三:快速部署(默认行为)
|
||||
```bash
|
||||
# 一步完成:构建+推送
|
||||
./build-and-push.sh bigscreen
|
||||
|
||||
# 然后部署
|
||||
./build-and-push.sh -d
|
||||
```
|
||||
|
||||
## 🐳 Docker Compose 管理
|
||||
|
||||
```bash
|
||||
# 启动所有服务
|
||||
./build-and-push.sh -d
|
||||
./build-and-push.sh compose-up
|
||||
|
||||
# 停止所有服务
|
||||
./build-and-push.sh compose-down
|
||||
|
||||
# 重启服务
|
||||
./build-and-push.sh compose-restart
|
||||
|
||||
# 查看日志
|
||||
./build-and-push.sh compose-logs
|
||||
|
||||
# 查看状态
|
||||
./build-and-push.sh compose-ps
|
||||
```
|
||||
|
||||
## ☸️ Kubernetes 部署
|
||||
|
||||
```bash
|
||||
# 部署单个组件
|
||||
./build-and-push.sh -d bigscreen # 使用 -d 选项
|
||||
./build-and-push.sh deploy bigscreen # 完整命令
|
||||
|
||||
# 部署所有服务
|
||||
./build-and-push.sh deploy-all
|
||||
|
||||
# 指定命名空间
|
||||
K8S_NAMESPACE=production ./build-and-push.sh -d bigscreen
|
||||
```
|
||||
|
||||
## 🔧 选项对比
|
||||
|
||||
| 操作 | 简洁方式 | 完整方式 | 说明 |
|
||||
|------|----------|----------|------|
|
||||
| 仅构建 | `-b bigscreen` | `PUSH_TO_REGISTRY=false bigscreen` | 不推送到 Registry |
|
||||
| 仅推送 | `-p bigscreen` | `push bigscreen` | 推送已构建的镜像 |
|
||||
| Docker Compose 部署 | `-d` | `compose-up` | 部署所有服务 |
|
||||
| K8s 部署 | `-d bigscreen` | `deploy bigscreen` | 部署到 K8s |
|
||||
|
||||
## 💡 常用命令速查
|
||||
|
||||
```bash
|
||||
# 开发调试
|
||||
./build-and-push.sh -b bigscreen # 本地构建测试
|
||||
./build-and-push.sh -d # 启动服务调试
|
||||
|
||||
# 生产发布
|
||||
./build-and-push.sh bigscreen # 构建+推送
|
||||
./build-and-push.sh -d # 部署
|
||||
|
||||
# 更新单个服务
|
||||
./build-and-push.sh -b bigscreen # 重新构建
|
||||
./build-and-push.sh -p bigscreen # 推送
|
||||
docker-compose -f docker-compose.prod.yml up -d --force-recreate ljwx-bigscreen # 重启
|
||||
|
||||
# 批量操作
|
||||
./build-and-push.sh -b mysql redis boot bigscreen admin # 构建多个
|
||||
./build-and-push.sh -p mysql redis boot bigscreen admin # 推送多个
|
||||
```
|
||||
|
||||
## 🌐 服务访问地址
|
||||
|
||||
部署成功后,可通过以下地址访问:
|
||||
|
||||
- **后端API**: http://localhost:9998
|
||||
- **管理界面**: http://localhost:80
|
||||
- **大屏服务**: http://localhost:8000
|
||||
- **MySQL**: localhost:3306 (root/123456)
|
||||
- **Redis**: localhost:6379
|
||||
- **Registry Web UI**: http://localhost:8082
|
||||
|
||||
## 🔍 故障排查
|
||||
|
||||
### 服务启动失败
|
||||
```bash
|
||||
# 查看日志
|
||||
./build-and-push.sh compose-logs
|
||||
|
||||
# 查看特定服务日志
|
||||
docker-compose -f docker-compose.prod.yml logs -f ljwx-bigscreen
|
||||
|
||||
# 重启服务
|
||||
./build-and-push.sh compose-restart
|
||||
```
|
||||
|
||||
### 镜像推送失败
|
||||
```bash
|
||||
# 检查 Registry 状态
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
|
||||
# 重新标记镜像
|
||||
docker tag 127.0.0.1:15000/ljwx/ljwx-bigscreen:2.0.3 localhost:15000/ljwx/ljwx-bigscreen:2.0.3
|
||||
|
||||
# 推送
|
||||
./build-and-push.sh -p bigscreen
|
||||
```
|
||||
|
||||
## 📚 更多信息
|
||||
|
||||
完整文档请查看 `./build-and-push.sh` 帮助信息:
|
||||
```bash
|
||||
./build-and-push.sh
|
||||
```
|
||||
@@ -1,476 +0,0 @@
|
||||
# Docker 构建优化指南
|
||||
|
||||
## 🎯 核心问题
|
||||
|
||||
原来的构建存在三大性能瓶颈:
|
||||
|
||||
1. **每次 `apk add maven`** - 重复拉 Alpine 索引(15-20秒)
|
||||
2. **每次下载 Maven 依赖** - 重复下载几百 MB(60-120秒)
|
||||
3. **跨平台构建** - QEMU 模拟降低 50-70% 性能
|
||||
|
||||
总构建时间:**3-5 分钟**(每次改代码都要等这么久)
|
||||
|
||||
## ✨ 优化方案
|
||||
|
||||
### 三步优化,速度提升 **5-10 倍**
|
||||
|
||||
```
|
||||
原版构建:180-300 秒
|
||||
优化后首次:120-180 秒(需要构建基础镜像 + 下载依赖)
|
||||
优化后后续:15-30 秒(只编译代码)
|
||||
```
|
||||
|
||||
## 📦 第一步:构建基础镜像(一次性)
|
||||
|
||||
### 为什么需要基础镜像?
|
||||
|
||||
把"装系统工具"从"每次构建"变成"只做一次":
|
||||
|
||||
**原来(每次构建)**:
|
||||
```dockerfile
|
||||
FROM eclipse-temurin:21-jdk-alpine
|
||||
RUN apk add --no-cache maven # ← 每次 15-20 秒
|
||||
RUN 配置 Maven settings.xml # ← 每次重复
|
||||
```
|
||||
|
||||
**优化后(只做一次)**:
|
||||
```dockerfile
|
||||
# 基础镜像已经装好 Maven + 配置好镜像
|
||||
FROM localhost:15000/ljwx/java-maven-base:21-jdk-alpine
|
||||
# 直接开始构建业务代码
|
||||
```
|
||||
|
||||
### 构建基础镜像
|
||||
|
||||
```bash
|
||||
# 1. 进入基础镜像目录
|
||||
cd docker/base-images
|
||||
|
||||
# 2. 运行构建脚本(只需要运行一次)
|
||||
./build-base-images.sh
|
||||
```
|
||||
|
||||
**输出**:
|
||||
```
|
||||
✅ Java Maven 基础镜像构建完成
|
||||
✅ Python 基础镜像构建完成
|
||||
✅ 所有基础镜像已推送到 localhost:15000
|
||||
```
|
||||
|
||||
**查看结果**:
|
||||
```bash
|
||||
docker images | grep ljwx.*base
|
||||
```
|
||||
|
||||
你会看到:
|
||||
```
|
||||
localhost:15000/ljwx/java-maven-base 21-jdk-alpine
|
||||
localhost:15000/ljwx/python-base 3.12-slim
|
||||
```
|
||||
|
||||
## 🔧 第二步:切换到优化版 Dockerfile
|
||||
|
||||
### 自动切换
|
||||
|
||||
```bash
|
||||
# 从项目根目录运行
|
||||
./switch-dockerfile.sh optimized
|
||||
```
|
||||
|
||||
**会自动**:
|
||||
- ✅ 备份原版 Dockerfile(保存为 `.original`)
|
||||
- ✅ 启用优化版 Dockerfile
|
||||
- ✅ 显示切换状态
|
||||
|
||||
### 手动验证
|
||||
|
||||
```bash
|
||||
# 查看当前使用的版本
|
||||
./switch-dockerfile.sh status
|
||||
```
|
||||
|
||||
**输出示例**:
|
||||
```
|
||||
Boot: ✅ 使用优化版
|
||||
Bigscreen: ✅ 使用优化版
|
||||
Admin: ✅ 已优化(原本就好)
|
||||
```
|
||||
|
||||
## 🚀 第三步:启用 BuildKit 构建
|
||||
|
||||
### 永久启用(推荐)
|
||||
|
||||
```bash
|
||||
# 添加到 ~/.zshrc 或 ~/.bashrc
|
||||
echo 'export DOCKER_BUILDKIT=1' >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
### 临时启用
|
||||
|
||||
```bash
|
||||
export DOCKER_BUILDKIT=1
|
||||
```
|
||||
|
||||
### 验证
|
||||
|
||||
```bash
|
||||
# 构建时看到类似输出就说明 BuildKit 已启用
|
||||
docker build ...
|
||||
# [+] Building 12.3s (15/15) FINISHED ← 带 [+] 符号
|
||||
```
|
||||
|
||||
## 📈 效果对比
|
||||
|
||||
### Boot 后端(Maven)
|
||||
|
||||
**原版构建过程**:
|
||||
```
|
||||
1. apk add maven → 15-20s
|
||||
2. 下载 Maven 依赖 → 60-90s
|
||||
3. 编译 starter → 20-30s
|
||||
4. 下载主应用依赖 → 30-40s
|
||||
5. 编译主应用 → 20-30s
|
||||
-----------------------------------------
|
||||
总计: ~180-210s(3-3.5分钟)
|
||||
```
|
||||
|
||||
**优化版首次构建**:
|
||||
```
|
||||
1. 拉基础镜像(已有 Maven)→ 5s
|
||||
2. 下载 starter 依赖 → 30-40s(缓存到宿主机)
|
||||
3. 编译 starter → 20-30s
|
||||
4. 下载主应用依赖 → 20-30s(缓存到宿主机)
|
||||
5. 编译主应用 → 15-20s
|
||||
-----------------------------------------
|
||||
总计: ~90-125s(1.5-2分钟)
|
||||
```
|
||||
|
||||
**优化版后续构建**(改代码):
|
||||
```
|
||||
1. 复用基础镜像 → 即时
|
||||
2. 复用 starter 依赖缓存 → 即时(pom 未变)
|
||||
3. 复用 starter 构建 → 即时(代码未变)
|
||||
4. 复用主应用依赖缓存 → 即时(pom 未变)
|
||||
5. 只编译改动的代码 → 15-20s
|
||||
-----------------------------------------
|
||||
总计: ~15-20s(只需20秒!)
|
||||
```
|
||||
|
||||
### Bigscreen(Python)
|
||||
|
||||
**原版构建**:
|
||||
```
|
||||
1. 配置 apt 源 → 10-15s
|
||||
2. 安装编译工具 → 30-40s
|
||||
3. pip 下载依赖 → 40-60s
|
||||
4. 复制代码 → 2-3s
|
||||
-----------------------------------------
|
||||
总计: ~85-120s
|
||||
```
|
||||
|
||||
**优化版后续构建**:
|
||||
```
|
||||
1. 复用基础镜像(已有编译工具)→ 即时
|
||||
2. 复用 pip 依赖缓存 → 即时
|
||||
3. 只复制代码 → 2-3s
|
||||
-----------------------------------------
|
||||
总计: ~2-3s(秒级完成!)
|
||||
```
|
||||
|
||||
### Admin(Node.js)
|
||||
|
||||
Admin 的 Dockerfile 本来就做得不错(已经用了 pnpm cache),优化空间较小。
|
||||
|
||||
## 🔍 优化原理详解
|
||||
|
||||
### 1. 基础镜像复用
|
||||
|
||||
**原理**:把"系统环境准备"从构建流程中剥离
|
||||
|
||||
```dockerfile
|
||||
# 原来:每次都要装 Maven(15-20s)
|
||||
FROM eclipse-temurin:21-jdk-alpine
|
||||
RUN apk add --no-cache maven # ← 浪费时间
|
||||
|
||||
# 优化:基础镜像已经装好
|
||||
FROM localhost:15000/ljwx/java-maven-base:21-jdk-alpine
|
||||
# Maven 已经装好,settings.xml 已配置
|
||||
```
|
||||
|
||||
### 2. BuildKit Cache Mount
|
||||
|
||||
**原理**:把依赖缓存在宿主机,而不是镜像层里
|
||||
|
||||
```dockerfile
|
||||
# 原来:依赖打包在镜像层里,每次重新下载
|
||||
RUN mvn clean package # ← ~/.m2 在容器里,构建完就丢了
|
||||
|
||||
# 优化:依赖缓存在宿主机
|
||||
RUN --mount=type=cache,target=/root/.m2/repository \
|
||||
mvn clean package # ← ~/.m2 缓存在宿主机的 BuildKit cache
|
||||
```
|
||||
|
||||
**缓存位置**(macOS):
|
||||
```
|
||||
~/Library/Containers/com.docker.docker/Data/vms/0/data/docker/buildkit/
|
||||
```
|
||||
|
||||
**效果**:
|
||||
- 第一次构建:下载依赖,存入缓存
|
||||
- 第二次构建:从缓存读取,不再下载
|
||||
|
||||
### 3. 分层构建
|
||||
|
||||
**原理**:把"变化频率不同"的内容分成不同的层
|
||||
|
||||
```dockerfile
|
||||
# ====== 低频变化层(几乎不变)======
|
||||
COPY pom.xml .
|
||||
RUN mvn dependency:go-offline # ← 只有 pom 变化时才重新执行
|
||||
|
||||
# ====== 高频变化层(经常改)======
|
||||
COPY src ./src
|
||||
RUN mvn package # ← 只有代码变化时才重新编译
|
||||
```
|
||||
|
||||
**Docker Layer Cache 机制**:
|
||||
- 每条 `RUN`/`COPY` 指令生成一个层
|
||||
- 如果指令和输入文件没变,就复用缓存层
|
||||
- 只有变化的层及之后的层需要重新构建
|
||||
|
||||
## 📋 完整使用流程
|
||||
|
||||
### 首次使用(完整设置)
|
||||
|
||||
```bash
|
||||
# 1. 构建基础镜像(只做一次)
|
||||
cd docker/base-images
|
||||
./build-base-images.sh
|
||||
cd ../..
|
||||
|
||||
# 2. 切换到优化版 Dockerfile
|
||||
./switch-dockerfile.sh optimized
|
||||
|
||||
# 3. 启用 BuildKit
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
# 4. 首次构建(会较慢,因为要下载依赖到缓存)
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 5. 再次构建(体验飞速)
|
||||
# 随便改点代码
|
||||
echo "// test" >> ljwx-boot/ljwx-boot-admin/src/main/java/Test.java
|
||||
./build-and-push.sh boot
|
||||
# 只需 15-20 秒!
|
||||
```
|
||||
|
||||
### 日常开发(已经设置好)
|
||||
|
||||
```bash
|
||||
# 1. 改代码
|
||||
vi ljwx-boot/ljwx-boot-admin/src/main/java/...
|
||||
|
||||
# 2. 构建(秒级完成)
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 3. 部署
|
||||
kubectl rollout restart deployment/ljwx-boot -n ljwx-system
|
||||
```
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### 问题 1:基础镜像拉取失败
|
||||
|
||||
**现象**:
|
||||
```
|
||||
ERROR: failed to solve: localhost:15000/ljwx/java-maven-base:21-jdk-alpine: not found
|
||||
```
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 检查基础镜像是否存在
|
||||
docker images | grep java-maven-base
|
||||
|
||||
# 如果不存在,重新构建
|
||||
cd docker/base-images
|
||||
./build-base-images.sh
|
||||
```
|
||||
|
||||
### 问题 2:BuildKit 未启用
|
||||
|
||||
**现象**:
|
||||
```
|
||||
WARNING: buildkit is not enabled
|
||||
```
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 启用 BuildKit
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
# 或者在 Docker Desktop 设置中启用
|
||||
# Settings → Docker Engine → 添加:
|
||||
{
|
||||
"features": {
|
||||
"buildkit": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 问题 3:缓存未命中
|
||||
|
||||
**现象**:每次构建还是很慢
|
||||
|
||||
**排查**:
|
||||
```bash
|
||||
# 1. 确认 BuildKit 已启用
|
||||
echo $DOCKER_BUILDKIT # 应该输出 1
|
||||
|
||||
# 2. 查看构建日志
|
||||
docker build ... 2>&1 | grep cache
|
||||
# 应该看到:---> Using cache
|
||||
|
||||
# 3. 清理缓存重试
|
||||
docker builder prune -af
|
||||
./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 问题 4:想恢复原版
|
||||
|
||||
```bash
|
||||
# 恢复到原版 Dockerfile
|
||||
./switch-dockerfile.sh original
|
||||
```
|
||||
|
||||
## 📊 性能监控
|
||||
|
||||
### 查看构建时间
|
||||
|
||||
```bash
|
||||
# 方法 1:使用 time 命令
|
||||
time ./build-and-push.sh boot
|
||||
|
||||
# 方法 2:查看构建日志
|
||||
docker build ... 2>&1 | grep "Building"
|
||||
```
|
||||
|
||||
### 查看缓存使用
|
||||
|
||||
```bash
|
||||
# 查看 BuildKit 缓存大小
|
||||
docker system df -v | grep buildx
|
||||
|
||||
# 查看本地镜像大小
|
||||
docker images | grep ljwx
|
||||
```
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
### 1. 基础镜像管理
|
||||
|
||||
```bash
|
||||
# 定期更新基础镜像(例如每月一次)
|
||||
cd docker/base-images
|
||||
./build-base-images.sh
|
||||
|
||||
# 推送到共享 Registry(团队协作)
|
||||
docker tag localhost:15000/ljwx/java-maven-base:21-jdk-alpine \
|
||||
registry.company.com/ljwx/java-maven-base:21-jdk-alpine
|
||||
docker push registry.company.com/ljwx/java-maven-base:21-jdk-alpine
|
||||
```
|
||||
|
||||
### 2. 依赖变化处理
|
||||
|
||||
```bash
|
||||
# pom.xml / requirements.txt 变化后:
|
||||
# 1. 首次构建会较慢(下载新依赖)
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 2. 之后又恢复快速
|
||||
./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 3. 缓存清理
|
||||
|
||||
```bash
|
||||
# 定期清理无用缓存
|
||||
docker builder prune -af
|
||||
|
||||
# 清理旧镜像
|
||||
docker image prune -af
|
||||
```
|
||||
|
||||
### 4. 本地 vs 远程构建
|
||||
|
||||
```bash
|
||||
# 本地开发:使用 arm64(你的 Mac)
|
||||
PLATFORMS=linux/arm64 ./build-and-push.sh boot
|
||||
|
||||
# CI/远程:使用 amd64(避免 QEMU 模拟)
|
||||
PLATFORMS=linux/amd64 ./build-and-push.sh boot
|
||||
```
|
||||
|
||||
## 📈 收益总结
|
||||
|
||||
| 指标 | 原版 | 优化版(首次)| 优化版(后续)| 提升 |
|
||||
|------|------|--------------|---------------|------|
|
||||
| **Boot 构建** | 180s | 120s | 20s | **9x** |
|
||||
| **Bigscreen 构建** | 90s | 60s | 3s | **30x** |
|
||||
| **Admin 构建** | 120s | 90s | 30s | **4x** |
|
||||
| **总开发时间** | 390s (6.5分钟) | 270s (4.5分钟) | 53s (< 1分钟) | **7x** |
|
||||
|
||||
**日常开发收益**:
|
||||
- 原来:改代码 → 等 6 分钟构建 → 部署
|
||||
- 现在:改代码 → 等 1 分钟构建 → 部署
|
||||
- **节省 5 分钟/次**,一天构建 10 次 = **节省 50 分钟**
|
||||
|
||||
## 🎓 进阶优化
|
||||
|
||||
### 1. 多阶段并行构建
|
||||
|
||||
```bash
|
||||
# 同时构建多个组件
|
||||
./build-and-push.sh boot &
|
||||
./build-and-push.sh bigscreen &
|
||||
./build-and-push.sh admin &
|
||||
wait
|
||||
|
||||
# 总时间 = 最慢的那个(而不是累加)
|
||||
```
|
||||
|
||||
### 2. 远程缓存(团队协作)
|
||||
|
||||
```dockerfile
|
||||
# 推送缓存到远程
|
||||
docker buildx build \
|
||||
--cache-to type=registry,ref=registry.com/cache/boot:latest \
|
||||
...
|
||||
|
||||
# 拉取缓存从远程
|
||||
docker buildx build \
|
||||
--cache-from type=registry,ref=registry.com/cache/boot:latest \
|
||||
...
|
||||
```
|
||||
|
||||
### 3. 增量构建
|
||||
|
||||
```bash
|
||||
# 使用 --target 只构建特定阶段
|
||||
docker build --target builder ... # 只构建不推送
|
||||
```
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
遇到问题?
|
||||
|
||||
1. **查看状态**:`./switch-dockerfile.sh status`
|
||||
2. **查看文档**:本文档
|
||||
3. **清理重试**:`docker builder prune -af && ./build-and-push.sh boot`
|
||||
4. **恢复原版**:`./switch-dockerfile.sh original`
|
||||
|
||||
---
|
||||
|
||||
**版本**: v1.0.0
|
||||
**更新**: 2025-11-26
|
||||
**适用**: macOS + OrbStack/Docker Desktop
|
||||
@@ -1,136 +0,0 @@
|
||||
# 构建优化 - 快速开始(3步搞定)
|
||||
|
||||
## 🎯 优化效果
|
||||
|
||||
- **原来**:改代码 → 等 6 分钟构建 → 部署
|
||||
- **现在**:改代码 → 等 1 分钟构建 → 部署
|
||||
- **提升**:**5-10 倍**加速
|
||||
|
||||
## ⚡ 3 步启用优化
|
||||
|
||||
### 第 1 步:构建基础镜像(2分钟,只做一次)
|
||||
|
||||
```bash
|
||||
cd docker/base-images
|
||||
./build-base-images.sh
|
||||
cd ../..
|
||||
```
|
||||
|
||||
### 第 2 步:切换到优化版(1秒)
|
||||
|
||||
```bash
|
||||
./switch-dockerfile.sh optimized
|
||||
```
|
||||
|
||||
### 第 3 步:启用 BuildKit(1秒)
|
||||
|
||||
```bash
|
||||
export DOCKER_BUILDKIT=1
|
||||
# 建议加到 ~/.zshrc:echo 'export DOCKER_BUILDKIT=1' >> ~/.zshrc
|
||||
```
|
||||
|
||||
完成!现在构建会快很多。
|
||||
|
||||
## 🚀 验证效果
|
||||
|
||||
### 首次构建(会较慢)
|
||||
|
||||
```bash
|
||||
# 首次构建需要下载依赖到缓存
|
||||
time ./build-and-push.sh boot
|
||||
|
||||
# 预期时间:1.5-2 分钟
|
||||
```
|
||||
|
||||
### 再次构建(体验飞速)
|
||||
|
||||
```bash
|
||||
# 随便改点代码
|
||||
echo "// test" >> ljwx-boot/ljwx-boot-admin/src/main/java/com/ljwx/Test.java
|
||||
|
||||
# 再次构建
|
||||
time ./build-and-push.sh boot
|
||||
|
||||
# 预期时间:15-20 秒!🚀
|
||||
```
|
||||
|
||||
## 📊 性能对比
|
||||
|
||||
| 构建类型 | 原版时间 | 优化版时间 | 加速比 |
|
||||
|---------|---------|-----------|--------|
|
||||
| Boot 首次 | 180s | 120s | 1.5x |
|
||||
| Boot 后续 | 180s | **20s** | **9x** ✨ |
|
||||
| Bigscreen 后续 | 90s | **3s** | **30x** 🚀 |
|
||||
| Admin 后续 | 120s | **30s** | **4x** ⚡ |
|
||||
|
||||
## 🔍 查看状态
|
||||
|
||||
```bash
|
||||
# 查看当前使用的 Dockerfile 版本
|
||||
./switch-dockerfile.sh status
|
||||
|
||||
# 查看基础镜像
|
||||
docker images | grep ljwx.*base
|
||||
```
|
||||
|
||||
## 🛠️ 常用命令
|
||||
|
||||
```bash
|
||||
# 恢复到原版(如果有问题)
|
||||
./switch-dockerfile.sh original
|
||||
|
||||
# 重新构建基础镜像(偶尔更新)
|
||||
cd docker/base-images && ./build-base-images.sh
|
||||
|
||||
# 清理缓存(如果缓存过大)
|
||||
docker builder prune -af
|
||||
```
|
||||
|
||||
## 💡 原理简述
|
||||
|
||||
### 为什么快?
|
||||
|
||||
1. **基础镜像复用** - Maven/Python 已经装好,不用每次 `apk add`
|
||||
2. **BuildKit Cache** - 依赖缓存在宿主机,不用重复下载
|
||||
3. **分层构建** - 只有代码变化才重新编译
|
||||
|
||||
### 缓存位置
|
||||
|
||||
```
|
||||
macOS: ~/Library/Containers/com.docker.docker/Data/vms/0/data/docker/buildkit/
|
||||
```
|
||||
|
||||
## 📚 详细文档
|
||||
|
||||
完整文档:[BUILD-OPTIMIZATION-GUIDE.md](./BUILD-OPTIMIZATION-GUIDE.md)
|
||||
|
||||
包含:
|
||||
- 🎯 优化原理详解
|
||||
- 📦 基础镜像管理
|
||||
- 🔍 故障排查指南
|
||||
- 📈 性能监控方法
|
||||
- 🎓 进阶优化技巧
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
1. **首次使用**需要构建基础镜像(2分钟)
|
||||
2. **首次构建**需要下载依赖到缓存(1-2分钟)
|
||||
3. **第二次起**才能体验飞速(20秒)
|
||||
4. **pom.xml 变化**后首次构建会稍慢(下载新依赖)
|
||||
|
||||
## 🎉 开始使用
|
||||
|
||||
```bash
|
||||
# 一条命令启用所有优化
|
||||
cd docker/base-images && ./build-base-images.sh && cd ../.. && \
|
||||
./switch-dockerfile.sh optimized && \
|
||||
export DOCKER_BUILDKIT=1 && \
|
||||
echo "✅ 优化已启用!现在构建会快很多"
|
||||
|
||||
# 验证效果
|
||||
time ./build-and-push.sh boot
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**节省时间 = 更多咖啡时间 ☕**
|
||||
@@ -1,388 +0,0 @@
|
||||
# Docker 构建优化工具集
|
||||
|
||||
完整的 Docker 构建优化方案,让构建速度提升 **5-10 倍**。
|
||||
|
||||
## 📦 文件清单
|
||||
|
||||
### 核心文件
|
||||
|
||||
| 文件 | 大小 | 功能 |
|
||||
|------|------|------|
|
||||
| `BUILD-OPTIMIZATION-QUICK-START.md` | 2.9KB | ⚡ 快速开始 - 3步启用 |
|
||||
| `BUILD-OPTIMIZATION-GUIDE.md` | 10KB | 📚 完整指南 - 详细文档 |
|
||||
| `switch-dockerfile.sh` | 5.4KB | 🔄 切换工具 - 一键切换优化版 |
|
||||
|
||||
### 基础镜像
|
||||
|
||||
| 文件 | 位置 | 功能 |
|
||||
|------|------|------|
|
||||
| `build-base-images.sh` | `docker/base-images/` | 🏗️ 构建基础镜像 |
|
||||
| `Dockerfile.java-maven-base` | `docker/base-images/` | ☕ Java Maven 基础镜像 |
|
||||
| `Dockerfile.python-base` | `docker/base-images/` | 🐍 Python 基础镜像 |
|
||||
|
||||
### 优化的 Dockerfile
|
||||
|
||||
| 文件 | 位置 | 功能 |
|
||||
|------|------|------|
|
||||
| `Dockerfile.prod.optimized` | `ljwx-boot/ljwx-boot-admin/` | 优化的 Boot Dockerfile |
|
||||
| `Dockerfile.prod.optimized` | `ljwx-bigscreen/bigscreen/` | 优化的 Bigscreen Dockerfile |
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 3 步启用优化
|
||||
|
||||
```bash
|
||||
# 1. 构建基础镜像(只做一次)
|
||||
cd docker/base-images
|
||||
./build-base-images.sh
|
||||
cd ../..
|
||||
|
||||
# 2. 切换到优化版
|
||||
./switch-dockerfile.sh optimized
|
||||
|
||||
# 3. 启用 BuildKit
|
||||
export DOCKER_BUILDKIT=1
|
||||
```
|
||||
|
||||
完成!现在构建会快 **5-10 倍**。
|
||||
|
||||
### 验证效果
|
||||
|
||||
```bash
|
||||
# 首次构建(会较慢,下载依赖)
|
||||
time ./build-and-push.sh boot
|
||||
|
||||
# 改点代码
|
||||
echo "// test" >> ljwx-boot/ljwx-boot-admin/src/main/java/Test.java
|
||||
|
||||
# 再次构建(飞速!)
|
||||
time ./build-and-push.sh boot
|
||||
```
|
||||
|
||||
## 📊 性能提升
|
||||
|
||||
| 组件 | 原版时间 | 优化后时间 | 提升 |
|
||||
|------|----------|-----------|------|
|
||||
| **Boot(Maven)** | 180s | **20s** | **9x** 🚀 |
|
||||
| **Bigscreen(Python)** | 90s | **3s** | **30x** ⚡ |
|
||||
| **Admin(Node.js)** | 120s | **30s** | **4x** ✨ |
|
||||
|
||||
**日常开发收益**:
|
||||
- 每次构建节省 **5 分钟**
|
||||
- 一天构建 10 次 = 节省 **50 分钟**
|
||||
|
||||
## 🎯 核心优化
|
||||
|
||||
### 1. 基础镜像复用
|
||||
|
||||
**原来**:每次 `apk add maven`(15-20秒)
|
||||
**现在**:基础镜像已装好,直接用
|
||||
|
||||
```dockerfile
|
||||
# 原来
|
||||
FROM eclipse-temurin:21-jdk-alpine
|
||||
RUN apk add --no-cache maven # ← 每次 15-20s
|
||||
|
||||
# 优化后
|
||||
FROM localhost:15000/ljwx/java-maven-base:21-jdk-alpine
|
||||
# Maven 已经装好 ✅
|
||||
```
|
||||
|
||||
### 2. BuildKit Cache Mount
|
||||
|
||||
**原来**:每次下载 Maven 依赖(60-90秒)
|
||||
**现在**:依赖缓存在宿主机,只下载一次
|
||||
|
||||
```dockerfile
|
||||
# 原来
|
||||
RUN mvn package # ← 每次重新下载依赖
|
||||
|
||||
# 优化后
|
||||
RUN --mount=type=cache,target=/root/.m2/repository \
|
||||
mvn package # ← 依赖缓存在宿主机 ✅
|
||||
```
|
||||
|
||||
### 3. 分层构建
|
||||
|
||||
**原来**:改代码 → 重新下载所有依赖 → 重新编译
|
||||
**现在**:改代码 → 复用依赖 → 只编译改动部分
|
||||
|
||||
```dockerfile
|
||||
# 第 1 层:下载依赖(pom 不变就复用)
|
||||
COPY pom.xml .
|
||||
RUN mvn dependency:go-offline
|
||||
|
||||
# 第 2 层:编译代码(代码变了才重新编译)
|
||||
COPY src ./src
|
||||
RUN mvn package
|
||||
```
|
||||
|
||||
## 🛠️ 使用工具
|
||||
|
||||
### switch-dockerfile.sh
|
||||
|
||||
一键切换 Dockerfile 版本:
|
||||
|
||||
```bash
|
||||
# 查看状态
|
||||
./switch-dockerfile.sh status
|
||||
|
||||
# 切换到优化版
|
||||
./switch-dockerfile.sh optimized
|
||||
|
||||
# 恢复原版
|
||||
./switch-dockerfile.sh original
|
||||
|
||||
# 查看帮助
|
||||
./switch-dockerfile.sh help
|
||||
```
|
||||
|
||||
### build-base-images.sh
|
||||
|
||||
构建基础镜像:
|
||||
|
||||
```bash
|
||||
cd docker/base-images
|
||||
./build-base-images.sh
|
||||
|
||||
# 输出:
|
||||
# ✅ Java Maven 基础镜像构建完成
|
||||
# ✅ Python 基础镜像构建完成
|
||||
# ✅ 所有基础镜像已推送
|
||||
```
|
||||
|
||||
## 📚 文档说明
|
||||
|
||||
### BUILD-OPTIMIZATION-QUICK-START.md
|
||||
|
||||
**适合**:快速上手
|
||||
**内容**:
|
||||
- ⚡ 3步启用优化
|
||||
- 🚀 验证效果
|
||||
- 📊 性能对比
|
||||
- 🛠️ 常用命令
|
||||
|
||||
**阅读时间**:2 分钟
|
||||
|
||||
### BUILD-OPTIMIZATION-GUIDE.md
|
||||
|
||||
**适合**:深入理解
|
||||
**内容**:
|
||||
- 🎯 核心问题分析
|
||||
- 📦 基础镜像详解
|
||||
- 🔧 优化原理
|
||||
- 📈 效果对比
|
||||
- 🛠️ 故障排查
|
||||
- 🎓 进阶优化
|
||||
|
||||
**阅读时间**:15 分钟
|
||||
|
||||
## 🔍 工作流程
|
||||
|
||||
### 开发流程(优化前)
|
||||
|
||||
```
|
||||
改代码 → 等 6 分钟 → 部署
|
||||
```
|
||||
|
||||
### 开发流程(优化后)
|
||||
|
||||
```
|
||||
改代码 → 等 1 分钟 → 部署 ← 节省 5 分钟!
|
||||
```
|
||||
|
||||
### 详细时间线
|
||||
|
||||
**原版**:
|
||||
```
|
||||
1. apk add maven → 15-20s
|
||||
2. 下载 Maven 依赖 → 60-90s
|
||||
3. 编译 starter → 20-30s
|
||||
4. 下载主应用依赖 → 30-40s
|
||||
5. 编译主应用 → 20-30s
|
||||
-----------------------------------------
|
||||
总计: 180-210s(3-3.5 分钟)
|
||||
```
|
||||
|
||||
**优化版(首次)**:
|
||||
```
|
||||
1. 拉基础镜像 → 5s
|
||||
2. 下载依赖(缓存) → 60-80s
|
||||
3. 编译 → 40-60s
|
||||
-----------------------------------------
|
||||
总计: 105-145s(1.5-2.5 分钟)
|
||||
```
|
||||
|
||||
**优化版(后续)**:
|
||||
```
|
||||
1. 复用镜像 → 即时
|
||||
2. 复用依赖缓存 → 即时
|
||||
3. 只编译代码 → 15-20s
|
||||
-----------------------------------------
|
||||
总计: 15-20s(只需 20 秒!)✨
|
||||
```
|
||||
|
||||
## 🎯 使用场景
|
||||
|
||||
### 场景 1:日常开发
|
||||
|
||||
```bash
|
||||
# 改 Java 代码
|
||||
vi ljwx-boot/src/main/java/...
|
||||
|
||||
# 快速构建(20秒)
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 部署
|
||||
kubectl rollout restart deployment/ljwx-boot
|
||||
```
|
||||
|
||||
### 场景 2:修改依赖
|
||||
|
||||
```bash
|
||||
# 修改 pom.xml 添加新依赖
|
||||
vi ljwx-boot/pom.xml
|
||||
|
||||
# 首次构建(下载新依赖,稍慢)
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 之后又恢复快速
|
||||
./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 场景 3:团队协作
|
||||
|
||||
```bash
|
||||
# 推送基础镜像到共享 Registry
|
||||
docker tag localhost:15000/ljwx/java-maven-base:21-jdk-alpine \
|
||||
registry.company.com/ljwx/java-maven-base:21-jdk-alpine
|
||||
docker push registry.company.com/ljwx/java-maven-base:21-jdk-alpine
|
||||
|
||||
# 团队成员拉取
|
||||
docker pull registry.company.com/ljwx/java-maven-base:21-jdk-alpine
|
||||
```
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 首次使用
|
||||
|
||||
1. ✅ 需要构建基础镜像(2分钟)
|
||||
2. ✅ 需要启用 BuildKit
|
||||
3. ✅ 首次构建会下载依赖到缓存
|
||||
4. ✅ 第二次起才能体验飞速
|
||||
|
||||
### 依赖变化
|
||||
|
||||
- pom.xml / requirements.txt 变化后
|
||||
- 首次构建会下载新依赖(稍慢)
|
||||
- 之后又恢复快速
|
||||
|
||||
### 缓存管理
|
||||
|
||||
```bash
|
||||
# 查看缓存大小
|
||||
docker system df
|
||||
|
||||
# 清理缓存(如果太大)
|
||||
docker builder prune -af
|
||||
```
|
||||
|
||||
## 🐛 故障排查
|
||||
|
||||
### 问题 1:基础镜像不存在
|
||||
|
||||
```bash
|
||||
# 检查
|
||||
docker images | grep ljwx.*base
|
||||
|
||||
# 解决:重新构建
|
||||
cd docker/base-images && ./build-base-images.sh
|
||||
```
|
||||
|
||||
### 问题 2:BuildKit 未启用
|
||||
|
||||
```bash
|
||||
# 检查
|
||||
echo $DOCKER_BUILDKIT # 应该输出 1
|
||||
|
||||
# 解决:启用
|
||||
export DOCKER_BUILDKIT=1
|
||||
```
|
||||
|
||||
### 问题 3:还是很慢
|
||||
|
||||
```bash
|
||||
# 1. 确认使用优化版
|
||||
./switch-dockerfile.sh status
|
||||
|
||||
# 2. 清理缓存重试
|
||||
docker builder prune -af
|
||||
./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 问题 4:想恢复原版
|
||||
|
||||
```bash
|
||||
./switch-dockerfile.sh original
|
||||
```
|
||||
|
||||
## 📈 进阶优化
|
||||
|
||||
### 1. 并行构建
|
||||
|
||||
```bash
|
||||
# 同时构建多个组件
|
||||
./build-and-push.sh boot &
|
||||
./build-and-push.sh bigscreen &
|
||||
./build-and-push.sh admin &
|
||||
wait
|
||||
```
|
||||
|
||||
### 2. 远程缓存
|
||||
|
||||
```bash
|
||||
# 推送缓存到远程
|
||||
docker buildx build \
|
||||
--cache-to type=registry,ref=registry.com/cache:latest \
|
||||
...
|
||||
```
|
||||
|
||||
### 3. 多平台构建
|
||||
|
||||
```bash
|
||||
# 本地开发:arm64
|
||||
PLATFORMS=linux/arm64 ./build-and-push.sh boot
|
||||
|
||||
# CI/生产:amd64
|
||||
PLATFORMS=linux/amd64 ./build-and-push.sh boot
|
||||
```
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
1. **基础镜像**:每月更新一次
|
||||
2. **缓存清理**:每周清理一次
|
||||
3. **本地构建**:使用 arm64(你的 Mac)
|
||||
4. **远程构建**:使用 amd64(CI/生产)
|
||||
5. **团队协作**:共享基础镜像
|
||||
|
||||
## 🎉 收益总结
|
||||
|
||||
- ✅ 构建时间从 6 分钟降到 1 分钟
|
||||
- ✅ 每天节省 50 分钟(构建 10 次)
|
||||
- ✅ 每周节省 250 分钟(4+ 小时)
|
||||
- ✅ 每月节省 1000 分钟(17+ 小时)
|
||||
|
||||
**一年节省 200+ 小时 = 25 个工作日!**
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
- 📖 [快速开始](./BUILD-OPTIMIZATION-QUICK-START.md)
|
||||
- 📚 [完整指南](./BUILD-OPTIMIZATION-GUIDE.md)
|
||||
- 🔧 [构建脚本](./build-and-push.sh)
|
||||
- 🐳 [Registry 配置](./REGISTRY-CACHE-SETUP.md)
|
||||
|
||||
---
|
||||
|
||||
**版本**: v1.0.0
|
||||
**更新**: 2025-11-26
|
||||
**节省时间 = 更多创造价值的时间** ⚡
|
||||
@@ -1,228 +0,0 @@
|
||||
# ljwx-boot 构建修复说明
|
||||
|
||||
## 问题
|
||||
|
||||
构建 ljwx-boot 镜像时 Maven 依赖下载失败:
|
||||
```
|
||||
Remote host terminated the handshake
|
||||
Could not transfer artifact from aliyunmaven
|
||||
```
|
||||
|
||||
## 根本原因
|
||||
|
||||
1. **代理配置缺失**:boot、bigscreen、admin 的构建命令没有传递代理参数 `$proxy_args`
|
||||
2. **容器内代理地址错误**:使用 `127.0.0.1:7890` 而非 `host.docker.internal:7890`
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 添加代理参数到构建命令
|
||||
|
||||
**修改前**:
|
||||
```bash
|
||||
docker build --build-arg MAVEN_OPTS="-XX:+UseG1GC -Xmx1g" \
|
||||
-t $tag -t $latest_tag . \
|
||||
-f ljwx-boot/ljwx-boot-admin/Dockerfile.prod
|
||||
```
|
||||
|
||||
**修改后**:
|
||||
```bash
|
||||
docker build $proxy_args \
|
||||
--build-arg MAVEN_OPTS="-XX:+UseG1GC -Xmx1g" \
|
||||
-t $tag -t $latest_tag . \
|
||||
-f ljwx-boot/ljwx-boot-admin/Dockerfile.prod
|
||||
```
|
||||
|
||||
### 2. 使用容器内可访问的代理地址
|
||||
|
||||
在 `build-and-push.sh` 中:
|
||||
```bash
|
||||
# 容器内部代理地址
|
||||
local container_http_proxy="http://host.docker.internal:${PROXY_PORT}"
|
||||
local container_https_proxy="http://host.docker.internal:${PROXY_PORT}"
|
||||
local proxy_args="--build-arg HTTP_PROXY=$container_http_proxy ..."
|
||||
```
|
||||
|
||||
### 3. Dockerfile 接收并配置代理
|
||||
|
||||
在 `ljwx-boot/ljwx-boot-admin/Dockerfile.prod` 中:
|
||||
```dockerfile
|
||||
# 接收代理参数
|
||||
ARG HTTP_PROXY
|
||||
ARG HTTPS_PROXY
|
||||
ARG NO_PROXY
|
||||
|
||||
# 设置环境变量
|
||||
ENV HTTP_PROXY=${HTTP_PROXY} \
|
||||
HTTPS_PROXY=${HTTPS_PROXY} \
|
||||
NO_PROXY=${NO_PROXY}
|
||||
|
||||
# 配置 Maven settings.xml
|
||||
RUN mkdir -p /root/.m2 && \
|
||||
echo '<?xml version="1.0" encoding="UTF-8"?>' > /root/.m2/settings.xml && \
|
||||
# ... 镜像配置 ...
|
||||
if [ -n "$HTTP_PROXY" ]; then \
|
||||
PROXY_HOST=$(echo $HTTP_PROXY | sed -E 's|https?://([^:]+):.*|\1|'); \
|
||||
PROXY_PORT=$(echo $HTTP_PROXY | sed -E 's|https?://[^:]+:([0-9]+).*|\1|'); \
|
||||
echo ' <proxies>' >> /root/.m2/settings.xml && \
|
||||
echo ' <proxy>' >> /root/.m2/settings.xml && \
|
||||
echo ' <id>proxy</id>' >> /root/.m2/settings.xml && \
|
||||
echo ' <active>true</active>' >> /root/.m2/settings.xml && \
|
||||
echo ' <protocol>http</protocol>' >> /root/.m2/settings.xml && \
|
||||
echo " <host>$PROXY_HOST</host>" >> /root/.m2/settings.xml && \
|
||||
echo " <port>$PROXY_PORT</port>" >> /root/.m2/settings.xml && \
|
||||
echo ' </proxy>' >> /root/.m2/settings.xml && \
|
||||
echo ' </proxies>' >> /root/.m2/settings.xml; \
|
||||
fi
|
||||
```
|
||||
|
||||
## 构建流程
|
||||
|
||||
### ljwx-boot-starter 依赖构建
|
||||
|
||||
Dockerfile 中的构建顺序:
|
||||
```dockerfile
|
||||
# 1. 复制源代码
|
||||
COPY ljwx-boot-starter/ ../ljwx-boot-starter/
|
||||
COPY ljwx-boot/ ./
|
||||
|
||||
# 2. 先构建 starter 模块
|
||||
RUN cd ../ljwx-boot-starter && mvn clean install -DskipTests -B
|
||||
|
||||
# 3. 再构建主应用
|
||||
RUN mvn clean package -DskipTests -B
|
||||
```
|
||||
|
||||
### 目录结构
|
||||
|
||||
构建上下文(release 目录):
|
||||
```
|
||||
release/
|
||||
├── ljwx-boot-starter/ # starter 模块
|
||||
│ ├── pom.xml
|
||||
│ └── ljwx-boot-starter-*/
|
||||
├── ljwx-boot/ # 主应用
|
||||
│ ├── ljwx-boot-admin/
|
||||
│ │ └── Dockerfile.prod
|
||||
│ └── ...
|
||||
└── build-and-push.sh
|
||||
```
|
||||
|
||||
Dockerfile 工作目录:
|
||||
```
|
||||
/build/ # WORKDIR
|
||||
├── ljwx-boot-starter/ # COPY from ../ljwx-boot-starter/
|
||||
└── ljwx-boot/ # COPY from ljwx-boot/
|
||||
```
|
||||
|
||||
## 验证
|
||||
|
||||
### 1. 检查代理配置
|
||||
|
||||
构建时会显示:
|
||||
```bash
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 输出:
|
||||
📡 容器代理配置: http://host.docker.internal:7890
|
||||
🔨 构建应用镜像 ljwx-boot (架构: linux/amd64)...
|
||||
🔨 使用多阶段容器构建 Spring Boot JAR 包...
|
||||
💡 在容器内构建确保跨平台兼容性,使用代理和阿里云Maven镜像加速
|
||||
```
|
||||
|
||||
### 2. 检查 Maven settings.xml
|
||||
|
||||
在构建日志中会显示生成的 settings.xml:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
|
||||
<mirrors>
|
||||
<mirror>
|
||||
<id>aliyunmaven</id>
|
||||
<mirrorOf>*</mirrorOf>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
</mirror>
|
||||
</mirrors>
|
||||
<proxies>
|
||||
<proxy>
|
||||
<id>proxy</id>
|
||||
<active>true</active>
|
||||
<protocol>http</protocol>
|
||||
<host>host.docker.internal</host>
|
||||
<port>7890</port>
|
||||
<nonProxyHosts>localhost|127.0.0.1|*.local</nonProxyHosts>
|
||||
</proxy>
|
||||
</proxies>
|
||||
</settings>
|
||||
```
|
||||
|
||||
### 3. 测试构建
|
||||
|
||||
```bash
|
||||
# 1. 确保代理运行
|
||||
lsof -i :7890
|
||||
|
||||
# 2. 构建 boot 镜像
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 3. 观察 Maven 下载日志
|
||||
# 应该看到通过代理成功下载依赖
|
||||
```
|
||||
|
||||
## 修改的文件
|
||||
|
||||
1. **build-and-push.sh**
|
||||
- 添加 `$proxy_args` 到 boot、bigscreen、admin 构建命令
|
||||
- 使用 `host.docker.internal` 作为容器内代理地址
|
||||
- 添加代理配置显示信息
|
||||
|
||||
2. **ljwx-boot/ljwx-boot-admin/Dockerfile.prod**
|
||||
- 接收代理 ARG 参数
|
||||
- 设置代理 ENV 环境变量
|
||||
- 动态生成包含代理配置的 Maven settings.xml
|
||||
- 显示生成的配置供调试
|
||||
|
||||
## 其他应用
|
||||
|
||||
同样的修复也应用到:
|
||||
- ✅ **bigscreen**: Python pip 使用代理
|
||||
- ✅ **admin**: NPM 使用代理
|
||||
|
||||
## 故障排查
|
||||
|
||||
### Maven 仍然无法下载
|
||||
|
||||
**检查代理**:
|
||||
```bash
|
||||
# 1. 宿主机代理
|
||||
lsof -i :7890
|
||||
|
||||
# 2. 测试代理
|
||||
curl --proxy http://127.0.0.1:7890 https://maven.aliyun.com
|
||||
|
||||
# 3. 容器内测试
|
||||
docker run --rm alpine/curl curl http://host.docker.internal:7890
|
||||
```
|
||||
|
||||
### Settings.xml 未生成
|
||||
|
||||
**调试**:
|
||||
```bash
|
||||
# 查看构建日志中的 settings.xml 输出
|
||||
./build-and-push.sh boot 2>&1 | grep -A 30 "settings.xml"
|
||||
```
|
||||
|
||||
### ljwx-boot-starter 未找到
|
||||
|
||||
**检查目录**:
|
||||
```bash
|
||||
# 确认目录存在
|
||||
ls -la ljwx-boot-starter/
|
||||
|
||||
# 确认 pom.xml 存在
|
||||
ls -la ljwx-boot-starter/pom.xml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**日期**: 2025-11-26
|
||||
**状态**: ✅ 已修复
|
||||
-198
@@ -1,198 +0,0 @@
|
||||
# CI/CD 基础服务统一构建方案
|
||||
|
||||
## 🎯 目标
|
||||
- 解决端口冲突问题,统一使用3开头端口
|
||||
- 简化架构,移除冗余配置
|
||||
- 提供一键式部署体验
|
||||
|
||||
## 📋 端口规划
|
||||
|
||||
### 服务端口分配
|
||||
```
|
||||
服务名称 | Web端口 | 额外端口 | 说明
|
||||
-----------------|---------|---------|------------------
|
||||
Gitea | 33000 | 32222 | Git服务 + SSH
|
||||
Jenkins | 38080 | 35000 | CI/CD + Agent通信
|
||||
Registry | 35001 | - | Docker镜像仓库
|
||||
Registry UI | 35002 | - | 镜像仓库界面
|
||||
Prometheus | 37001 | - | 监控(预留)
|
||||
Grafana | 37002 | - | 监控面板(预留)
|
||||
```
|
||||
|
||||
## 🚀 有序搭建步骤
|
||||
|
||||
### 阶段1: 环境准备 (5分钟)
|
||||
```bash
|
||||
# 1. 停止现有服务,避免冲突
|
||||
./scripts/cleanup-existing.sh
|
||||
|
||||
# 2. 创建统一网络和目录
|
||||
./scripts/init-environment.sh
|
||||
|
||||
# 3. 检查端口可用性
|
||||
./scripts/check-ports.sh
|
||||
```
|
||||
|
||||
### 阶段2: 基础服务部署 (10分钟)
|
||||
```bash
|
||||
# 1. 启动Docker Registry (最基础)
|
||||
./scripts/deploy-registry.sh
|
||||
|
||||
# 2. 启动Gitea (代码仓库)
|
||||
./scripts/deploy-gitea.sh
|
||||
|
||||
# 3. 验证基础服务
|
||||
./scripts/verify-basic-services.sh
|
||||
```
|
||||
|
||||
### 阶段3: CI/CD部署 (15分钟)
|
||||
```bash
|
||||
# 1. 启动Jenkins (完全自动化配置)
|
||||
./scripts/deploy-jenkins.sh
|
||||
|
||||
# 2. 配置服务集成
|
||||
./scripts/setup-integration.sh
|
||||
|
||||
# 3. 创建示例项目
|
||||
./scripts/create-demo-projects.sh
|
||||
```
|
||||
|
||||
### 阶段4: 验证和优化 (5分钟)
|
||||
```bash
|
||||
# 1. 完整功能测试
|
||||
./scripts/run-integration-tests.sh
|
||||
|
||||
# 2. 性能优化
|
||||
./scripts/optimize-services.sh
|
||||
|
||||
# 3. 创建维护计划
|
||||
./scripts/setup-maintenance.sh
|
||||
```
|
||||
|
||||
## 📂 建议的目录结构整理
|
||||
|
||||
```
|
||||
infra/
|
||||
├── configs/ # 统一配置文件
|
||||
│ ├── gitea.env # Gitea环境变量
|
||||
│ ├── jenkins.env # Jenkins环境变量
|
||||
│ └── registry.env # Registry环境变量
|
||||
├── docker/
|
||||
│ └── compose/
|
||||
│ ├── core-services.yml # 核心服务组合
|
||||
│ ├── gitea.yml # Gitea独立配置
|
||||
│ ├── jenkins.yml # Jenkins独立配置
|
||||
│ └── registry.yml # Registry独立配置
|
||||
├── jenkins/
|
||||
│ ├── casc/ # Configuration as Code
|
||||
│ ├── shared-library/ # Pipeline共享库
|
||||
│ └── templates/ # 项目模板
|
||||
├── scripts/ # 部署和管理脚本
|
||||
│ ├── deploy/ # 部署脚本
|
||||
│ ├── maintenance/ # 维护脚本
|
||||
│ └── utils/ # 工具脚本
|
||||
└── docs/ # 文档
|
||||
├── deployment.md # 部署指南
|
||||
├── maintenance.md # 维护指南
|
||||
└── troubleshooting.md # 故障排查
|
||||
```
|
||||
|
||||
## 🔧 关键配置变更
|
||||
|
||||
### 服务访问地址
|
||||
```
|
||||
原来 → 现在
|
||||
http://localhost:3000 → http://localhost:33000 (Gitea)
|
||||
http://localhost:8081 → http://localhost:38080 (Jenkins)
|
||||
http://localhost:5001 → http://localhost:35001 (Registry)
|
||||
http://localhost:5002 → http://localhost:35002 (Registry UI)
|
||||
```
|
||||
|
||||
### 环境变量统一
|
||||
```bash
|
||||
# configs/global.env
|
||||
GITEA_PORT=33000
|
||||
GITEA_SSH_PORT=32222
|
||||
GITEA_URL=http://localhost:33000
|
||||
|
||||
JENKINS_PORT=38080
|
||||
JENKINS_AGENT_PORT=35000
|
||||
JENKINS_URL=http://localhost:38080
|
||||
|
||||
REGISTRY_PORT=35001
|
||||
REGISTRY_UI_PORT=35002
|
||||
REGISTRY_URL=localhost:35001
|
||||
```
|
||||
|
||||
## ⚡ 一键部署命令
|
||||
|
||||
```bash
|
||||
# 完整自动化部署
|
||||
./build-infra.sh --full-auto
|
||||
|
||||
# 分步骤部署
|
||||
./build-infra.sh --step-by-step
|
||||
|
||||
# 仅更新端口配置
|
||||
./build-infra.sh --update-ports-only
|
||||
```
|
||||
|
||||
## 📊 部署验证检查点
|
||||
|
||||
### 基础服务检查
|
||||
- [ ] Docker Registry 响应正常 (http://localhost:35001/v2/)
|
||||
- [ ] Registry UI 界面可访问 (http://localhost:35002)
|
||||
- [ ] Gitea 服务启动正常 (http://localhost:33000)
|
||||
- [ ] Gitea 健康检查通过 (http://localhost:33000/api/healthz)
|
||||
|
||||
### CI/CD功能检查
|
||||
- [ ] Jenkins 自动配置完成 (http://localhost:38080)
|
||||
- [ ] Jenkins 管理员登录成功 (admin/admin123)
|
||||
- [ ] Gitea 集成配置正确
|
||||
- [ ] 多平台构建环境就绪
|
||||
- [ ] 示例Pipeline创建成功
|
||||
|
||||
### 集成测试检查
|
||||
- [ ] Gitea Webhook 触发Jenkins构建
|
||||
- [ ] 多平台镜像构建成功
|
||||
- [ ] 镜像推送到Registry正常
|
||||
- [ ] 从Registry拉取镜像正常
|
||||
|
||||
## 🛡️ 安全和优化
|
||||
|
||||
### 安全加固
|
||||
- Jenkins运行在非root用户下
|
||||
- 使用环境变量管理敏感信息
|
||||
- 网络隔离和访问控制
|
||||
- 定期安全更新
|
||||
|
||||
### 性能优化
|
||||
- 合理的资源限制配置
|
||||
- 定期清理无用数据
|
||||
- 监控服务性能指标
|
||||
- 自动化备份策略
|
||||
|
||||
## 🔄 维护计划
|
||||
|
||||
### 日常维护
|
||||
```bash
|
||||
# 服务健康检查
|
||||
./scripts/health-check.sh
|
||||
|
||||
# 数据备份
|
||||
./scripts/backup-all.sh
|
||||
|
||||
# 系统清理
|
||||
./scripts/cleanup-system.sh
|
||||
```
|
||||
|
||||
### 定期维护
|
||||
- 每周:服务状态检查和日志清理
|
||||
- 每月:完整备份和性能优化
|
||||
- 每季度:安全更新和配置审查
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
- 配置问题: 查看 docs/troubleshooting.md
|
||||
- 性能优化: 查看 docs/optimization.md
|
||||
- 升级指南: 查看 docs/upgrade.md
|
||||
@@ -1,432 +0,0 @@
|
||||
# LJWX 镜像构建指南 (OrbStack + Harbor)
|
||||
|
||||
## 📋 概述
|
||||
|
||||
本文档说明如何使用优化后的 `build-and-push.sh` 脚本,将镜像构建并推送到本地 Harbor 仓库。
|
||||
|
||||
### 主要变更
|
||||
|
||||
- ✅ **运行时**: 从 Docker Desktop 切换到 OrbStack
|
||||
- ✅ **镜像仓库**: 从阿里云切换到本地 Harbor (localhost:8080)
|
||||
- ✅ **健康检查**: 自动检查 Harbor 服务状态
|
||||
- ✅ **多架构支持**: 支持 linux/amd64 和 linux/arm64
|
||||
|
||||
## 🔧 前置要求
|
||||
|
||||
### 1. 安装 OrbStack
|
||||
|
||||
```bash
|
||||
# 如果已安装 Docker Desktop,建议先卸载
|
||||
# 然后安装 OrbStack (macOS)
|
||||
brew install --cask orbstack
|
||||
|
||||
# 启动 OrbStack
|
||||
open -a OrbStack
|
||||
```
|
||||
|
||||
### 2. 部署 Harbor
|
||||
|
||||
确保 Harbor 服务运行在 `localhost:8080`:
|
||||
|
||||
```bash
|
||||
# 检查 Harbor 是否运行
|
||||
curl -f http://localhost:8080/api/v2.0/health
|
||||
|
||||
# 如果 Harbor 未运行,启动它
|
||||
docker-compose -f harbor-compose.yml up -d
|
||||
|
||||
# 访问 Harbor Web UI
|
||||
open http://localhost:8080
|
||||
```
|
||||
|
||||
### 3. 验证环境
|
||||
|
||||
```bash
|
||||
# 检查 Docker 是否使用 OrbStack
|
||||
docker context ls
|
||||
# 应该显示 orbstack 或 default
|
||||
|
||||
# 检查 Docker 版本
|
||||
docker --version
|
||||
|
||||
# 检查 buildx 支持
|
||||
docker buildx ls
|
||||
```
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
### 基本用法
|
||||
|
||||
```bash
|
||||
# 查看帮助
|
||||
./build-and-push.sh
|
||||
|
||||
# 构建所有镜像(应用 + 监控)
|
||||
./build-and-push.sh all
|
||||
|
||||
# 仅构建应用镜像
|
||||
./build-and-push.sh apps
|
||||
|
||||
# 仅构建监控镜像
|
||||
./build-and-push.sh monitoring
|
||||
|
||||
# 构建单个镜像
|
||||
./build-and-push.sh boot
|
||||
./build-and-push.sh admin
|
||||
./build-and-push.sh bigscreen
|
||||
```
|
||||
|
||||
### 配置选项
|
||||
|
||||
#### 使用环境变量
|
||||
|
||||
```bash
|
||||
# 自定义 Harbor 地址
|
||||
HARBOR_HOST=harbor.example.com:8080 ./build-and-push.sh apps
|
||||
|
||||
# 自定义 Harbor 凭证
|
||||
HARBOR_USERNAME=myuser HARBOR_PASSWORD=mypass ./build-and-push.sh apps
|
||||
|
||||
# 仅构建,不推送
|
||||
PUSH_TO_REGISTRY=false ./build-and-push.sh apps
|
||||
```
|
||||
|
||||
#### 修改配置文件
|
||||
|
||||
编辑 `monitoring-versions.env`:
|
||||
|
||||
```bash
|
||||
# Harbor 配置
|
||||
HARBOR_HOST=localhost:8080 # Harbor 地址
|
||||
HARBOR_USERNAME=admin # Harbor 用户名
|
||||
HARBOR_PASSWORD=admin123 # Harbor 密码
|
||||
|
||||
# 构建配置
|
||||
REGISTRY=localhost:8080/ljwx # 镜像仓库地址
|
||||
PLATFORMS=linux/amd64,linux/arm64 # 构建架构
|
||||
LOCAL_BUILD=false # 多架构构建
|
||||
PUSH_TO_REGISTRY=true # 推送到 Harbor
|
||||
```
|
||||
|
||||
## 📦 构建流程
|
||||
|
||||
### 1. 完整构建流程
|
||||
|
||||
```bash
|
||||
# Step 1: 检查 Harbor 状态
|
||||
curl -f http://localhost:8080/api/v2.0/health
|
||||
|
||||
# Step 2: 准备数据(如果需要构建 MySQL 镜像)
|
||||
./export-data.sh
|
||||
|
||||
# Step 3: 构建所有镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# Step 4: 验证镜像已推送到 Harbor
|
||||
# 访问 http://localhost:8080
|
||||
# 登录: admin / admin123
|
||||
# 查看 ljwx 项目下的镜像
|
||||
```
|
||||
|
||||
### 2. 增量构建流程
|
||||
|
||||
```bash
|
||||
# 仅构建并推送后端服务
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 仅构建并推送前端服务
|
||||
./build-and-push.sh admin
|
||||
|
||||
# 仅构建并推送大屏服务
|
||||
./build-and-push.sh bigscreen
|
||||
```
|
||||
|
||||
### 3. 本地测试流程
|
||||
|
||||
```bash
|
||||
# 构建但不推送到 Harbor
|
||||
PUSH_TO_REGISTRY=false ./build-and-push.sh boot
|
||||
|
||||
# 本地运行测试
|
||||
docker run -p 9998:9998 localhost:8080/ljwx/ljwx-boot:2.0.3
|
||||
```
|
||||
|
||||
## 🔍 健康检查
|
||||
|
||||
脚本会自动执行以下健康检查:
|
||||
|
||||
### 1. Harbor 健康检查
|
||||
|
||||
```bash
|
||||
# 脚本自动检查
|
||||
GET http://localhost:8080/api/v2.0/health
|
||||
|
||||
# 如果 Harbor 不可用,脚本会提示:
|
||||
⚠️ 无法连接到 Harbor (http://localhost:8080/api/v2.0/health)
|
||||
💡 请确认 Harbor 服务已启动:
|
||||
- 访问: http://localhost:8080
|
||||
- 检查 Docker 容器: docker ps | grep harbor
|
||||
|
||||
是否继续构建(不推送到 Harbor)? (y/n)
|
||||
```
|
||||
|
||||
### 2. 手动健康检查
|
||||
|
||||
```bash
|
||||
# 检查 Harbor API
|
||||
curl http://localhost:8080/api/v2.0/health
|
||||
|
||||
# 检查 Harbor Web UI
|
||||
open http://localhost:8080
|
||||
|
||||
# 检查 Harbor 容器
|
||||
docker ps | grep harbor
|
||||
```
|
||||
|
||||
## 📊 镜像管理
|
||||
|
||||
### 查看本地镜像
|
||||
|
||||
```bash
|
||||
# 查看所有 LJWX 镜像
|
||||
docker images | grep localhost:8080/ljwx
|
||||
|
||||
# 查看特定镜像
|
||||
docker images localhost:8080/ljwx/ljwx-boot
|
||||
```
|
||||
|
||||
### 查看 Harbor 镜像
|
||||
|
||||
1. **Web UI 方式**:
|
||||
- 访问 http://localhost:8080
|
||||
- 登录: admin / admin123
|
||||
- 进入 `ljwx` 项目
|
||||
- 查看镜像列表
|
||||
|
||||
2. **API 方式**:
|
||||
```bash
|
||||
# 列出所有仓库
|
||||
curl -u admin:admin123 http://localhost:8080/api/v2.0/projects/ljwx/repositories
|
||||
|
||||
# 列出镜像标签
|
||||
curl -u admin:admin123 http://localhost:8080/api/v2.0/projects/ljwx/repositories/ljwx-boot/artifacts
|
||||
```
|
||||
|
||||
### 拉取镜像
|
||||
|
||||
```bash
|
||||
# 从 Harbor 拉取镜像
|
||||
docker pull localhost:8080/ljwx/ljwx-boot:2.0.3
|
||||
|
||||
# 拉取最新版本
|
||||
docker pull localhost:8080/ljwx/ljwx-boot:latest
|
||||
```
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### 问题 1: Harbor 连接失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
⚠️ 无法连接到 Harbor (http://localhost:8080/api/v2.0/health)
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Harbor 是否运行
|
||||
docker ps | grep harbor
|
||||
|
||||
# 2. 启动 Harbor
|
||||
docker-compose -f harbor-compose.yml up -d
|
||||
|
||||
# 3. 等待 Harbor 完全启动(约 30 秒)
|
||||
sleep 30
|
||||
|
||||
# 4. 再次检查健康状态
|
||||
curl http://localhost:8080/api/v2.0/health
|
||||
```
|
||||
|
||||
### 问题 2: 登录失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
❌ Harbor 登录失败,请检查凭据
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查凭证
|
||||
echo "用户名: admin"
|
||||
echo "密码: admin123"
|
||||
|
||||
# 2. 手动登录测试
|
||||
docker login localhost:8080
|
||||
# Username: admin
|
||||
# Password: admin123
|
||||
|
||||
# 3. 检查 Harbor 配置
|
||||
cat monitoring-versions.env | grep HARBOR
|
||||
```
|
||||
|
||||
### 问题 3: 镜像推送失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
⚠️ ljwx-boot 镜像推送失败
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 insecure-registries 配置
|
||||
# OrbStack 配置位置: ~/.orbstack/config/docker.json
|
||||
cat ~/.orbstack/config/docker.json | grep insecure
|
||||
|
||||
# 2. 添加 insecure-registries
|
||||
# 编辑 ~/.orbstack/config/docker.json
|
||||
{
|
||||
"insecure-registries": [
|
||||
"localhost:8080",
|
||||
"127.0.0.1:8080"
|
||||
]
|
||||
}
|
||||
|
||||
# 3. 重启 OrbStack
|
||||
killall OrbStack
|
||||
open -a OrbStack
|
||||
|
||||
# 4. 重新推送
|
||||
./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 问题 4: 多架构构建失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
ERROR: multiple platforms feature is currently not supported for docker driver
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 创建 buildx builder
|
||||
docker buildx create --name multiarch-builder --use
|
||||
|
||||
# 2. 启动 builder
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
# 3. 重新构建
|
||||
./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 问题 5: OrbStack 不可用
|
||||
|
||||
**症状**:
|
||||
```
|
||||
Cannot connect to the Docker daemon
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 OrbStack 是否运行
|
||||
ps aux | grep OrbStack
|
||||
|
||||
# 2. 启动 OrbStack
|
||||
open -a OrbStack
|
||||
|
||||
# 3. 检查 Docker context
|
||||
docker context ls
|
||||
|
||||
# 4. 切换到 OrbStack context(如果需要)
|
||||
docker context use orbstack
|
||||
```
|
||||
|
||||
## 📝 最佳实践
|
||||
|
||||
### 1. 构建前准备
|
||||
|
||||
```bash
|
||||
# 检查 Harbor 状态
|
||||
curl -f http://localhost:8080/api/v2.0/health || exit 1
|
||||
|
||||
# 检查磁盘空间
|
||||
df -h
|
||||
|
||||
# 清理旧镜像(可选)
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
### 2. 分批构建
|
||||
|
||||
```bash
|
||||
# 先构建基础设施镜像
|
||||
./build-and-push.sh mysql redis
|
||||
|
||||
# 再构建应用镜像
|
||||
./build-and-push.sh boot admin bigscreen
|
||||
|
||||
# 最后构建监控镜像
|
||||
./build-and-push.sh monitoring
|
||||
```
|
||||
|
||||
### 3. 版本管理
|
||||
|
||||
```bash
|
||||
# 更新版本号
|
||||
vim monitoring-versions.env
|
||||
# 修改 LJWX_VERSION=2.0.4
|
||||
|
||||
# 构建新版本
|
||||
./build-and-push.sh all
|
||||
|
||||
# 验证新版本
|
||||
docker images localhost:8080/ljwx/ljwx-boot
|
||||
```
|
||||
|
||||
### 4. 备份镜像
|
||||
|
||||
```bash
|
||||
# 导出镜像到文件
|
||||
docker save localhost:8080/ljwx/ljwx-boot:2.0.3 -o ljwx-boot-2.0.3.tar
|
||||
|
||||
# 从文件导入镜像
|
||||
docker load -i ljwx-boot-2.0.3.tar
|
||||
```
|
||||
|
||||
## 🎯 常用命令速查
|
||||
|
||||
```bash
|
||||
# 健康检查
|
||||
curl http://localhost:8080/api/v2.0/health
|
||||
|
||||
# 登录 Harbor
|
||||
docker login localhost:8080
|
||||
|
||||
# 查看镜像
|
||||
docker images | grep localhost:8080/ljwx
|
||||
|
||||
# 构建所有镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# 构建单个镜像
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 拉取镜像
|
||||
docker pull localhost:8080/ljwx/ljwx-boot:latest
|
||||
|
||||
# 清理缓存
|
||||
./build-and-push.sh cache-clean
|
||||
|
||||
# 查看 Harbor 项目
|
||||
open http://localhost:8080
|
||||
```
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [OrbStack 文档](https://docs.orbstack.dev/)
|
||||
- [Harbor 文档](https://goharbor.io/docs/)
|
||||
- [Docker Buildx 文档](https://docs.docker.com/buildx/working-with-buildx/)
|
||||
- [主项目文档](./DOCKER_README.md)
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-25
|
||||
**版本**: 1.3.0
|
||||
@@ -1,103 +0,0 @@
|
||||
# CDN 本地化替换总结
|
||||
|
||||
## 概述
|
||||
已成功将所有模板中的外部CDN链接替换为本地文件,提高系统稳定性和加载速度。
|
||||
|
||||
## 已处理的项目
|
||||
- ✅ ljwx-bigscreen
|
||||
- ✅ ljwx-admin (未发现CDN链接)
|
||||
|
||||
## 已下载的本地资源
|
||||
|
||||
### JavaScript 库
|
||||
- `/static/js/chart.js` - Chart.js 图表库
|
||||
- `/static/js/axios.min.js` - Axios HTTP 客户端
|
||||
- `/static/js/socket.io.js` - Socket.IO 实时通信
|
||||
- `/static/js/vue.min.js` - Vue.js 2.7.14
|
||||
- `/static/js/element-ui.min.js` - Element UI 组件库
|
||||
- `/static/js/leaflet.awesome-markers.js` - Leaflet 地图标记
|
||||
- `/static/js/bootstrap-4.4.1.min.js` - Bootstrap 4.4.1 JS
|
||||
- `/static/js/pyecharts.echarts.min.js` - PyECharts ECharts
|
||||
|
||||
### CSS 样式文件
|
||||
- `/static/css/element-ui.min.css` - Element UI 样式
|
||||
- `/static/css/fontawesome-6.0.0.min.css` - Font Awesome 6.0.0
|
||||
- `/static/css/leaflet.awesome-markers.css` - Leaflet 标记样式
|
||||
- `/static/css/leaflet.awesome.rotate.min.css` - Leaflet 旋转样式
|
||||
- `/static/css/bootstrap-3.0.0.min.css` - Bootstrap 3.0.0
|
||||
- `/static/css/fortawesome-6.2.0.min.css` - Font Awesome 6.2.0
|
||||
- `/static/css/bootstrap-4.4.1.min.css` - Bootstrap 4.4.1
|
||||
|
||||
## 已处理的模板文件
|
||||
|
||||
### ljwx-bigscreen 目录
|
||||
1. `/templates/test_report.html`
|
||||
- Chart.js: `https://cdn.jsdelivr.net/npm/chart.js` → `/static/js/chart.js`
|
||||
- Axios: `https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js` → `/static/js/axios.min.js`
|
||||
|
||||
2. `/bigscreen/test_baseline_chart.html`
|
||||
- ECharts: `https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js` → `/static/js/echarts-5.4.0.min.js`
|
||||
|
||||
3. `/bigscreen/templates/health_profile.html`
|
||||
- Bootstrap CSS: `https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css` → `/static/css/bootstrap-5.1.3.min.css`
|
||||
- Font Awesome: `https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css` → `/static/css/fontawesome-6.0.0.min.css`
|
||||
- Bootstrap JS: `https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js` → `/static/js/bootstrap-5.1.3.bundle.min.js`
|
||||
|
||||
4. `/bigscreen/templates/personal_new.html`
|
||||
- Element UI CSS: `https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.min.css` → `/static/css/element-ui.min.css`
|
||||
- Vue.js: `https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.min.js` → `/static/js/vue.min.js`
|
||||
- Element UI JS: `https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.min.js` → `/static/js/element-ui.min.js`
|
||||
- Axios: `https://cdn.bootcdn.net/ajax/libs/axios/1.6.8/axios.min.js` → `/static/js/axios.min.js`
|
||||
- ECharts: `https://cdn.bootcdn.net/ajax/libs/echarts/5.4.3/echarts.min.js` → `/static/js/echarts-5.4.0.min.js`
|
||||
|
||||
5. `/bigscreen/templates/track_view.html`
|
||||
- ECharts: `https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js` → `/static/js/echarts-5.4.0.min.js`
|
||||
|
||||
6. `/bigscreen/templates/system_event_alert.html`
|
||||
- Bootstrap CSS: `https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css` → `/static/css/bootstrap-5.1.3.min.css`
|
||||
- Font Awesome: `https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css` → `/static/css/font-awesome-4.7.0.min.css`
|
||||
- Bootstrap JS: `https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js` → `/static/js/bootstrap-5.1.3.bundle.min.js`
|
||||
|
||||
7. `/bigscreen/bigScreen/templates/config_management.html`
|
||||
- Font Awesome: `https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css` → `/static/css/fontawesome-6.0.0.min.css`
|
||||
|
||||
8. `/bigscreen/bigScreen/templates/user_info_map.html`
|
||||
- Leaflet markers: `https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js` → `/static/js/leaflet.awesome-markers.js`
|
||||
- Bootstrap: `https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css` → `/static/css/bootstrap-3.0.0.min.css`
|
||||
- Font Awesome: `https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css` → `/static/css/fortawesome-6.2.0.min.css`
|
||||
- Leaflet CSS: `https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css` → `/static/css/leaflet.awesome-markers.css`
|
||||
- Leaflet rotate: `https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css` → `/static/css/leaflet.awesome.rotate.min.css`
|
||||
|
||||
9. `/bigscreen/test_report.html`
|
||||
- Chart.js: `https://cdn.jsdelivr.net/npm/chart.js` → `/static/js/chart.js`
|
||||
|
||||
10. `/bigscreen/drink_flavors.html`
|
||||
- PyECharts: `https://assets.pyecharts.org/assets/v5/echarts.min.js` → `/static/js/pyecharts.echarts.min.js`
|
||||
|
||||
11. `/bigscreen/bigScreen/test.html`
|
||||
- Bootstrap: `https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css` → `/static/css/bootstrap-4.4.1.min.css`
|
||||
|
||||
## 保留的外部服务
|
||||
以下服务因业务需要保留为外部链接:
|
||||
- 高德地图 API: `https://webapi.amap.com/maps?v=2.0&key=*` (需要API密钥)
|
||||
- 高德地图 Loca: `https://webapi.amap.com/loca?v=2.0.0&key=*` (需要API密钥)
|
||||
|
||||
## 影响与优势
|
||||
1. **离线支持**: 系统可在无互联网环境下正常运行
|
||||
2. **性能提升**: 消除外部CDN依赖,加快页面加载速度
|
||||
3. **稳定性**: 避免CDN服务中断影响系统功能
|
||||
4. **安全性**: 减少外部依赖,降低安全风险
|
||||
5. **内网部署**: 支持完全内网环境部署
|
||||
|
||||
## 验证状态
|
||||
✅ 所有模板中的CDN链接已成功替换
|
||||
✅ 本地静态资源已下载到 `/bigscreen/static/` 目录
|
||||
✅ 文件路径格式统一使用 `/static/` 前缀
|
||||
✅ 验证无遗漏的CDN链接
|
||||
|
||||
## 注意事项
|
||||
1. 确保Flask应用的`static_folder`配置正确指向`../static`
|
||||
2. 定期更新本地资源文件以获取安全补丁和新功能
|
||||
3. 高德地图API仍需要外网访问,如需完全内网部署可考虑替换为其他地图方案
|
||||
|
||||
生成时间: 2025-09-06
|
||||
@@ -1,268 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Repository Overview
|
||||
|
||||
This is a comprehensive CI/CD infrastructure setup for Mac Studio M2 environment, featuring Jenkins, Gitea, and Docker Registry with full automation support.
|
||||
|
||||
## Quick Start Commands
|
||||
|
||||
```bash
|
||||
# Complete automated deployment - fully configured Jenkins
|
||||
./jenkins-auto-deploy.sh
|
||||
|
||||
# Daily management
|
||||
./jenkins-manager.sh start # Start services
|
||||
./jenkins-manager.sh stop # Stop services
|
||||
./jenkins-manager.sh status # Check status
|
||||
./jenkins-manager.sh logs # View Jenkins logs
|
||||
./jenkins-manager.sh backup # Backup configuration
|
||||
./jenkins-manager.sh health # Health check
|
||||
|
||||
# Simple quick start (manual setup required)
|
||||
./quick-start-jenkins.sh
|
||||
```
|
||||
|
||||
## Service Access Points
|
||||
|
||||
- **Jenkins**: http://localhost:8081 (admin/admin123 for auto-deployed)
|
||||
- **Docker Registry**: http://localhost:5001
|
||||
- **Registry UI**: http://localhost:5002
|
||||
- **Gitea**: http://192.168.1.6:3000
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
- **Jenkins LTS**: CI/CD server with Configuration as Code (CasC)
|
||||
- **Gitea**: Git repository server with Actions support
|
||||
- **Docker Registry**: Local container registry for multi-platform images
|
||||
- **Multi-platform Build**: Supports linux/amd64 and linux/arm64
|
||||
|
||||
### Key Directories
|
||||
```
|
||||
infra/
|
||||
├── jenkins-auto-deploy.sh # ⭐ Main automated deployment
|
||||
├── jenkins-manager.sh # Daily management script
|
||||
├── docker/compose/
|
||||
│ ├── jenkins-simple.yml # Primary Jenkins Compose file
|
||||
│ ├── jenkins-complete-auto.yml # Full auto-configuration
|
||||
│ └── jenkins/
|
||||
│ ├── casc/jenkins.yaml # ⭐ Configuration as Code
|
||||
│ ├── plugins.txt # Jenkins plugins list
|
||||
│ ├── init-scripts/ # Initialization scripts
|
||||
│ ├── shared-library/ # Pipeline shared libraries
|
||||
│ └── templates/ # Dockerfile & Pipeline templates
|
||||
├── deployment/scripts/ # Management & integration scripts
|
||||
└── docs/ # Documentation and guides
|
||||
```
|
||||
|
||||
## Docker Configuration Files
|
||||
|
||||
### Main Compose Files
|
||||
- `jenkins-simple.yml` - Basic Jenkins setup
|
||||
- `jenkins-complete-auto.yml` - Full automation with CasC
|
||||
- `gitea-compose.yml` - Gitea service
|
||||
- `registry-compose.yml` - Docker registry
|
||||
|
||||
### Jenkins Automation
|
||||
The Jenkins instance uses Configuration as Code located at `docker/compose/jenkins/casc/jenkins.yaml` which includes:
|
||||
- Auto-configured tools (Git, Maven, Gradle, NodeJS, Docker, Python)
|
||||
- Pre-configured credentials (Gitea, Registry, SSH)
|
||||
- Cloud configurations (Docker, Kubernetes)
|
||||
- Security settings and user management
|
||||
- Pre-created jobs (multi-platform builds, system monitoring)
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### For Infrastructure Changes
|
||||
1. Modify configuration files in `docker/compose/jenkins/casc/`
|
||||
2. Test with: `./jenkins-manager.sh restart`
|
||||
3. Use: `./jenkins-manager.sh health` to verify
|
||||
|
||||
### For Adding New Services
|
||||
1. Create/modify compose files in `docker/compose/`
|
||||
2. Update management scripts in `deployment/scripts/`
|
||||
3. Test deployment with appropriate script
|
||||
|
||||
### Pipeline Development
|
||||
- Templates available in `docker/compose/jenkins/templates/`
|
||||
- Shared libraries in `docker/compose/jenkins/shared-library/`
|
||||
- Multi-platform Docker builds supported by default
|
||||
|
||||
## Important Configuration Files
|
||||
|
||||
- `docker/compose/jenkins/casc/jenkins.yaml` - Jenkins Configuration as Code
|
||||
- `docker/compose/jenkins/plugins.txt` - Jenkins plugins
|
||||
- `jenkins-manager.sh` - Primary management interface
|
||||
- `deployment/scripts/` - Various automation scripts
|
||||
|
||||
## Multi-Platform Build Support
|
||||
|
||||
All Docker builds support both linux/amd64 and linux/arm64 platforms. The Jenkins configuration includes buildx setup and multi-platform pipeline templates.
|
||||
|
||||
## Backup and Recovery
|
||||
|
||||
```bash
|
||||
./jenkins-manager.sh backup # Create backup
|
||||
./jenkins-manager.sh restore # Restore from backup
|
||||
```
|
||||
|
||||
Backups are stored in `backup/jenkins/` with timestamps.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. Check service health: `./jenkins-manager.sh health`
|
||||
2. View logs: `./jenkins-manager.sh logs`
|
||||
3. Restart services: `./jenkins-manager.sh restart`
|
||||
4. Full reset: `./jenkins-manager.sh cleanup` (⚠️ destructive)
|
||||
|
||||
Detailed troubleshooting guide available at `docs/troubleshooting.md`.
|
||||
|
||||
## ljwx-boot 健康定时任务系统
|
||||
|
||||
### 健康定时任务概览
|
||||
|
||||
ljwx-boot 包含一套完整的健康数据处理定时任务系统,主要包括:
|
||||
|
||||
1. **HealthBaselineScoreTasks** - 核心定时任务类
|
||||
- 位置: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/health/task/HealthBaselineScoreTasks.java`
|
||||
- 使用 `@Scheduled` 注解实现多个定时任务
|
||||
- 支持分表架构和并行处理
|
||||
|
||||
2. **HealthRecommendationJob** - 健康建议生成作业
|
||||
- 位置: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/health/job/HealthRecommendationJob.java`
|
||||
- 实现 Quartz Job 接口,集成到 mon_scheduler 系统
|
||||
|
||||
### 定时任务执行时间表
|
||||
|
||||
```
|
||||
01:00 - 权重配置验证任务 (validateWeightConfigurations)
|
||||
02:00 - 生成用户健康基线 (generateUserHealthBaseline)
|
||||
02:05 - 生成部门健康基线聚合 (generateDepartmentHealthBaseline)
|
||||
02:10 - 生成组织健康基线 (generateOrgHealthBaseline)
|
||||
02:15 - 生成部门健康评分 (generateDepartmentHealthScore)
|
||||
04:00 - 生成用户健康评分 (generateHealthScore)
|
||||
04:10 - 生成组织健康评分 (generateOrgHealthScore)
|
||||
05:00 - 数据清理任务 (cleanupOldData)
|
||||
|
||||
每月1日凌晨 - 按月分表任务 (archiveAndResetUserHealthTable)
|
||||
```
|
||||
|
||||
### 管理界面
|
||||
|
||||
前端管理界面位于:
|
||||
- **ljwx-admin**: `/src/views/monitor/scheduler/index.vue`
|
||||
- **API接口**: `/src/service/api/monitor/scheduler.ts`
|
||||
- **访问地址**: http://localhost:3000/#/monitor/scheduler
|
||||
|
||||
管理界面功能:
|
||||
- 查看所有调度任务状态
|
||||
- 立即执行任务 (immediate)
|
||||
- 暂停/恢复任务 (pause/resume)
|
||||
- 暂停/恢复任务组 (pauseGroup/resumeGroup)
|
||||
- 编辑任务配置
|
||||
- 删除任务
|
||||
|
||||
### 核心功能
|
||||
|
||||
1. **多表支持**: 自动检测并查询主表和月度分表
|
||||
2. **并行处理**: 使用线程池并行处理多个健康特征
|
||||
3. **异常检测**: 自动检测和修复数据异常
|
||||
4. **覆盖率监控**: 检查各个特征的数据覆盖率
|
||||
5. **权重计算**: 集成客户自定义权重配置
|
||||
|
||||
### 健康特征支持
|
||||
|
||||
系统支持以下健康指标的基线和评分计算:
|
||||
- heart_rate (心率)
|
||||
- blood_oxygen (血氧)
|
||||
- temperature (体温)
|
||||
- pressure_high/pressure_low (血压)
|
||||
- stress (压力)
|
||||
- step (步数)
|
||||
- calorie (卡路里)
|
||||
- distance (距离)
|
||||
- sleep (睡眠)
|
||||
|
||||
### 调试说明
|
||||
|
||||
**重要**: 调试过程中不要重启 ljwx-boot 服务,用户会手动重启。
|
||||
|
||||
使用以下命令检查服务状态:
|
||||
```bash
|
||||
cd ljwx-boot && ./run-local.sh status # 检查状态
|
||||
# 不要使用 ./run-local.sh start 或 ./run-local.sh restart
|
||||
```
|
||||
|
||||
### 任务监控
|
||||
|
||||
1. **日志监控**: 所有任务执行都有详细的日志输出
|
||||
2. **性能指标**: 记录任务执行时间和处理数据量
|
||||
3. **异常处理**: 自动捕获和记录异常,不会影响其他任务
|
||||
4. **状态跟踪**: 通过 mon_scheduler 系统跟踪任务状态
|
||||
|
||||
### IP地址解析修复
|
||||
|
||||
系统已修复IPv6地址解析问题:
|
||||
- **问题**: IPv6 localhost地址 "0:0:0:0:0:0:0:1" 无法被 ip2region 库识别
|
||||
- **解决**: 在 `IPUtil.java` 中添加IPv6和本地地址检测
|
||||
- **位置**: `ljwx-boot/ljwx-boot-common/src/main/java/com/ljwx/common/util/IPUtil.java`
|
||||
- **处理策略**:
|
||||
- 本地地址 (127.0.0.1, ::1, 0:0:0:0:0:0:0:1) → "本地|本地|本地|本地"
|
||||
- IPv6地址 → "IPv6|IPv6|IPv6|IPv6"
|
||||
- 内网IP → "内网|内网|内网|内网"
|
||||
- 查询失败 → "未知|未知|未知|未知"
|
||||
|
||||
### 权重缓存表修复
|
||||
|
||||
系统已修复权重计算功能:
|
||||
- **问题**: `t_weight_cache` 表不存在导致健康评分任务失败
|
||||
- **解决**: 创建了完整的权重缓存表结构
|
||||
- **位置**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/health/service/WeightCalculationService.java`
|
||||
- **表结构**: 支持用户权重配置、岗位风险倍数、归一化权重等功能
|
||||
- **安全处理**: 添加表存在性检查,避免SQL错误
|
||||
|
||||
### 健康建议服务修复
|
||||
|
||||
系统已修复健康建议生成功能:
|
||||
- **问题**: `HealthRecommendationService` 中 NullPointerException,由于数据分组时遇到null键
|
||||
- **解决**: 在流处理前过滤null值,添加数据验证和日志记录
|
||||
- **位置**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/health/service/HealthRecommendationService.java`
|
||||
- **改进**: 增强了数据质量检测和错误处理
|
||||
|
||||
### 权重配置优化和合理化
|
||||
|
||||
系统已完成权重分配的标准化:
|
||||
- **问题**: 权重配置不合理(总和超过1.0、存在null值、分配不科学)
|
||||
- **解决**: 实现了基于医学重要性的标准化权重分配算法
|
||||
- **位置**: `ljwx-boot/ljwx-boot-modules/src/main/java/com/ljwx/modules/health/service/WeightCalculationService.java`
|
||||
|
||||
#### 标准权重分配方案
|
||||
|
||||
**核心生命体征 (65%)**:
|
||||
- 心率: 20% - 最重要的生命体征指标
|
||||
- 血氧: 18% - 呼吸系统核心指标
|
||||
- 体温: 15% - 基础生命体征
|
||||
- 收缩压: 6% - 心血管健康指标
|
||||
- 舒张压: 6% - 心血管健康指标
|
||||
|
||||
**健康状态指标 (20%)**:
|
||||
- 压力指数: 12% - 心理健康重要指标
|
||||
- 睡眠质量: 8% - 恢复性健康指标
|
||||
|
||||
**运动健康指标 (10%)**:
|
||||
- 步数: 4% - 日常活动量
|
||||
- 距离: 3% - 运动强度
|
||||
- 卡路里: 3% - 代谢水平
|
||||
|
||||
**辅助指标 (5%)**:
|
||||
- 心电图: 2% - 深度心血管监测
|
||||
- 位置/锻炼等: 各1%以下
|
||||
|
||||
#### 技术改进
|
||||
|
||||
- **类型安全**: 修复了BigDecimal到Double的类型转换问题
|
||||
- **数据验证**: 添加了权重配置的自动验证和修复
|
||||
- **标准化**: 实现了科学的权重分配标准
|
||||
- **自动修复**: 系统自动检测和修复不合理的权重配置
|
||||
@@ -1,137 +0,0 @@
|
||||
# 容器构建代理修复说明
|
||||
|
||||
## 问题
|
||||
|
||||
Maven 在容器内部构建时无法下载依赖:
|
||||
```
|
||||
Remote host terminated the handshake
|
||||
Could not transfer artifact from aliyunmaven
|
||||
```
|
||||
|
||||
## 根本原因
|
||||
|
||||
构建脚本传递的代理地址 `http://127.0.0.1:7890` 在容器内部指向容器自己,而不是宿主机。
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 修改代理地址
|
||||
|
||||
使用 `host.docker.internal` 替代 `127.0.0.1`:
|
||||
|
||||
```bash
|
||||
# 宿主机代理地址(容器外)
|
||||
HTTP_PROXY=http://127.0.0.1:7890
|
||||
|
||||
# 容器内代理地址
|
||||
HTTP_PROXY=http://host.docker.internal:7890
|
||||
```
|
||||
|
||||
### 2. Dockerfile 配置
|
||||
|
||||
在 `ljwx-boot/ljwx-boot-admin/Dockerfile.prod` 中:
|
||||
|
||||
```dockerfile
|
||||
# 接收代理参数
|
||||
ARG HTTP_PROXY
|
||||
ARG HTTPS_PROXY
|
||||
|
||||
# 配置 Maven settings.xml 包含代理设置
|
||||
RUN if [ -n "$HTTP_PROXY" ]; then \
|
||||
PROXY_HOST=$(echo $HTTP_PROXY | sed -E 's|https?://([^:]+):.*|\1|'); \
|
||||
PROXY_PORT=$(echo $HTTP_PROXY | sed -E 's|https?://[^:]+:([0-9]+).*|\1|'); \
|
||||
# 添加代理配置到 settings.xml
|
||||
fi
|
||||
```
|
||||
|
||||
### 3. 构建脚本修改
|
||||
|
||||
在 `build-and-push.sh` 中:
|
||||
|
||||
```bash
|
||||
# 容器内部代理地址
|
||||
local container_http_proxy="http://host.docker.internal:${PROXY_PORT}"
|
||||
local container_https_proxy="http://host.docker.internal:${PROXY_PORT}"
|
||||
|
||||
# 传递给 Docker 构建
|
||||
docker build \
|
||||
--build-arg HTTP_PROXY=$container_http_proxy \
|
||||
--build-arg HTTPS_PROXY=$container_https_proxy \
|
||||
...
|
||||
```
|
||||
|
||||
## 验证
|
||||
|
||||
构建时会显示代理配置:
|
||||
```bash
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 输出:
|
||||
📡 容器代理配置: http://host.docker.internal:7890
|
||||
```
|
||||
|
||||
Maven settings.xml 会包含:
|
||||
```xml
|
||||
<proxies>
|
||||
<proxy>
|
||||
<id>proxy</id>
|
||||
<active>true</active>
|
||||
<protocol>http</protocol>
|
||||
<host>host.docker.internal</host>
|
||||
<port>7890</port>
|
||||
<nonProxyHosts>localhost|127.0.0.1|*.local</nonProxyHosts>
|
||||
</proxy>
|
||||
</proxies>
|
||||
```
|
||||
|
||||
## 工作原理
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ 宿主机 Mac │
|
||||
│ │
|
||||
│ ClashX/V2Ray │
|
||||
│ :7890 │
|
||||
└────────▲────────┘
|
||||
│
|
||||
│ host.docker.internal
|
||||
│
|
||||
┌────────┴────────┐
|
||||
│ Docker 容器 │
|
||||
│ │
|
||||
│ Maven 构建 │
|
||||
│ ├─ HTTP_PROXY │
|
||||
│ └─ settings.xml│
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
1. 代理服务在宿主机监听 7890 端口
|
||||
2. Docker 容器通过 `host.docker.internal` 访问宿主机
|
||||
3. Maven 使用代理下载依赖到阿里云镜像
|
||||
|
||||
## 适用范围
|
||||
|
||||
此修复适用于所有需要在容器内部访问网络的构建:
|
||||
|
||||
- ✅ Maven 依赖下载
|
||||
- ✅ NPM 包下载
|
||||
- ✅ pip 包下载
|
||||
- ✅ Go modules 下载
|
||||
- ✅ apt-get/apk 软件包安装
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
# 1. 确保代理运行
|
||||
lsof -i :7890
|
||||
|
||||
# 2. 构建镜像
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 3. 检查 Maven 下载日志
|
||||
# 应该看到通过代理成功下载依赖
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**日期**: 2025-11-26
|
||||
**状态**: ✅ 已修复
|
||||
@@ -1,623 +0,0 @@
|
||||
# LJWX 统一构建部署方案 v2.0
|
||||
|
||||
## 概述
|
||||
|
||||
本方案解决了以下三个核心问题:
|
||||
|
||||
1. **配置管理统一化** - 使用单一`.env`文件管理所有配置
|
||||
2. **脚本功能优化** - 支持分阶段执行(build/push/deploy)
|
||||
3. **数据库版本管理** - 优雅的数据库迁移和升级方案
|
||||
|
||||
## 架构改进
|
||||
|
||||
### 改进前 (v1.x)
|
||||
|
||||
```
|
||||
配置文件分散:
|
||||
- monitoring-versions.env (版本配置)
|
||||
- docker-compose.prod.yml (硬编码配置)
|
||||
- build-and-push.sh (硬编码逻辑)
|
||||
|
||||
数据库管理:
|
||||
- 手动导出 data.sql
|
||||
- 容易出现版本不一致
|
||||
- 无迁移历史追踪
|
||||
|
||||
构建流程:
|
||||
- 一体化执行,无法分阶段
|
||||
- 难以调试和错误恢复
|
||||
```
|
||||
|
||||
### 改进后 (v2.0)
|
||||
|
||||
```
|
||||
统一配置:
|
||||
.env (唯一配置源)
|
||||
├── 版本配置
|
||||
├── Registry配置
|
||||
├── 数据库配置
|
||||
├── Redis配置
|
||||
└── 构建/部署配置
|
||||
|
||||
数据库迁移:
|
||||
docker/mysql/migrations/
|
||||
├── V1.0.0__baseline.sql
|
||||
├── V2.0.0__add_features.sql
|
||||
├── V2.0.3__current.sql
|
||||
├── schema_migrations (历史表)
|
||||
└── rollback/ (回滚脚本)
|
||||
|
||||
分阶段构建:
|
||||
build-and-push-v2.sh
|
||||
├── -b (build only)
|
||||
├── -p (push only)
|
||||
├── -d (deploy only)
|
||||
└── -a (all)
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 初始配置
|
||||
|
||||
```bash
|
||||
# 1.1 复制统一配置文件
|
||||
cp .env.unified .env
|
||||
|
||||
# 1.2 编辑配置(修改密码、端口等)
|
||||
vim .env
|
||||
|
||||
# 关键配置项:
|
||||
# - LJWX_VERSION=2.0.3
|
||||
# - MYSQL_ROOT_PASSWORD=your_password
|
||||
# - REDIS_PASSWORD=your_password
|
||||
# - REGISTRY=localhost:15000/ljwx
|
||||
```
|
||||
|
||||
### 2. 导出数据库基线
|
||||
|
||||
```bash
|
||||
# 方式1: 使用数据库迁移工具(推荐)
|
||||
./db-migrate.sh export 2.0.3
|
||||
|
||||
# 方式2: 使用构建脚本
|
||||
./build-and-push-v2.sh -e
|
||||
|
||||
# 这会导出宿主机数据库到:
|
||||
# - docker/mysql/migrations/V2.0.3__baseline.sql (版本化)
|
||||
# - docker/mysql/data.sql (Docker构建使用)
|
||||
```
|
||||
|
||||
### 3. 构建镜像
|
||||
|
||||
```bash
|
||||
# 构建所有镜像
|
||||
./build-and-push-v2.sh -b
|
||||
|
||||
# 或构建单个组件
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
|
||||
# 查看构建日志
|
||||
tail -f logs/build/ljwx-boot_*.log
|
||||
```
|
||||
|
||||
### 4. 推送镜像
|
||||
|
||||
```bash
|
||||
# 推送所有镜像到Registry
|
||||
./build-and-push-v2.sh -p
|
||||
|
||||
# 或推送单个组件
|
||||
./build-and-push-v2.sh -p -c ljwx-mysql
|
||||
```
|
||||
|
||||
### 5. 部署服务
|
||||
|
||||
```bash
|
||||
# 部署所有服务
|
||||
./build-and-push-v2.sh -d
|
||||
|
||||
# 或手动使用docker-compose
|
||||
docker-compose -f docker-compose.prod.v2.yml up -d
|
||||
```
|
||||
|
||||
### 6. 一键部署
|
||||
|
||||
```bash
|
||||
# 导出数据库 + 构建 + 推送 + 部署
|
||||
./build-and-push-v2.sh -e -a
|
||||
|
||||
# 或分步执行(推荐生产环境)
|
||||
./build-and-push-v2.sh -e # 导出数据库
|
||||
./build-and-push-v2.sh -b # 构建镜像
|
||||
./build-and-push-v2.sh -p # 推送镜像
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
```
|
||||
|
||||
## 配置文件详解
|
||||
|
||||
### .env 配置结构
|
||||
|
||||
```bash
|
||||
# ============================================
|
||||
# 版本配置
|
||||
# ============================================
|
||||
LJWX_VERSION=2.0.3 # 统一版本号
|
||||
LJWX_MYSQL_VERSION=${LJWX_VERSION} # 可独立设置组件版本
|
||||
LJWX_REDIS_VERSION=${LJWX_VERSION}
|
||||
LJWX_BOOT_VERSION=${LJWX_VERSION}
|
||||
LJWX_BIGSCREEN_VERSION=${LJWX_VERSION}
|
||||
LJWX_ADMIN_VERSION=${LJWX_VERSION}
|
||||
|
||||
# ============================================
|
||||
# Registry配置
|
||||
# ============================================
|
||||
REGISTRY=localhost:15000/ljwx # 镜像仓库地址
|
||||
PRIVATE_REGISTRY_HOST=localhost:15000
|
||||
CACHE_REGISTRY_HOST=localhost:15001
|
||||
|
||||
# ============================================
|
||||
# 数据库配置
|
||||
# ============================================
|
||||
# 容器内配置
|
||||
MYSQL_ROOT_PASSWORD=123456
|
||||
MYSQL_DATABASE=test
|
||||
MYSQL_PORT=3307
|
||||
|
||||
# 宿主机配置(用于导出)
|
||||
HOST_MYSQL_HOST=127.0.0.1
|
||||
HOST_MYSQL_PORT=3306
|
||||
HOST_MYSQL_DATABASE=test
|
||||
|
||||
# 迁移配置
|
||||
DB_MIGRATION_ENABLED=true
|
||||
DB_MIGRATION_AUTO_APPLY=true
|
||||
DB_MIGRATION_DIR=./docker/mysql/migrations
|
||||
|
||||
# ============================================
|
||||
# Redis配置
|
||||
# ============================================
|
||||
REDIS_HOST=ljwx-redis
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=123456
|
||||
|
||||
# ============================================
|
||||
# 应用配置
|
||||
# ============================================
|
||||
BOOT_PORT=9998
|
||||
BIGSCREEN_PORT=5225
|
||||
BIGSCREEN_EXTERNAL_PORT=8000
|
||||
ADMIN_EXTERNAL_PORT=8080
|
||||
|
||||
# ============================================
|
||||
# 部署配置
|
||||
# ============================================
|
||||
COMPOSE_FILE=docker-compose.prod.v2.yml
|
||||
NETWORK_NAME=ljwx-network
|
||||
```
|
||||
|
||||
### docker-compose.prod.v2.yml 特性
|
||||
|
||||
```yaml
|
||||
# 使用环境变量替换
|
||||
services:
|
||||
ljwx-mysql:
|
||||
image: ${REGISTRY}/ljwx-mysql:${LJWX_MYSQL_VERSION}
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
- MYSQL_DATABASE=${MYSQL_DATABASE}
|
||||
ports:
|
||||
- "${MYSQL_PORT}:3306"
|
||||
|
||||
ljwx-boot:
|
||||
image: ${REGISTRY}/ljwx-boot:${LJWX_BOOT_VERSION}
|
||||
environment:
|
||||
- REDIS_HOST=${REDIS_HOST}
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
||||
ports:
|
||||
- "${BOOT_PORT}:9998"
|
||||
```
|
||||
|
||||
## 数据库迁移管理
|
||||
|
||||
### 迁移文件命名规范
|
||||
|
||||
```
|
||||
V{版本号}__{描述}.sql
|
||||
|
||||
示例:
|
||||
V1.0.0__baseline.sql # 初始基线
|
||||
V2.0.0__add_health_tables.sql # 添加健康表
|
||||
V2.0.1__fix_indexes.sql # 修复索引
|
||||
V2.0.2__add_org_fields.sql # 添加组织字段
|
||||
V2.0.3__current.sql # 当前版本
|
||||
```
|
||||
|
||||
### 创建新迁移
|
||||
|
||||
```bash
|
||||
# 1. 创建迁移脚本模板
|
||||
./db-migrate.sh create 2.0.4 add_new_features
|
||||
|
||||
# 2. 编辑生成的迁移脚本
|
||||
vim docker/mysql/migrations/V2.0.4__add_new_features.sql
|
||||
|
||||
# 3. 编辑对应的回滚脚本
|
||||
vim docker/mysql/migrations/rollback/R2.0.4__rollback.sql
|
||||
```
|
||||
|
||||
### 迁移脚本示例
|
||||
|
||||
```sql
|
||||
-- V2.0.4__add_new_features.sql
|
||||
-- ============================================
|
||||
-- 迁移版本: V2.0.4
|
||||
-- 创建时间: 2025-11-28
|
||||
-- 描述: 添加用户健康评分表
|
||||
-- 依赖版本: V2.0.3
|
||||
-- ============================================
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- 创建表(幂等性)
|
||||
CREATE TABLE IF NOT EXISTS `t_user_health_score` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL,
|
||||
`score` decimal(5,2) DEFAULT 0.00,
|
||||
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_created_at` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- 添加字段(幂等性)
|
||||
SET @col_exists = 0;
|
||||
SELECT COUNT(*) INTO @col_exists
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 't_user'
|
||||
AND column_name = 'health_level';
|
||||
|
||||
SET @sql = IF(@col_exists = 0,
|
||||
'ALTER TABLE t_user ADD COLUMN health_level VARCHAR(20)',
|
||||
'SELECT "Column already exists"');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
COMMIT;
|
||||
```
|
||||
|
||||
### 应用迁移
|
||||
|
||||
```bash
|
||||
# 查看迁移状态
|
||||
./db-migrate.sh status
|
||||
|
||||
# 应用特定版本
|
||||
./db-migrate.sh apply 2.0.4
|
||||
|
||||
# 应用所有待执行迁移
|
||||
./db-migrate.sh apply-all
|
||||
|
||||
# 回滚到指定版本
|
||||
./db-migrate.sh rollback 2.0.3
|
||||
```
|
||||
|
||||
### 迁移历史追踪
|
||||
|
||||
系统自动在数据库中创建`schema_migrations`表:
|
||||
|
||||
```sql
|
||||
mysql> SELECT * FROM schema_migrations;
|
||||
+---------+---------------------+------+------------+----------+
|
||||
| version | description | ... | installed | success |
|
||||
+---------+---------------------+------+------------+----------+
|
||||
| 2.0.0 | baseline | ... | 2025-11-28 | 1 |
|
||||
| 2.0.1 | add_health_tables | ... | 2025-11-28 | 1 |
|
||||
| 2.0.2 | fix_indexes | ... | 2025-11-28 | 1 |
|
||||
| 2.0.3 | add_org_fields | ... | 2025-11-28 | 1 |
|
||||
+---------+---------------------+------+------------+----------+
|
||||
```
|
||||
|
||||
## 构建脚本使用
|
||||
|
||||
### build-and-push-v2.sh 功能
|
||||
|
||||
```bash
|
||||
# 查看帮助
|
||||
./build-and-push-v2.sh -h
|
||||
|
||||
# 分阶段执行
|
||||
./build-and-push-v2.sh -b # 仅构建
|
||||
./build-and-push-v2.sh -p # 仅推送
|
||||
./build-and-push-v2.sh -d # 仅部署
|
||||
./build-and-push-v2.sh -a # 全部执行
|
||||
|
||||
# 单组件操作
|
||||
./build-and-push-v2.sh -b -c ljwx-boot # 构建单个组件
|
||||
./build-and-push-v2.sh -b -p -c ljwx-mysql # 构建并推送
|
||||
|
||||
# 数据库操作
|
||||
./build-and-push-v2.sh -e # 导出数据库
|
||||
./build-and-push-v2.sh -m # 应用迁移
|
||||
|
||||
# 指定版本
|
||||
./build-and-push-v2.sh -b -v 2.0.4 # 构建指定版本
|
||||
```
|
||||
|
||||
### 组合使用示例
|
||||
|
||||
```bash
|
||||
# 场景1: 开发环境快速迭代
|
||||
./build-and-push-v2.sh -b -c ljwx-boot # 只构建修改的组件
|
||||
./build-and-push-v2.sh -p -c ljwx-boot # 推送
|
||||
./build-and-push-v2.sh -d # 重新部署
|
||||
|
||||
# 场景2: 数据库结构变更
|
||||
./db-migrate.sh create 2.0.4 add_features # 创建迁移
|
||||
vim docker/mysql/migrations/V2.0.4__*.sql # 编辑迁移脚本
|
||||
./db-migrate.sh apply 2.0.4 # 测试应用
|
||||
./build-and-push-v2.sh -b -c ljwx-mysql # 重新构建MySQL镜像
|
||||
./build-and-push-v2.sh -p -c ljwx-mysql # 推送
|
||||
|
||||
# 场景3: 生产环境完整部署
|
||||
./db-migrate.sh export 2.0.4 # 导出最新数据库
|
||||
./build-and-push-v2.sh -b # 构建所有镜像
|
||||
./build-and-push-v2.sh -p # 推送所有镜像
|
||||
# 在生产环境执行:
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
```
|
||||
|
||||
## 版本发布流程
|
||||
|
||||
### 开发阶段
|
||||
|
||||
```bash
|
||||
# 1. 更新代码
|
||||
git pull origin main
|
||||
|
||||
# 2. 创建数据库迁移(如有表结构变更)
|
||||
./db-migrate.sh create 2.0.4 add_new_features
|
||||
vim docker/mysql/migrations/V2.0.4__add_new_features.sql
|
||||
|
||||
# 3. 本地测试迁移
|
||||
./db-migrate.sh apply 2.0.4
|
||||
|
||||
# 4. 如有问题,回滚测试
|
||||
./db-migrate.sh rollback 2.0.3
|
||||
|
||||
# 5. 提交代码
|
||||
git add .
|
||||
git commit -m "feat: add new features v2.0.4"
|
||||
git push
|
||||
```
|
||||
|
||||
### 构建阶段
|
||||
|
||||
```bash
|
||||
# 1. 更新版本号
|
||||
vim .env
|
||||
# 修改: LJWX_VERSION=2.0.4
|
||||
|
||||
# 2. 导出最新数据库
|
||||
./db-migrate.sh export 2.0.4
|
||||
|
||||
# 3. 构建所有镜像
|
||||
./build-and-push-v2.sh -b
|
||||
|
||||
# 4. 推送到Registry
|
||||
./build-and-push-v2.sh -p
|
||||
|
||||
# 5. 验证镜像
|
||||
docker images | grep ljwx
|
||||
```
|
||||
|
||||
### 测试阶段
|
||||
|
||||
```bash
|
||||
# 1. 在测试环境部署
|
||||
./build-and-push-v2.sh -d
|
||||
|
||||
# 2. 验证服务
|
||||
curl http://localhost:9998/actuator/health
|
||||
curl http://localhost:8000/api/health
|
||||
|
||||
# 3. 验证数据库迁移
|
||||
./db-migrate.sh status
|
||||
|
||||
# 4. 功能测试
|
||||
# ...执行各项功能测试...
|
||||
```
|
||||
|
||||
### 生产部署
|
||||
|
||||
```bash
|
||||
# 1. 备份生产数据库
|
||||
docker exec ljwx-mysql mysqldump -u root -p123456 test > backup_prod_$(date +%Y%m%d).sql
|
||||
|
||||
# 2. 拉取最新镜像
|
||||
docker-compose -f docker-compose.prod.v2.yml pull
|
||||
|
||||
# 3. 停止服务
|
||||
docker-compose -f docker-compose.prod.v2.yml down
|
||||
|
||||
# 4. 启动新版本
|
||||
docker-compose -f docker-compose.prod.v2.yml up -d
|
||||
|
||||
# 5. 自动应用迁移(如启用了AUTO_APPLY)
|
||||
# 或手动应用:
|
||||
./db-migrate.sh apply-all
|
||||
|
||||
# 6. 验证服务
|
||||
docker-compose -f docker-compose.prod.v2.yml ps
|
||||
./db-migrate.sh status
|
||||
|
||||
# 7. 健康检查
|
||||
curl http://localhost:9998/actuator/health
|
||||
```
|
||||
|
||||
## 故障处理
|
||||
|
||||
### 构建失败
|
||||
|
||||
```bash
|
||||
# 查看构建日志
|
||||
tail -f logs/build/ljwx-boot_*.log
|
||||
|
||||
# 清理Docker缓存重新构建
|
||||
docker system prune -f
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
```
|
||||
|
||||
### 迁移失败
|
||||
|
||||
```bash
|
||||
# 查看迁移状态
|
||||
./db-migrate.sh status
|
||||
|
||||
# 查看错误日志
|
||||
docker-compose -f docker-compose.prod.v2.yml logs ljwx-mysql
|
||||
|
||||
# 回滚到上一版本
|
||||
./db-migrate.sh rollback 2.0.3
|
||||
|
||||
# 恢复备份(最后手段)
|
||||
mysql -h 127.0.0.1 -u root -p123456 test < backup_prod_20251128.sql
|
||||
```
|
||||
|
||||
### 服务异常
|
||||
|
||||
```bash
|
||||
# 查看所有服务状态
|
||||
docker-compose -f docker-compose.prod.v2.yml ps
|
||||
|
||||
# 查看特定服务日志
|
||||
docker-compose -f docker-compose.prod.v2.yml logs -f ljwx-boot
|
||||
|
||||
# 重启服务
|
||||
docker-compose -f docker-compose.prod.v2.yml restart ljwx-boot
|
||||
|
||||
# 完全重新部署
|
||||
docker-compose -f docker-compose.prod.v2.yml down
|
||||
docker-compose -f docker-compose.prod.v2.yml up -d
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 配置管理
|
||||
|
||||
1. ✅ 使用`.env`作为唯一配置源
|
||||
2. ✅ 不要在`.env`中硬编码敏感信息到Git
|
||||
3. ✅ 为不同环境维护不同的`.env`文件(.env.dev, .env.prod)
|
||||
4. ✅ 使用环境变量默认值提供回退
|
||||
|
||||
### 数据库迁移
|
||||
|
||||
1. ✅ 每个迁移脚本保持幂等性
|
||||
2. ✅ 迁移前必须备份数据库
|
||||
3. ✅ 在测试环境充分测试后再上生产
|
||||
4. ✅ 为每个迁移编写对应的回滚脚本
|
||||
5. ✅ 避免在迁移中执行耗时操作
|
||||
|
||||
### 构建部署
|
||||
|
||||
1. ✅ 生产环境使用分阶段部署
|
||||
2. ✅ 构建前导出最新数据库
|
||||
3. ✅ 推送前验证镜像构建成功
|
||||
4. ✅ 部署后验证服务健康状态
|
||||
5. ✅ 保留多个历史版本的备份
|
||||
|
||||
## 文件清单
|
||||
|
||||
```
|
||||
release/
|
||||
├── .env.unified # 统一配置模板
|
||||
├── .env # 实际配置(不入Git)
|
||||
├── docker-compose.prod.v2.yml # v2版本Compose文件
|
||||
├── build-and-push-v2.sh # v2版本构建脚本
|
||||
├── db-migrate.sh # 数据库迁移工具
|
||||
├── DEPLOYMENT-GUIDE-V2.md # 本文档
|
||||
├── docker/
|
||||
│ └── mysql/
|
||||
│ ├── Dockerfile
|
||||
│ ├── data.sql # 当前版本数据
|
||||
│ └── migrations/ # 迁移脚本目录
|
||||
│ ├── README.md
|
||||
│ ├── V1.0.0__baseline.sql
|
||||
│ ├── V2.0.0__add_features.sql
|
||||
│ ├── V2.0.3__current.sql
|
||||
│ └── rollback/
|
||||
│ ├── R2.0.3__rollback.sql
|
||||
│ └── ...
|
||||
├── logs/
|
||||
│ ├── build/ # 构建日志
|
||||
│ └── deploy/ # 部署日志
|
||||
└── backups/
|
||||
└── mysql/ # 数据库备份
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 如何从v1迁移到v2?
|
||||
|
||||
```bash
|
||||
# 1. 创建新配置
|
||||
cp .env.unified .env
|
||||
|
||||
# 2. 从旧配置文件复制设置
|
||||
# 参考 monitoring-versions.env 和 docker-compose.prod.yml
|
||||
|
||||
# 3. 导出当前数据库作为基线
|
||||
./db-migrate.sh export 2.0.3
|
||||
|
||||
# 4. 测试新脚本
|
||||
./build-and-push-v2.sh -b -c ljwx-mysql
|
||||
|
||||
# 5. 逐步迁移其他组件
|
||||
```
|
||||
|
||||
### Q: 如何处理多环境部署?
|
||||
|
||||
```bash
|
||||
# 方式1: 使用不同的.env文件
|
||||
cp .env.dev .env && ./build-and-push-v2.sh -d # 开发环境
|
||||
cp .env.prod .env && ./build-and-push-v2.sh -d # 生产环境
|
||||
|
||||
# 方式2: 使用环境变量覆盖
|
||||
COMPOSE_FILE=docker-compose.prod.yml ./build-and-push-v2.sh -d
|
||||
```
|
||||
|
||||
### Q: data.sql和迁移脚本的关系?
|
||||
|
||||
- `data.sql` 是完整的数据库快照,用于Docker镜像构建
|
||||
- 迁移脚本是增量变更,用于已有数据库的升级
|
||||
- 每次发布前,应该导出最新的data.sql作为新版本基线
|
||||
- 老版本升级使用迁移脚本,新部署使用data.sql
|
||||
|
||||
### Q: 如何回退到旧版本?
|
||||
|
||||
```bash
|
||||
# 1. 恢复数据库备份
|
||||
mysql -h 127.0.0.1 -u root -p123456 test < backup_before_2.0.3.sql
|
||||
|
||||
# 2. 修改.env版本号
|
||||
# LJWX_VERSION=2.0.2
|
||||
|
||||
# 3. 重新部署
|
||||
./build-and-push-v2.sh -d
|
||||
|
||||
# 4. 应用回滚脚本(如有)
|
||||
./db-migrate.sh rollback 2.0.2
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
v2.0方案的核心优势:
|
||||
|
||||
1. **单一配置源** - 所有配置集中在`.env`,易于管理
|
||||
2. **灵活构建** - 支持分阶段、单组件操作
|
||||
3. **版本化迁移** - 数据库变更可追溯、可回滚
|
||||
4. **自动化程度高** - 减少人工操作,降低出错率
|
||||
5. **易于扩展** - 添加新组件只需修改配置文件
|
||||
|
||||
通过这套方案,实现了从开发到生产的完整DevOps流程。
|
||||
@@ -1,467 +0,0 @@
|
||||
# LJWX 统一 Docker Compose 部署文档
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [概述](#概述)
|
||||
- [系统架构](#系统架构)
|
||||
- [快速开始](#快速开始)
|
||||
- [服务说明](#服务说明)
|
||||
- [管理命令](#管理命令)
|
||||
- [配置说明](#配置说明)
|
||||
- [故障排查](#故障排查)
|
||||
|
||||
## 🎯 概述
|
||||
|
||||
这是 LJWX 项目的统一 Docker Compose 配置,整合了以下三大部分:
|
||||
|
||||
1. **业务应用**:ljwx-boot、ljwx-admin、ljwx-bigscreen
|
||||
2. **基础设施**:MySQL、Redis
|
||||
3. **监控系统**:Prometheus、Grafana、Loki、Alertmanager
|
||||
|
||||
所有服务通过一个 docker-compose.yml 文件统一管理,简化部署和运维流程。
|
||||
|
||||
## 🏗️ 系统架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ LJWX 系统架构 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ ljwx-admin │ │ ljwx-bigscreen│ │ 监控面板 │ │
|
||||
│ │ (前端管理) │ │ (大屏展示) │ │ (Grafana) │ │
|
||||
│ │ :5173 │ │ :5001 │ │ :3001 │ │
|
||||
│ └──────┬───────┘ └──────┬────────┘ └──────┬───────┘ │
|
||||
│ │ │ │ │
|
||||
│ └─────────────────┼───────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────▼─────────┐ │
|
||||
│ │ ljwx-boot │ │
|
||||
│ │ (后端API) │ │
|
||||
│ │ :9998 │ │
|
||||
│ └────────┬─────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────────┼─────────────────┐ │
|
||||
│ │ │ │ │
|
||||
│ ┌────▼─────┐ ┌─────▼──────┐ ┌─────▼──────┐ │
|
||||
│ │ MySQL │ │ Redis │ │ Prometheus │ │
|
||||
│ │ :3306 │ │ :6379 │ │ :9091 │ │
|
||||
│ └──────────┘ └────────────┘ └────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 前置要求
|
||||
|
||||
- Docker >= 20.10
|
||||
- Docker Compose >= 2.0
|
||||
- 至少 4GB 可用内存
|
||||
- 至少 20GB 可用磁盘空间
|
||||
|
||||
### 一键启动
|
||||
|
||||
```bash
|
||||
# 1. 复制环境变量配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 2. 根据需要修改 .env 文件中的配置
|
||||
vim .env
|
||||
|
||||
# 3. 启动所有服务
|
||||
./docker-manager.sh start
|
||||
|
||||
# 或者使用原生 docker-compose 命令
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 分步启动(推荐)
|
||||
|
||||
对于首次部署,建议分步启动以便更好地控制启动顺序:
|
||||
|
||||
```bash
|
||||
# 1. 先启动基础设施服务
|
||||
./docker-manager.sh start-infra
|
||||
|
||||
# 2. 等待 MySQL 和 Redis 完全启动(约 30 秒)
|
||||
./docker-manager.sh status
|
||||
|
||||
# 3. 启动业务应用服务
|
||||
./docker-manager.sh start-apps
|
||||
|
||||
# 4. (可选)启动监控系统
|
||||
./docker-manager.sh start-monitor
|
||||
```
|
||||
|
||||
## 📦 服务说明
|
||||
|
||||
### 业务应用服务
|
||||
|
||||
| 服务名 | 容器名 | 端口 | 说明 |
|
||||
|--------|--------|------|------|
|
||||
| ljwx-boot | ljwx-boot | 9998 | Spring Boot 后端服务 |
|
||||
| ljwx-admin | ljwx-admin | 5173 | Vue3 前端管理界面 |
|
||||
| ljwx-bigscreen | ljwx-bigscreen | 5001 | Flask 大屏展示服务 |
|
||||
|
||||
### 基础设施服务
|
||||
|
||||
| 服务名 | 容器名 | 端口 | 说明 |
|
||||
|--------|--------|------|------|
|
||||
| ljwx-mysql | ljwx-mysql | 3306 | MySQL 8.0 数据库 |
|
||||
| ljwx-redis | ljwx-redis | 6379 | Redis 7 缓存服务 |
|
||||
|
||||
### 监控系统服务
|
||||
|
||||
| 服务名 | 容器名 | 端口 | 说明 |
|
||||
|--------|--------|------|------|
|
||||
| ljwx-prometheus | ljwx-prometheus | 9091 | 监控指标收集 |
|
||||
| ljwx-alertmanager | ljwx-alertmanager | 9094 | 告警管理 |
|
||||
| ljwx-loki | ljwx-loki | 3100 | 日志聚合 |
|
||||
| ljwx-promtail | ljwx-promtail | - | 日志采集 |
|
||||
| ljwx-grafana | ljwx-grafana | 3001 | 监控可视化面板 |
|
||||
| ljwx-node-exporter | ljwx-node-exporter | 9101 | 系统指标导出 |
|
||||
|
||||
## 🎮 管理命令
|
||||
|
||||
### 使用管理脚本(推荐)
|
||||
|
||||
```bash
|
||||
# 查看帮助
|
||||
./docker-manager.sh help
|
||||
|
||||
# 启动服务
|
||||
./docker-manager.sh start # 启动所有服务
|
||||
./docker-manager.sh start-infra # 仅启动基础设施
|
||||
./docker-manager.sh start-apps # 仅启动业务应用
|
||||
./docker-manager.sh start-monitor # 仅启动监控系统
|
||||
|
||||
# 停止服务
|
||||
./docker-manager.sh stop # 停止所有服务
|
||||
./docker-manager.sh down # 停止并删除容器(保留数据)
|
||||
|
||||
# 查看状态
|
||||
./docker-manager.sh status # 查看服务状态
|
||||
./docker-manager.sh health # 健康检查
|
||||
./docker-manager.sh urls # 显示访问地址
|
||||
|
||||
# 查看日志
|
||||
./docker-manager.sh logs # 查看所有日志
|
||||
./docker-manager.sh logs ljwx-boot # 查看指定服务日志
|
||||
|
||||
# 重启服务
|
||||
./docker-manager.sh restart # 重启所有服务
|
||||
./docker-manager.sh restart ljwx-boot # 重启指定服务
|
||||
|
||||
# 完全清理(谨慎操作)
|
||||
./docker-manager.sh cleanup # 删除所有容器和数据卷
|
||||
```
|
||||
|
||||
### 使用原生 Docker Compose 命令
|
||||
|
||||
```bash
|
||||
# 启动服务
|
||||
docker-compose up -d # 启动所有服务
|
||||
docker-compose up -d ljwx-mysql ljwx-redis # 启动指定服务
|
||||
|
||||
# 停止服务
|
||||
docker-compose stop # 停止所有服务
|
||||
docker-compose stop ljwx-boot # 停止指定服务
|
||||
|
||||
# 查看状态和日志
|
||||
docker-compose ps # 查看服务状态
|
||||
docker-compose logs -f ljwx-boot # 查看指定服务日志
|
||||
|
||||
# 重启服务
|
||||
docker-compose restart # 重启所有服务
|
||||
docker-compose restart ljwx-boot # 重启指定服务
|
||||
|
||||
# 删除服务
|
||||
docker-compose down # 删除所有容器(保留数据)
|
||||
docker-compose down -v # 删除所有容器和数据卷
|
||||
```
|
||||
|
||||
## ⚙️ 配置说明
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
编辑 `.env` 文件修改配置:
|
||||
|
||||
```bash
|
||||
# MySQL 配置
|
||||
MYSQL_ROOT_PASSWORD=root123456 # MySQL root 密码
|
||||
MYSQL_DATABASE=ljwx # 数据库名
|
||||
MYSQL_USER=ljwx # 应用数据库用户
|
||||
MYSQL_PASSWORD=ljwx123456 # 应用数据库密码
|
||||
|
||||
# Redis 配置
|
||||
REDIS_PASSWORD=redis123456 # Redis 密码
|
||||
|
||||
# Spring Boot 配置
|
||||
SPRING_PROFILES_ACTIVE=prod # Spring 运行环境
|
||||
|
||||
# Node.js 配置
|
||||
NODE_ENV=development # Node 运行环境
|
||||
VITE_USER_NODE_ENV=development # Vite 运行环境
|
||||
```
|
||||
|
||||
### 端口配置
|
||||
|
||||
如果默认端口冲突,可以在 `docker-compose.yml` 中修改端口映射:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "主机端口:容器端口"
|
||||
```
|
||||
|
||||
例如,修改 ljwx-boot 端口:
|
||||
|
||||
```yaml
|
||||
ljwx-boot:
|
||||
ports:
|
||||
- "8080:9998" # 将主机端口改为 8080
|
||||
```
|
||||
|
||||
### 数据持久化
|
||||
|
||||
数据卷配置在 docker-compose.yml 的 `volumes` 部分:
|
||||
|
||||
- `mysql_data`: MySQL 数据目录
|
||||
- `redis_data`: Redis 数据目录
|
||||
- `prometheus_data`: Prometheus 时序数据
|
||||
- `grafana_data`: Grafana 配置和仪表盘
|
||||
- `loki_data`: Loki 日志数据
|
||||
- `alertmanager_data`: Alertmanager 配置
|
||||
|
||||
数据默认存储在 Docker 的卷存储目录中,可以通过以下命令查看:
|
||||
|
||||
```bash
|
||||
docker volume ls
|
||||
docker volume inspect <volume_name>
|
||||
```
|
||||
|
||||
## 🌐 服务访问地址
|
||||
|
||||
启动成功后,可以通过以下地址访问各个服务:
|
||||
|
||||
### 业务应用
|
||||
|
||||
- **后端 API**: http://localhost:9998
|
||||
- **管理界面**: http://localhost:5173
|
||||
- **大屏服务**: http://localhost:5001
|
||||
|
||||
### 监控系统
|
||||
|
||||
- **Grafana**: http://localhost:3001 (默认账号: admin / admin123)
|
||||
- **Prometheus**: http://localhost:9091
|
||||
- **Alertmanager**: http://localhost:9094
|
||||
|
||||
### 基础设施
|
||||
|
||||
- **MySQL**: localhost:3306
|
||||
- **Redis**: localhost:6379
|
||||
|
||||
## 🔧 故障排查
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 1. 端口冲突
|
||||
|
||||
**问题**:启动时提示端口已被占用
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 查看端口占用情况
|
||||
lsof -i :9998
|
||||
lsof -i :3306
|
||||
|
||||
# 修改 docker-compose.yml 中的端口映射
|
||||
# 或停止占用端口的服务
|
||||
```
|
||||
|
||||
#### 2. 容器启动失败
|
||||
|
||||
**问题**:某个容器无法启动
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 查看容器日志
|
||||
docker-compose logs ljwx-boot
|
||||
|
||||
# 查看详细错误信息
|
||||
docker logs ljwx-boot
|
||||
|
||||
# 重新构建镜像
|
||||
docker-compose build --no-cache ljwx-boot
|
||||
docker-compose up -d ljwx-boot
|
||||
```
|
||||
|
||||
#### 3. 数据库连接失败
|
||||
|
||||
**问题**:应用无法连接到 MySQL
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 检查 MySQL 是否正常运行
|
||||
docker-compose ps ljwx-mysql
|
||||
|
||||
# 检查 MySQL 健康状态
|
||||
docker-compose exec ljwx-mysql mysqladmin ping -p
|
||||
|
||||
# 查看 MySQL 日志
|
||||
docker-compose logs ljwx-mysql
|
||||
|
||||
# 确认 .env 文件中的数据库密码配置正确
|
||||
```
|
||||
|
||||
#### 4. 内存不足
|
||||
|
||||
**问题**:服务启动后系统变慢或容器被杀死
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 查看 Docker 资源使用情况
|
||||
docker stats
|
||||
|
||||
# 调整 Docker Desktop 内存限制(推荐至少 4GB)
|
||||
# 或者分批启动服务,不要一次性启动所有服务
|
||||
./docker-manager.sh start-infra
|
||||
./docker-manager.sh start-apps
|
||||
```
|
||||
|
||||
#### 5. 磁盘空间不足
|
||||
|
||||
**问题**:磁盘空间不足导致服务异常
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 清理未使用的 Docker 资源
|
||||
docker system prune -a
|
||||
|
||||
# 查看 Docker 磁盘使用情况
|
||||
docker system df
|
||||
|
||||
# 删除旧的镜像和容器
|
||||
docker image prune -a
|
||||
docker container prune
|
||||
```
|
||||
|
||||
### 健康检查
|
||||
|
||||
```bash
|
||||
# 使用管理脚本进行健康检查
|
||||
./docker-manager.sh health
|
||||
|
||||
# 手动检查各服务健康状态
|
||||
docker-compose ps
|
||||
|
||||
# 检查容器健康状态
|
||||
docker inspect --format='{{.State.Health.Status}}' ljwx-boot
|
||||
docker inspect --format='{{.State.Health.Status}}' ljwx-mysql
|
||||
```
|
||||
|
||||
### 日志查看
|
||||
|
||||
```bash
|
||||
# 查看所有服务日志
|
||||
./docker-manager.sh logs
|
||||
|
||||
# 查看特定服务日志
|
||||
./docker-manager.sh logs ljwx-boot
|
||||
|
||||
# 查看最近的日志
|
||||
docker-compose logs --tail=100 ljwx-boot
|
||||
|
||||
# 实时跟踪日志
|
||||
docker-compose logs -f ljwx-boot
|
||||
```
|
||||
|
||||
## 📊 监控系统使用
|
||||
|
||||
### Grafana 仪表盘
|
||||
|
||||
1. 访问 http://localhost:3001
|
||||
2. 使用默认账号登录:admin / admin123
|
||||
3. 导航到 Dashboards 查看预配置的监控面板:
|
||||
- 系统资源监控
|
||||
- 应用性能监控
|
||||
- 告警规则监控
|
||||
|
||||
### Prometheus 指标查询
|
||||
|
||||
1. 访问 http://localhost:9091
|
||||
2. 在查询框中输入 PromQL 查询语句
|
||||
3. 常用查询示例:
|
||||
```
|
||||
# CPU 使用率
|
||||
rate(process_cpu_seconds_total[5m])
|
||||
|
||||
# 内存使用
|
||||
process_resident_memory_bytes
|
||||
|
||||
# HTTP 请求数
|
||||
http_requests_total
|
||||
```
|
||||
|
||||
### 告警配置
|
||||
|
||||
告警规则配置文件位于:
|
||||
- `ljwx-bigscreen/bigscreen/monitoring/prometheus/alerts.yml`
|
||||
- `ljwx-bigscreen/bigscreen/monitoring/alertmanager/alertmanager.yml`
|
||||
|
||||
修改配置后重启相应服务:
|
||||
```bash
|
||||
docker-compose restart ljwx-prometheus ljwx-alertmanager
|
||||
```
|
||||
|
||||
## 🔐 安全建议
|
||||
|
||||
### 生产环境部署注意事项
|
||||
|
||||
1. **修改默认密码**
|
||||
```bash
|
||||
# 修改 .env 文件中的所有密码
|
||||
MYSQL_ROOT_PASSWORD=<strong-password>
|
||||
MYSQL_PASSWORD=<strong-password>
|
||||
REDIS_PASSWORD=<strong-password>
|
||||
```
|
||||
|
||||
2. **网络隔离**
|
||||
- 将数据库和 Redis 端口仅暴露给内部网络
|
||||
- 使用防火墙限制访问
|
||||
|
||||
3. **数据备份**
|
||||
```bash
|
||||
# MySQL 备份
|
||||
docker-compose exec ljwx-mysql mysqldump -u root -p ljwx > backup.sql
|
||||
|
||||
# Redis 备份
|
||||
docker-compose exec ljwx-redis redis-cli --rdb /data/dump.rdb
|
||||
```
|
||||
|
||||
4. **日志管理**
|
||||
- 定期清理旧日志
|
||||
- 配置日志轮转
|
||||
|
||||
5. **更新策略**
|
||||
- 定期更新镜像到最新稳定版本
|
||||
- 测试后再应用到生产环境
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [CLAUDE.md](./CLAUDE.md) - 项目整体说明
|
||||
- [ljwx-bigscreen/CLAUDE.md](./ljwx-bigscreen/CLAUDE.md) - 大屏服务说明
|
||||
- [ljwx-admin/CLAUDE.md](./ljwx-admin/CLAUDE.md) - 管理界面说明
|
||||
- [Monitoring README](./ljwx-bigscreen/bigscreen/monitoring/README.md) - 监控系统详细文档
|
||||
|
||||
## 🤝 支持
|
||||
|
||||
如有问题,请查看:
|
||||
1. 本文档的故障排查部分
|
||||
2. 各服务的日志输出
|
||||
3. 相关服务的官方文档
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-25
|
||||
**版本**: 1.0.0
|
||||
@@ -1,289 +0,0 @@
|
||||
# 🐳 Docker Registry 私有镜像服务器部署完成
|
||||
|
||||
## 🎉 部署成功!
|
||||
|
||||
您的私有 Docker Registry 已成功部署并与 Gitea CI/CD 系统集成。
|
||||
|
||||
## 📋 服务概览
|
||||
|
||||
| 服务 | 地址 | 状态 | 用途 |
|
||||
|------|------|------|------|
|
||||
| **Gitea** | http://192.168.1.83:3000 | ✅ 运行中 | Git 仓库管理 |
|
||||
| **Docker Registry** | http://localhost:5001 | ✅ 运行中 | 私有镜像仓库 |
|
||||
| **Registry Web UI** | http://192.168.1.83:5002 | ✅ 运行中 | 镜像可视化管理 |
|
||||
|
||||
## 🚀 快速使用指南
|
||||
|
||||
### 1. 推送镜像到私有仓库
|
||||
|
||||
```bash
|
||||
# 构建或拉取镜像
|
||||
docker build -t my-app:latest .
|
||||
# 或者: docker pull nginx:latest
|
||||
|
||||
# 标记镜像
|
||||
docker tag my-app:latest localhost:5001/my-app:latest
|
||||
|
||||
# 推送到私有仓库
|
||||
docker push localhost:5001/my-app:latest
|
||||
```
|
||||
|
||||
### 2. 从私有仓库拉取镜像
|
||||
|
||||
```bash
|
||||
# 拉取镜像
|
||||
docker pull localhost:5001/my-app:latest
|
||||
|
||||
# 运行容器
|
||||
docker run -d localhost:5001/my-app:latest
|
||||
```
|
||||
|
||||
### 3. 查看镜像列表
|
||||
|
||||
```bash
|
||||
# 命令行查看
|
||||
curl http://localhost:5001/v2/_catalog
|
||||
|
||||
# 或访问 Web UI
|
||||
open http://192.168.1.83:5002
|
||||
```
|
||||
|
||||
## 🔧 管理命令
|
||||
|
||||
### CI/CD 集成管理
|
||||
|
||||
```bash
|
||||
# 启动所有服务
|
||||
./deployment/scripts/cicd-integration.sh start
|
||||
|
||||
# 查看服务状态
|
||||
./deployment/scripts/cicd-integration.sh status
|
||||
|
||||
# 测试集成功能
|
||||
./deployment/scripts/cicd-integration.sh test
|
||||
|
||||
# 停止所有服务
|
||||
./deployment/scripts/cicd-integration.sh stop
|
||||
```
|
||||
|
||||
### Registry 单独管理
|
||||
|
||||
```bash
|
||||
# 启动 Registry
|
||||
./deployment/scripts/registry-manager.sh start
|
||||
|
||||
# 查看状态
|
||||
./deployment/scripts/registry-manager.sh status
|
||||
|
||||
# 备份数据
|
||||
./deployment/scripts/registry-manager.sh backup
|
||||
|
||||
# 测试推送
|
||||
./deployment/scripts/registry-manager.sh push-test
|
||||
```
|
||||
|
||||
## 📊 持久化配置
|
||||
|
||||
### 数据存储方式
|
||||
- **类型**: Docker 命名卷
|
||||
- **优势**: Docker 统一管理,跨平台兼容
|
||||
- **位置**: `/var/lib/docker/volumes/compose_registry-data/_data`
|
||||
|
||||
### 备份策略
|
||||
- **自动备份**: 保留最近 5 个备份
|
||||
- **备份内容**: 镜像数据 + 配置文件
|
||||
- **恢复方法**: 一键恢复脚本
|
||||
|
||||
## 🔗 CI/CD 集成
|
||||
|
||||
### Jenkins Pipeline 示例
|
||||
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
DOCKER_REGISTRY = 'localhost:5001'
|
||||
APP_NAME = 'my-app'
|
||||
IMAGE_TAG = "${BUILD_NUMBER}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('构建镜像') {
|
||||
steps {
|
||||
script {
|
||||
def image = docker.build("${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}")
|
||||
image.push()
|
||||
image.push("latest")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('部署应用') {
|
||||
steps {
|
||||
sh """
|
||||
docker stop ${APP_NAME} || true
|
||||
docker rm ${APP_NAME} || true
|
||||
docker run -d --name ${APP_NAME} -p 8080:80 ${DOCKER_REGISTRY}/${APP_NAME}:${IMAGE_TAG}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Gitea Actions 示例
|
||||
|
||||
```yaml
|
||||
name: Build and Push
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build Docker image
|
||||
run: docker build -t localhost:5001/my-app:${{ github.sha }} .
|
||||
|
||||
- name: Push to registry
|
||||
run: docker push localhost:5001/my-app:${{ github.sha }}
|
||||
```
|
||||
|
||||
## ⚙️ 配置详情
|
||||
|
||||
### Registry 配置特点
|
||||
- **认证**: 已禁用(开发环境)
|
||||
- **删除**: 支持镜像删除
|
||||
- **CORS**: 支持跨域访问
|
||||
- **健康检查**: 自动监控服务状态
|
||||
- **日志**: 详细的访问和错误日志
|
||||
|
||||
### 网络配置
|
||||
- **内部网络**: `cicd-network`
|
||||
- **端口映射**:
|
||||
- Registry API: `5001:5000`
|
||||
- Registry UI: `5002:80`
|
||||
- **服务发现**: 容器间可通过服务名访问
|
||||
|
||||
## 🛡️ 安全考虑
|
||||
|
||||
### 开发环境(当前)
|
||||
- ✅ 无认证访问(便于开发)
|
||||
- ✅ HTTP 协议
|
||||
- ✅ 内网访问
|
||||
|
||||
### 生产环境建议
|
||||
- 🔒 启用 HTTP Basic Auth
|
||||
- 🔒 配置 HTTPS/TLS
|
||||
- 🔒 配置防火墙规则
|
||||
- 🔒 定期备份和监控
|
||||
|
||||
## 📈 性能优化
|
||||
|
||||
### 镜像构建优化
|
||||
```dockerfile
|
||||
# 多阶段构建
|
||||
FROM node:18-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
FROM node:18-alpine AS runtime
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
### 镜像标签策略
|
||||
```bash
|
||||
# 语义化版本
|
||||
localhost:5001/my-app:1.0.0
|
||||
localhost:5001/my-app:1.0.0-beta.1
|
||||
|
||||
# Git 信息
|
||||
localhost:5001/my-app:main-abc1234
|
||||
localhost:5001/my-app:feature-xyz-def5678
|
||||
|
||||
# 环境标签
|
||||
localhost:5001/my-app:dev
|
||||
localhost:5001/my-app:staging
|
||||
localhost:5001/my-app:prod
|
||||
```
|
||||
|
||||
## 🔍 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **推送失败 - TLS 错误**
|
||||
```bash
|
||||
# 解决方案:确认 Docker daemon 配置
|
||||
cat ~/.docker/daemon.json
|
||||
# 应包含: "insecure-registries": ["localhost:5001"]
|
||||
```
|
||||
|
||||
2. **服务无法访问**
|
||||
```bash
|
||||
# 检查容器状态
|
||||
docker ps | grep registry
|
||||
|
||||
# 检查日志
|
||||
docker logs docker-registry
|
||||
```
|
||||
|
||||
3. **镜像推送慢**
|
||||
```bash
|
||||
# 检查网络
|
||||
ping localhost
|
||||
|
||||
# 检查存储空间
|
||||
df -h
|
||||
```
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [Registry 配置参考](docker/registry/config.yml)
|
||||
- [Compose 配置](docker/compose/registry-compose.yml)
|
||||
- [管理脚本](deployment/scripts/)
|
||||
- [备份脚本](deployment/scripts/registry-manager.sh)
|
||||
|
||||
## 🎯 下一步
|
||||
|
||||
1. **配置生产环境认证**
|
||||
```bash
|
||||
# 启用认证(可选)
|
||||
./deployment/scripts/fix-docker-registry.sh enable-auth
|
||||
```
|
||||
|
||||
2. **集成 Jenkins**
|
||||
- 安装 Docker Pipeline 插件
|
||||
- 配置 Registry 凭据
|
||||
- 创建构建流水线
|
||||
|
||||
3. **监控和告警**
|
||||
- 配置日志收集
|
||||
- 设置存储空间监控
|
||||
- 建立备份计划
|
||||
|
||||
---
|
||||
|
||||
## 🚀 现在您可以开始使用私有 Docker Registry!
|
||||
|
||||
**快速测试:**
|
||||
```bash
|
||||
./deployment/scripts/cicd-integration.sh test
|
||||
```
|
||||
|
||||
**查看服务状态:**
|
||||
```bash
|
||||
./deployment/scripts/cicd-integration.sh status
|
||||
```
|
||||
|
||||
**访问 Web UI:**
|
||||
http://192.168.1.83:5002
|
||||
|
||||
享受您的私有 CI/CD 环境! 🎉
|
||||
-350
@@ -1,350 +0,0 @@
|
||||
# 最终配置和使用指南
|
||||
|
||||
## ✅ 已完成的配置
|
||||
|
||||
### 1. OrbStack Docker 配置
|
||||
|
||||
**配置文件**: `~/.orbstack/config/docker.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"insecure-registries": [
|
||||
"127.0.0.1:8080",
|
||||
"localhost:8080"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- ✅ insecure-registries 允许连接到本地 Harbor
|
||||
- ❌ proxies 配置不支持(OrbStack 限制)
|
||||
- ✅ 代理通过脚本中的环境变量实现
|
||||
|
||||
### 2. Harbor 配置
|
||||
|
||||
**位置**: `~/work/codes/tools/macos/harbor`
|
||||
|
||||
**访问地址**:
|
||||
- HTTP: http://127.0.0.1:8080 (重定向到 HTTPS)
|
||||
- HTTPS: https://127.0.0.1:8443
|
||||
- 凭证: admin / admin123
|
||||
|
||||
**HTTPS 配置**: Harbor 强制使用 HTTPS,但 docker login/push 会自动处理重定向
|
||||
|
||||
### 3. 构建配置
|
||||
|
||||
**配置文件**: `monitoring-versions.env`
|
||||
|
||||
```bash
|
||||
# 使用本地构建模式(避免 buildx HTTPS 问题)
|
||||
LOCAL_BUILD=true
|
||||
PUSH_TO_REGISTRY=true
|
||||
PLATFORMS=linux/amd64
|
||||
|
||||
# Harbor 配置
|
||||
REGISTRY=127.0.0.1:8080/ljwx
|
||||
HARBOR_HOST=127.0.0.1:8080
|
||||
HARBOR_USERNAME=admin
|
||||
HARBOR_PASSWORD=admin123
|
||||
|
||||
# 代理配置(自动使用)
|
||||
PROXY_PORT=7890
|
||||
HTTP_PROXY=http://127.0.0.1:7890
|
||||
HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
## 🚀 使用流程
|
||||
|
||||
### 一键构建并推送
|
||||
|
||||
```bash
|
||||
# 1. 确保 OrbStack 运行
|
||||
open -a OrbStack
|
||||
|
||||
# 2. 确保 Harbor 运行
|
||||
cd ~/work/codes/tools/macos/harbor
|
||||
docker-compose ps
|
||||
|
||||
# 3. 确保代理运行
|
||||
lsof -i :7890
|
||||
|
||||
# 4. 构建并推送镜像
|
||||
cd ~/work/codes/shenye/release
|
||||
./build-and-push.sh mysql
|
||||
```
|
||||
|
||||
### 构建所有镜像
|
||||
|
||||
```bash
|
||||
# 构建所有应用镜像
|
||||
./build-and-push.sh apps
|
||||
|
||||
# 构建所有监控镜像
|
||||
./build-and-push.sh monitoring
|
||||
|
||||
# 构建所有镜像
|
||||
./build-and-push.sh all
|
||||
```
|
||||
|
||||
### 构建单个镜像
|
||||
|
||||
```bash
|
||||
# 后端服务
|
||||
./build-and-push.sh boot
|
||||
|
||||
# 前端管理
|
||||
./build-and-push.sh admin
|
||||
|
||||
# 大屏服务
|
||||
./build-and-push.sh bigscreen
|
||||
|
||||
# MySQL
|
||||
./build-and-push.sh mysql
|
||||
|
||||
# Redis
|
||||
./build-and-push.sh redis
|
||||
```
|
||||
|
||||
## 📋 工作原理
|
||||
|
||||
### 为什么使用本地构建模式?
|
||||
|
||||
1. **buildx HTTPS 问题**:
|
||||
- `docker buildx build --push` 需要 Harbor 的 HTTP 端口
|
||||
- Harbor 强制 HTTP 重定向到 HTTPS
|
||||
- buildx 无法正确处理这个重定向
|
||||
|
||||
2. **本地构建解决方案**:
|
||||
- `docker build` 构建镜像到本地
|
||||
- `docker push` 推送到 Harbor
|
||||
- docker push 可以正确处理 HTTP→HTTPS 重定向
|
||||
|
||||
### 构建流程
|
||||
|
||||
```
|
||||
1. setup_docker_config()
|
||||
├── 设置代理环境变量
|
||||
└── 检测代理连接
|
||||
|
||||
2. check_harbor_health()
|
||||
└── 检查 Harbor 是否运行
|
||||
|
||||
3. login_harbor()
|
||||
└── docker login 127.0.0.1:8080
|
||||
|
||||
4. build_app_image()
|
||||
├── docker build (本地构建)
|
||||
└── docker push (推送到 Harbor)
|
||||
|
||||
5. show_summary()
|
||||
└── 显示构建结果
|
||||
```
|
||||
|
||||
## 🔧 技术细节
|
||||
|
||||
### 代理配置
|
||||
|
||||
脚本自动导出环境变量:
|
||||
```bash
|
||||
export HTTP_PROXY=http://127.0.0.1:7890
|
||||
export HTTPS_PROXY=http://127.0.0.1:7890
|
||||
export NO_PROXY=localhost,127.0.0.1,*.local
|
||||
```
|
||||
|
||||
传递给 Docker 构建:
|
||||
```bash
|
||||
docker build \
|
||||
--build-arg HTTP_PROXY=$HTTP_PROXY \
|
||||
--build-arg HTTPS_PROXY=$HTTPS_PROXY \
|
||||
--build-arg NO_PROXY=$NO_PROXY \
|
||||
...
|
||||
```
|
||||
|
||||
### Harbor 连接
|
||||
|
||||
Docker login/push 处理流程:
|
||||
```
|
||||
1. docker login 127.0.0.1:8080
|
||||
├── 尝试 HTTP 连接
|
||||
├── 收到 308 重定向到 HTTPS
|
||||
└── 自动切换到 HTTPS 8443
|
||||
|
||||
2. docker push 127.0.0.1:8080/ljwx/xxx
|
||||
├── 尝试 HTTP 连接
|
||||
├── 收到 308 重定向到 HTTPS
|
||||
└── 自动切换到 HTTPS 8443
|
||||
```
|
||||
|
||||
### 镜像标签
|
||||
|
||||
每个镜像生成两个标签:
|
||||
- 版本标签: `127.0.0.1:8080/ljwx/ljwx-mysql:2.0.3`
|
||||
- latest 标签: `127.0.0.1:8080/ljwx/ljwx-mysql:latest`
|
||||
|
||||
## 📊 Harbor 管理
|
||||
|
||||
### 访问 Harbor Web UI
|
||||
|
||||
```bash
|
||||
# 1. 访问
|
||||
open http://127.0.0.1:8080
|
||||
|
||||
# 2. 登录
|
||||
Username: admin
|
||||
Password: admin123
|
||||
|
||||
# 3. 查看镜像
|
||||
进入 "ljwx" 项目 → 查看仓库列表
|
||||
```
|
||||
|
||||
### 使用 API 管理
|
||||
|
||||
```bash
|
||||
# 列出所有仓库
|
||||
curl -u admin:admin123 http://127.0.0.1:8080/api/v2.0/projects/ljwx/repositories
|
||||
|
||||
# 列出镜像标签
|
||||
curl -u admin:admin123 \
|
||||
http://127.0.0.1:8080/api/v2.0/projects/ljwx/repositories/ljwx-mysql/artifacts
|
||||
|
||||
# 检查健康状态
|
||||
curl -L http://127.0.0.1:8080/api/v2.0/health
|
||||
```
|
||||
|
||||
### 拉取镜像
|
||||
|
||||
```bash
|
||||
# 从 Harbor 拉取镜像
|
||||
docker pull 127.0.0.1:8080/ljwx/ljwx-mysql:2.0.3
|
||||
|
||||
# 拉取 latest
|
||||
docker pull 127.0.0.1:8080/ljwx/ljwx-mysql:latest
|
||||
```
|
||||
|
||||
## 🛠️ 常见问题
|
||||
|
||||
### 问题 1: 代理不工作
|
||||
|
||||
**症状**: docker pull mysql:8.0 很慢或超时
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查代理
|
||||
lsof -i :7890
|
||||
|
||||
# 2. 测试代理
|
||||
curl --proxy http://127.0.0.1:7890 https://www.google.com
|
||||
|
||||
# 3. 手动设置代理
|
||||
export HTTP_PROXY=http://127.0.0.1:7890
|
||||
export HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
### 问题 2: Harbor 连接被拒绝
|
||||
|
||||
**症状**: connect: connection refused
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Harbor 是否运行
|
||||
cd ~/work/codes/tools/macos/harbor
|
||||
docker-compose ps
|
||||
|
||||
# 2. 启动 Harbor
|
||||
docker-compose up -d
|
||||
|
||||
# 3. 等待启动完成
|
||||
sleep 30
|
||||
|
||||
# 4. 测试连接
|
||||
curl -L http://127.0.0.1:8080/api/v2.0/health
|
||||
```
|
||||
|
||||
### 问题 3: 登录失败
|
||||
|
||||
**症状**: unauthorized
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 重新登录
|
||||
docker login 127.0.0.1:8080
|
||||
Username: admin
|
||||
Password: admin123
|
||||
```
|
||||
|
||||
### 问题 4: 推送失败
|
||||
|
||||
**症状**: denied: requested access to the resource is denied
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查项目是否存在
|
||||
curl -u admin:admin123 http://127.0.0.1:8080/api/v2.0/projects/ljwx
|
||||
|
||||
# 2. 如果不存在,创建项目
|
||||
# 访问 http://127.0.0.1:8080
|
||||
# Projects → New Project → Name: ljwx, Public: Yes
|
||||
|
||||
# 3. 重新推送
|
||||
docker push 127.0.0.1:8080/ljwx/ljwx-mysql:2.0.3
|
||||
```
|
||||
|
||||
## 📝 检查清单
|
||||
|
||||
构建前检查:
|
||||
|
||||
```bash
|
||||
# ✅ OrbStack 运行
|
||||
ps aux | grep OrbStack
|
||||
|
||||
# ✅ Harbor 运行
|
||||
cd ~/work/codes/tools/macos/harbor && docker-compose ps | grep healthy
|
||||
|
||||
# ✅ 代理运行
|
||||
lsof -i :7890
|
||||
|
||||
# ✅ Docker 登录
|
||||
docker login 127.0.0.1:8080
|
||||
|
||||
# ✅ 测试拉取
|
||||
docker pull mysql:8.0
|
||||
|
||||
# ✅ 开始构建
|
||||
./build-and-push.sh mysql
|
||||
```
|
||||
|
||||
## 🎯 下一步
|
||||
|
||||
1. **构建所有镜像**:
|
||||
```bash
|
||||
./build-and-push.sh all
|
||||
```
|
||||
|
||||
2. **部署到生产环境**:
|
||||
```bash
|
||||
# 在生产服务器上拉取镜像
|
||||
docker pull 127.0.0.1:8080/ljwx/ljwx-boot:2.0.3
|
||||
docker pull 127.0.0.1:8080/ljwx/ljwx-admin:2.0.3
|
||||
docker pull 127.0.0.1:8080/ljwx/ljwx-bigscreen:2.0.3
|
||||
```
|
||||
|
||||
3. **使用 docker-compose 部署**:
|
||||
```bash
|
||||
# 更新 docker-compose.yml 中的镜像地址
|
||||
# image: 127.0.0.1:8080/ljwx/ljwx-boot:2.0.3
|
||||
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [BUILD_WITH_HARBOR.md](./BUILD_WITH_HARBOR.md) - Harbor 详细指南
|
||||
- [PROXY_CONFIG.md](./PROXY_CONFIG.md) - 代理配置详解
|
||||
- [ORBSTACK_CONFIG.md](./ORBSTACK_CONFIG.md) - OrbStack 配置说明
|
||||
- [DOCKER_README.md](./DOCKER_README.md) - Docker Compose 使用指南
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-26
|
||||
**版本**: 1.0.0
|
||||
**状态**: ✅ 已验证可用
|
||||
@@ -1,252 +0,0 @@
|
||||
# Gitea 数据保护解决方案
|
||||
|
||||
## 问题解决
|
||||
|
||||
✅ **自动定时备份** - 每6小时自动备份,无需手动干预
|
||||
✅ **实时数据同步** - 数据变更实时同步到保护目录
|
||||
✅ **一键恢复** - 单命令快速恢复任意备份点
|
||||
✅ **多层保护** - 卷备份 + 实时同步 + 安全备份
|
||||
✅ **智能清理** - 自动清理30天前的旧备份
|
||||
✅ **健康监控** - 全方位监控数据完整性
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 初始化数据保护
|
||||
|
||||
```bash
|
||||
# 一键设置所有数据保护机制
|
||||
./gitea-data-protection.sh auto-setup
|
||||
```
|
||||
|
||||
### 2. 启动保护服务
|
||||
|
||||
```bash
|
||||
# 启动 Gitea + 数据保护
|
||||
./gitea-data-protection.sh start
|
||||
```
|
||||
|
||||
### 3. 验证保护状态
|
||||
|
||||
```bash
|
||||
# 检查所有保护机制
|
||||
./gitea-data-protection.sh health
|
||||
```
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 自动备份
|
||||
|
||||
- **定时备份**: 每6小时自动执行
|
||||
- **命名规范**: `gitea-YYYYMMDD-HHMMSS.tar.gz`
|
||||
- **元数据记录**: 每个备份都有详细信息
|
||||
- **自动清理**: 保留30天内的备份
|
||||
|
||||
```bash
|
||||
# 手动创建备份
|
||||
./gitea-data-protection.sh backup
|
||||
|
||||
# 创建命名备份
|
||||
./gitea-data-protection.sh backup "important-milestone"
|
||||
```
|
||||
|
||||
### 数据恢复
|
||||
|
||||
```bash
|
||||
# 列出可用备份并恢复
|
||||
./gitea-data-protection.sh restore
|
||||
|
||||
# 恢复特定备份
|
||||
./gitea-data-protection.sh restore gitea-20240824-120000.tar.gz
|
||||
```
|
||||
|
||||
### 实时同步
|
||||
|
||||
- 每5分钟同步数据变更到 `data-protection/gitea/realtime-sync/`
|
||||
- 守护进程持续运行,确保数据实时保护
|
||||
- 即使主备份丢失,同步目录仍有最新数据
|
||||
|
||||
### 健康监控
|
||||
|
||||
```bash
|
||||
# 全面健康检查
|
||||
./gitea-data-protection.sh health
|
||||
|
||||
# 检查内容包括:
|
||||
# - 服务运行状态
|
||||
# - 数据卷完整性
|
||||
# - Git 仓库数量统计
|
||||
# - 最近备份状态
|
||||
# - 保护机制工作状态
|
||||
```
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
infra/
|
||||
├── gitea-data-protection.sh # 主管理脚本
|
||||
├── backup/gitea/ # 备份文件存储
|
||||
│ ├── gitea-20240824-120000.tar.gz # 备份文件
|
||||
│ ├── gitea-20240824-120000.meta # 备份元数据
|
||||
│ └── safety-backup-*.tar.gz # 恢复前安全备份
|
||||
├── data-protection/gitea/ # 保护机制配置
|
||||
│ ├── protection-config.yaml # 保护配置
|
||||
│ ├── realtime-sync/ # 实时同步目录
|
||||
│ ├── sync-daemon.sh # 同步守护进程
|
||||
│ └── sync-daemon.pid # 守护进程 PID
|
||||
├── scripts/
|
||||
│ └── gitea-auto-backup.sh # 自动备份脚本
|
||||
└── logs/
|
||||
└── gitea-protection.log # 保护日志
|
||||
```
|
||||
|
||||
## 多层保护机制
|
||||
|
||||
### 第1层:Docker 数据卷持久化
|
||||
- 使用命名卷 `gitea-data` 存储所有 Gitea 数据
|
||||
- 卷生命周期独立于容器,重启不丢失
|
||||
|
||||
### 第2层:定时自动备份
|
||||
- Cron 任务每6小时自动备份
|
||||
- 完整的数据卷快照,包含所有仓库和配置
|
||||
- 备份前停止服务确保数据一致性
|
||||
|
||||
### 第3层:实时数据同步
|
||||
- 守护进程每5分钟同步数据变更
|
||||
- 本地文件系统镜像,可直接访问
|
||||
- 即使备份丢失也能快速恢复
|
||||
|
||||
### 第4层:恢复前安全备份
|
||||
- 每次恢复前自动创建当前状态备份
|
||||
- 防止恢复操作意外损坏现有数据
|
||||
- 提供恢复操作的"后悔药"
|
||||
|
||||
## 故障恢复场景
|
||||
|
||||
### 场景1: 容器重启后数据丢失
|
||||
```bash
|
||||
# 检查数据卷状态
|
||||
./gitea-data-protection.sh health
|
||||
|
||||
# 如果数据卷完好,直接重启服务
|
||||
./gitea-data-protection.sh start
|
||||
|
||||
# 如果数据卷损坏,恢复最新备份
|
||||
./gitea-data-protection.sh restore
|
||||
```
|
||||
|
||||
### 场景2: 误操作删除仓库
|
||||
```bash
|
||||
# 查看可用备份时间点
|
||||
ls -la backup/gitea/
|
||||
|
||||
# 恢复到误操作前的备份
|
||||
./gitea-data-protection.sh restore gitea-20240824-100000.tar.gz
|
||||
```
|
||||
|
||||
### 场景3: 系统完全重装
|
||||
```bash
|
||||
# 重新部署基础环境
|
||||
docker-compose -f docker/compose/gitea-compose.yml up -d
|
||||
|
||||
# 恢复数据(自动创建卷并恢复)
|
||||
./gitea-data-protection.sh restore <backup-file>
|
||||
|
||||
# 重新初始化保护机制
|
||||
./gitea-data-protection.sh auto-setup
|
||||
```
|
||||
|
||||
## 监控和维护
|
||||
|
||||
### 日志监控
|
||||
```bash
|
||||
# 查看保护日志
|
||||
tail -f logs/gitea-protection.log
|
||||
|
||||
# 查看 Gitea 服务日志
|
||||
docker-compose -f docker/compose/gitea-compose.yml logs -f gitea
|
||||
```
|
||||
|
||||
### 存储管理
|
||||
```bash
|
||||
# 查看备份占用空间
|
||||
du -sh backup/gitea/
|
||||
|
||||
# 手动清理旧备份(超过30天)
|
||||
find backup/gitea/ -name "gitea-*.tar.gz" -mtime +30 -delete
|
||||
```
|
||||
|
||||
### 定时任务管理
|
||||
```bash
|
||||
# 查看当前定时任务
|
||||
crontab -l | grep gitea
|
||||
|
||||
# 临时禁用自动备份
|
||||
crontab -l | grep -v gitea-auto-backup | crontab -
|
||||
|
||||
# 重新启用自动备份
|
||||
./gitea-data-protection.sh auto-setup
|
||||
```
|
||||
|
||||
## 高级配置
|
||||
|
||||
### 自定义备份间隔
|
||||
编辑 `data-protection/gitea/protection-config.yaml`:
|
||||
```yaml
|
||||
settings:
|
||||
backup_interval_hours: 4 # 改为4小时一次
|
||||
```
|
||||
|
||||
重新运行: `./gitea-data-protection.sh auto-setup`
|
||||
|
||||
### 自定义同步间隔
|
||||
编辑 `data-protection/gitea/sync-daemon.sh` 中的 `sleep 300` 改为其他秒数。
|
||||
|
||||
### 远程备份
|
||||
可在备份脚本基础上添加 rsync 或 scp 命令,将备份同步到远程服务器:
|
||||
|
||||
```bash
|
||||
# 在 backup() 函数末尾添加
|
||||
rsync -av "${BACKUP_PATH}" user@remote-server:/path/to/remote/backup/
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **定期验证**: 每月验证一次备份恢复流程
|
||||
2. **监控空间**: 定期检查备份目录磁盘空间
|
||||
3. **测试恢复**: 在测试环境验证恢复流程
|
||||
4. **多地备份**: 考虑将备份同步到远程位置
|
||||
5. **文档更新**: 记录重要的配置变更和恢复操作
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 备份失败
|
||||
```bash
|
||||
# 检查 Docker 服务状态
|
||||
docker system df
|
||||
docker volume ls
|
||||
|
||||
# 检查磁盘空间
|
||||
df -h
|
||||
|
||||
# 查看详细错误日志
|
||||
tail -50 logs/gitea-protection.log
|
||||
```
|
||||
|
||||
### 恢复失败
|
||||
```bash
|
||||
# 检查备份文件完整性
|
||||
tar -tzf backup/gitea/backup-file.tar.gz
|
||||
|
||||
# 手动验证数据卷
|
||||
docker run --rm -v gitea-data:/data busybox ls -la /data
|
||||
```
|
||||
|
||||
### 同步守护进程异常
|
||||
```bash
|
||||
# 检查进程状态
|
||||
ps aux | grep sync-daemon
|
||||
|
||||
# 重启同步守护进程
|
||||
./gitea-data-protection.sh stop
|
||||
./gitea-data-protection.sh start
|
||||
```
|
||||
@@ -1,98 +0,0 @@
|
||||
# GitHub 推送设置指南
|
||||
|
||||
## 当前状态 ✅
|
||||
|
||||
- ✅ Git仓库已初始化
|
||||
- ✅ 所有文件已提交 (133个文件)
|
||||
- ✅ 提交信息已创建
|
||||
- ⏳ 需要添加GitHub远程仓库
|
||||
|
||||
## 🔧 GitHub设置步骤
|
||||
|
||||
### 1. 创建GitHub仓库
|
||||
|
||||
在GitHub上创建一个新的仓库,建议命名为 `infra` 或 `cicd-infrastructure`
|
||||
|
||||
### 2. 添加远程仓库并推送
|
||||
|
||||
```bash
|
||||
# 替换为您的实际GitHub仓库地址
|
||||
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO_NAME.git
|
||||
|
||||
# 推送到GitHub
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### 3. 推送完整命令示例
|
||||
|
||||
```bash
|
||||
# 如果您的GitHub用户名是 brunogao,仓库名是 infra
|
||||
git remote add origin https://github.com/brunogao/infra.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### 4. SSH方式(推荐)
|
||||
|
||||
如果您配置了SSH密钥:
|
||||
```bash
|
||||
git remote add origin git@github.com:YOUR_USERNAME/YOUR_REPO_NAME.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
## 📋 当前提交信息
|
||||
|
||||
```
|
||||
🚀 feat: 企业级CI/CD基础设施完整部署方案
|
||||
|
||||
✨ 新功能:
|
||||
- 一键自动化部署脚本 (build-infra.sh)
|
||||
- 统一端口配置 (3开头端口,避免冲突)
|
||||
- 多平台Docker构建支持 (AMD64 + ARM64)
|
||||
- Jenkins Configuration as Code (零手动配置)
|
||||
- 完整的服务验证和健康检查
|
||||
|
||||
🏗️ 核心组件:
|
||||
- Jenkins LTS + JDK21 (端口38080)
|
||||
- Gitea 1.21 (端口33000, SSH: 32222)
|
||||
- Docker Registry + UI (端口35001/35002)
|
||||
- 统一cicd-network网络
|
||||
|
||||
📋 管理工具:
|
||||
- 自动化部署和验证脚本
|
||||
- 健康检查和日志管理工具
|
||||
- 完整的文档和故障排查指南
|
||||
|
||||
🎯 已验证功能:
|
||||
- 所有服务正常启动和运行
|
||||
- API和Web界面完全可访问
|
||||
- 多平台构建环境就绪
|
||||
- 完整的CI/CD流水线支持
|
||||
|
||||
适用环境: Mac Studio M2 + Docker Desktop
|
||||
```
|
||||
|
||||
## 📊 统计信息
|
||||
|
||||
- **文件数量**: 133个文件
|
||||
- **代码行数**: 21,015+ 行
|
||||
- **主要功能**: 完整的CI/CD基础设施
|
||||
- **部署方式**: 一键自动化部署
|
||||
- **支持平台**: Mac Studio M2 + Docker
|
||||
|
||||
## 🎯 仓库特色
|
||||
|
||||
这个仓库包含:
|
||||
- 🚀 **一键部署脚本**: 15分钟完成所有配置
|
||||
- 📚 **完整文档**: README、快速开始、构建计划等
|
||||
- 🔧 **管理工具**: 健康检查、日志管理、备份恢复
|
||||
- 🏗️ **企业级配置**: Jenkins CasC、多平台构建、完整CI/CD
|
||||
- 🔍 **故障排查**: 详细的问题诊断和解决方案
|
||||
|
||||
## 下一步
|
||||
|
||||
1. 在GitHub上创建仓库
|
||||
2. 复制仓库URL
|
||||
3. 执行上面的git remote add命令
|
||||
4. 推送到GitHub
|
||||
|
||||
推送完成后,您的GitHub仓库将包含这个完整的CI/CD基础设施项目!
|
||||
@@ -1,202 +0,0 @@
|
||||
# 🎉 Jenkins 自动化配置部署成功!
|
||||
|
||||
## 部署摘要
|
||||
|
||||
✅ **Jenkins 自动化配置已成功部署并运行正常**
|
||||
|
||||
- 📍 **Jenkins 访问地址**: http://localhost:8081
|
||||
- 🔐 **登录信息**: admin / admin123
|
||||
- 🐳 **容器状态**: 健康运行中
|
||||
- 📊 **存储使用**: 3% (良好)
|
||||
- 🔗 **服务集成**: Registry(35001) + Gitea(192.168.1.6:3000)
|
||||
|
||||
## 🚀 已完成的自动化配置
|
||||
|
||||
### 核心功能
|
||||
- ✅ **完全跳过设置向导** - 无需手动配置
|
||||
- ✅ **管理员用户自动创建** - admin/admin123
|
||||
- ✅ **Configuration as Code** - 配置文件化管理
|
||||
- ✅ **Docker 集成** - 完整的 Docker 支持
|
||||
- ✅ **多平台构建支持** - linux/amd64, linux/arm64
|
||||
|
||||
### 环境集成
|
||||
- ✅ **Registry 集成** - localhost:35001 (已测试连通)
|
||||
- ✅ **Gitea 集成** - http://192.168.1.6:3000 (配置就绪)
|
||||
- ✅ **网络配置** - 使用现有 cicd-network
|
||||
- ✅ **凭据模板** - Docker Registry 和 Gitea API Token
|
||||
|
||||
### 预置作业
|
||||
- ✅ **hello-world-demo** - 验证环境配置的示例作业
|
||||
- ✅ **环境检查** - 自动检测 Registry 和 Gitea 连接状态
|
||||
- ✅ **Docker 版本检查** - 验证 Docker 集成正常
|
||||
|
||||
## 🛠️ 管理命令
|
||||
|
||||
使用 `./jenkins-quick-manager.sh` 进行日常管理:
|
||||
|
||||
```bash
|
||||
# 基础管理
|
||||
./jenkins-quick-manager.sh start # 启动服务
|
||||
./jenkins-quick-manager.sh stop # 停止服务
|
||||
./jenkins-quick-manager.sh restart # 重启服务
|
||||
./jenkins-quick-manager.sh status # 查看状态
|
||||
|
||||
# 监控和维护
|
||||
./jenkins-quick-manager.sh health # 健康检查
|
||||
./jenkins-quick-manager.sh logs # 查看日志
|
||||
./jenkins-quick-manager.sh backup # 备份配置
|
||||
./jenkins-quick-manager.sh test # 测试说明
|
||||
```
|
||||
|
||||
## 📋 下一步操作
|
||||
|
||||
### 1. 验证自动化配置
|
||||
1. 访问 http://localhost:8081
|
||||
2. 使用 admin/admin123 登录
|
||||
3. 运行 `hello-world-demo` 作业
|
||||
4. 检查作业输出确认环境正常
|
||||
|
||||
### 2. 完善集成配置
|
||||
1. **Gitea Token**: 在 Gitea 中生成 Personal Access Token
|
||||
- 访问 Gitea → Settings → Applications → Generate New Token
|
||||
- 在 Jenkins 中更新 `gitea-api-token` 凭据
|
||||
|
||||
2. **Registry 认证**: 如需自定义 Registry 认证
|
||||
- 在 Jenkins 中更新 `docker-registry-auth` 凭据
|
||||
|
||||
### 3. 创建第一个 CI/CD 流水线
|
||||
1. 在 Jenkins 中创建新的 Pipeline 作业
|
||||
2. 使用预配置的环境变量:
|
||||
- `DOCKER_REGISTRY`: localhost:35001
|
||||
- `GITEA_URL`: http://192.168.1.6:3000
|
||||
- `BUILD_PLATFORMS`: linux/amd64,linux/arm64
|
||||
|
||||
## 🏗️ 示例 Pipeline 模板
|
||||
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
IMAGE_NAME = "${env.JOB_NAME.toLowerCase()}"
|
||||
IMAGE_TAG = "${env.BUILD_NUMBER}"
|
||||
FULL_IMAGE = "${env.DOCKER_REGISTRY}/${env.IMAGE_NAME}:${env.IMAGE_TAG}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('检出代码') {
|
||||
steps {
|
||||
// 使用 Gitea 仓库
|
||||
git branch: 'main',
|
||||
url: "${env.GITEA_URL}/your-project.git",
|
||||
credentialsId: 'gitea-api-token'
|
||||
}
|
||||
}
|
||||
|
||||
stage('构建应用') {
|
||||
steps {
|
||||
sh 'echo "构建你的应用..."'
|
||||
// 添加你的构建步骤
|
||||
}
|
||||
}
|
||||
|
||||
stage('构建 Docker 镜像') {
|
||||
steps {
|
||||
sh """
|
||||
docker build -t ${env.FULL_IMAGE} .
|
||||
docker push ${env.FULL_IMAGE}
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
stage('多平台构建') {
|
||||
steps {
|
||||
sh """
|
||||
docker buildx build \\
|
||||
--platform ${env.BUILD_PLATFORMS} \\
|
||||
--tag ${env.FULL_IMAGE} \\
|
||||
--push .
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
cleanWs()
|
||||
}
|
||||
success {
|
||||
echo "✅ 构建成功: ${env.FULL_IMAGE}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📁 配置文件位置
|
||||
|
||||
- **Docker Compose**: `docker/compose/jenkins-quick.yml`
|
||||
- **CasC 配置**: `docker/compose/jenkins/casc/jenkins.yaml`
|
||||
- **管理脚本**: `jenkins-quick-manager.sh`
|
||||
- **数据卷**: `compose_jenkins-quick-data`
|
||||
|
||||
## 🔧 自定义配置
|
||||
|
||||
### 修改 CasC 配置
|
||||
编辑 `docker/compose/jenkins/casc/jenkins.yaml` 文件,然后:
|
||||
```bash
|
||||
./jenkins-quick-manager.sh restart
|
||||
```
|
||||
|
||||
### 添加插件
|
||||
在 CasC 配置中添加插件,或通过 Jenkins UI 安装后导出配置。
|
||||
|
||||
### 扩展环境变量
|
||||
在 CasC 配置的 `globalNodeProperties` 部分添加新的环境变量。
|
||||
|
||||
## 🚨 故障排除
|
||||
|
||||
### Jenkins 无法启动
|
||||
```bash
|
||||
# 查看日志
|
||||
./jenkins-quick-manager.sh logs
|
||||
|
||||
# 检查容器状态
|
||||
docker ps -a | grep jenkins-quick
|
||||
```
|
||||
|
||||
### 配置未生效
|
||||
```bash
|
||||
# 检查配置文件挂载
|
||||
docker exec jenkins-quick ls -la /var/jenkins_home/casc_configs
|
||||
|
||||
# 重启服务重新加载配置
|
||||
./jenkins-quick-manager.sh restart
|
||||
```
|
||||
|
||||
### 网络连接问题
|
||||
```bash
|
||||
# 检查网络
|
||||
docker network ls | grep cicd-network
|
||||
|
||||
# 测试服务连接
|
||||
./jenkins-quick-manager.sh status
|
||||
```
|
||||
|
||||
## 🎯 性能优化建议
|
||||
|
||||
1. **内存设置**: 根据使用情况调整 `JAVA_OPTS` 中的 `-Xmx` 参数
|
||||
2. **执行器数量**: 在 CasC 中调整 `numExecutors` 数值
|
||||
3. **定期备份**: 设置定时任务执行 `./jenkins-quick-manager.sh backup`
|
||||
4. **日志清理**: 配置日志轮转和清理策略
|
||||
|
||||
## 🎊 恭喜!
|
||||
|
||||
你现在拥有一个完全自动化配置的 Jenkins CI/CD 环境,具备:
|
||||
|
||||
- ⚡ **零配置启动** - 开箱即用
|
||||
- 🔧 **完整工具链** - Docker + Git + 多平台构建
|
||||
- 🔗 **服务集成** - Registry + Gitea 无缝集成
|
||||
- 📊 **健康监控** - 自动健康检查和状态监控
|
||||
- 💾 **配置管理** - Configuration as Code 便于维护
|
||||
|
||||
**立即开始使用你的自动化 CI/CD 流水线吧!**
|
||||
@@ -1,629 +0,0 @@
|
||||
# 灵境万象系统 - Kubernetes 部署指南
|
||||
|
||||
本指南说明如何将灵境万象系统一键部署到 Kubernetes 集群。
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [系统架构](#系统架构)
|
||||
- [前置要求](#前置要求)
|
||||
- [快速开始](#快速开始)
|
||||
- [详细配置](#详细配置)
|
||||
- [运维管理](#运维管理)
|
||||
- [故障排查](#故障排查)
|
||||
- [最佳实践](#最佳实践)
|
||||
|
||||
## 系统架构
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ Kubernetes Cluster (ljwx-system) │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
|
||||
│ │ Ingress │───▶│ ljwx-admin │ │ ljwx- │ │
|
||||
│ │ Controller │ │ (Vue前端) │ │ bigscreen │ │
|
||||
│ └─────────────┘ │ Pods: 2 │ │ (FastAPI)│ │
|
||||
│ │ └─────────────┘ │ Pods: 2 │ │
|
||||
│ │ │ └───────────┘ │
|
||||
│ ▼ ▼ │ │
|
||||
│ ┌─────────────────────────────────────────────┘ │
|
||||
│ │ ljwx-boot (Spring Boot) │
|
||||
│ │ Pods: 2 │
|
||||
│ └────────────────┬───────────────┬───────────────────┘
|
||||
│ │ │ │
|
||||
│ ┌─────────▼──────┐ ┌────▼─────────┐ │
|
||||
│ │ ljwx-mysql │ │ ljwx-redis │ │
|
||||
│ │ StatefulSet │ │ Deployment │ │
|
||||
│ │ (持久化存储) │ │ (缓存) │ │
|
||||
│ └────────────────┘ └──────────────┘ │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 前置要求
|
||||
|
||||
### 1. Kubernetes 集群
|
||||
|
||||
```bash
|
||||
# 检查 K8s 版本(需要 1.19+)
|
||||
kubectl version --short
|
||||
|
||||
# 检查集群连接
|
||||
kubectl cluster-info
|
||||
|
||||
# 查看节点状态
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
**支持的 Kubernetes 平台**:
|
||||
- Docker Desktop (macOS/Windows)
|
||||
- Minikube
|
||||
- K3s
|
||||
- Kind
|
||||
- OrbStack (macOS)
|
||||
- 生产级集群 (GKE, EKS, AKS, etc.)
|
||||
|
||||
### 2. 本地 Docker Registry
|
||||
|
||||
系统需要本地 Docker Registry 来存储镜像:
|
||||
|
||||
```bash
|
||||
# 检查 Registry 是否运行
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
|
||||
# 如果未运行,启动 Registry
|
||||
cd ~/work/codes/tools/macos/registery
|
||||
./install-local-registry-macos.sh
|
||||
```
|
||||
|
||||
### 3. 必要工具
|
||||
|
||||
- `kubectl` - Kubernetes 命令行工具
|
||||
- `docker` - Docker 客户端
|
||||
- `jq` - JSON 处理工具(可选,用于状态检查)
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 完整部署(推荐)
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
cd /Users/brunogao/work/codes/shenye/release
|
||||
|
||||
# 一键部署(包括构建镜像)
|
||||
./k8s-deploy.sh
|
||||
```
|
||||
|
||||
这将自动完成:
|
||||
- ✅ 检查前置条件
|
||||
- ✅ 生成 K8s 配置文件
|
||||
- ✅ 构建 Docker 镜像
|
||||
- ✅ 推送镜像到本地 Registry
|
||||
- ✅ 部署到 Kubernetes
|
||||
- ✅ 等待服务就绪
|
||||
- ✅ 验证部署状态
|
||||
|
||||
### 2. 使用已有镜像
|
||||
|
||||
如果镜像已经构建好:
|
||||
|
||||
```bash
|
||||
# 跳过镜像构建
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### 3. 查看部署状态
|
||||
|
||||
```bash
|
||||
# 查看详细状态
|
||||
./k8s-status.sh
|
||||
|
||||
# 查看 Pods
|
||||
kubectl get pods -n ljwx-system
|
||||
|
||||
# 查看服务
|
||||
kubectl get svc -n ljwx-system
|
||||
```
|
||||
|
||||
## 详细配置
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
```bash
|
||||
# 自定义命名空间
|
||||
K8S_NAMESPACE=ljwx-prod ./k8s-deploy.sh
|
||||
|
||||
# 自定义域名
|
||||
LJWX_DOMAIN=ljwx.example.com ./k8s-deploy.sh
|
||||
|
||||
# 自定义 MySQL 密码
|
||||
MYSQL_ROOT_PASSWORD=MySecurePassword123 ./k8s-deploy.sh
|
||||
|
||||
# 组合配置
|
||||
K8S_NAMESPACE=ljwx-prod \
|
||||
LJWX_DOMAIN=ljwx.example.com \
|
||||
MYSQL_ROOT_PASSWORD=SecurePass123 \
|
||||
./k8s-deploy.sh
|
||||
```
|
||||
|
||||
### 命令行选项
|
||||
|
||||
```bash
|
||||
# 查看所有选项
|
||||
./k8s-deploy.sh --help
|
||||
|
||||
# 跳过 MySQL 部署(使用外部数据库)
|
||||
./k8s-deploy.sh --skip-mysql
|
||||
|
||||
# 跳过 Redis 部署(使用外部缓存)
|
||||
./k8s-deploy.sh --skip-redis
|
||||
|
||||
# 指定镜像仓库
|
||||
./k8s-deploy.sh --registry registry.example.com:5000
|
||||
|
||||
# 指定命名空间
|
||||
./k8s-deploy.sh --namespace ljwx-production
|
||||
|
||||
# 指定域名
|
||||
./k8s-deploy.sh --domain ljwx.company.com
|
||||
```
|
||||
|
||||
### 配置外部数据库
|
||||
|
||||
如果使用外部 MySQL 和 Redis:
|
||||
|
||||
```bash
|
||||
# 1. 跳过内部数据库部署
|
||||
./k8s-deploy.sh --skip-mysql --skip-redis
|
||||
|
||||
# 2. 手动创建 Secret 连接外部数据库
|
||||
kubectl create secret generic ljwx-secret \
|
||||
--from-literal=mysql-host=external-mysql.example.com \
|
||||
--from-literal=mysql-port=3306 \
|
||||
--from-literal=mysql-user=ljwx_user \
|
||||
--from-literal=mysql-password=password \
|
||||
--from-literal=mysql-database=ljwx \
|
||||
--from-literal=redis-host=external-redis.example.com \
|
||||
--from-literal=redis-port=6379 \
|
||||
--from-literal=redis-password=redis_password \
|
||||
-n ljwx-system
|
||||
```
|
||||
|
||||
## 访问应用
|
||||
|
||||
### 1. 配置本地域名(开发环境)
|
||||
|
||||
```bash
|
||||
# 获取 Ingress IP
|
||||
kubectl get nodes -o wide
|
||||
|
||||
# 编辑 /etc/hosts
|
||||
sudo nano /etc/hosts
|
||||
|
||||
# 添加以下行(替换为实际 IP)
|
||||
192.168.65.4 ljwx.local
|
||||
```
|
||||
|
||||
### 2. 访问地址
|
||||
|
||||
- **管理后台**: http://ljwx.local
|
||||
- **后端 API**: http://ljwx.local/api
|
||||
- **数据大屏**: http://ljwx.local/bigscreen
|
||||
|
||||
### 3. 使用端口转发(临时访问)
|
||||
|
||||
```bash
|
||||
# 转发前端
|
||||
kubectl port-forward svc/ljwx-admin 8080:80 -n ljwx-system
|
||||
# 访问: http://localhost:8080
|
||||
|
||||
# 转发后端 API
|
||||
kubectl port-forward svc/ljwx-boot 9998:9998 -n ljwx-system
|
||||
# 访问: http://localhost:9998
|
||||
|
||||
# 转发大屏
|
||||
kubectl port-forward svc/ljwx-bigscreen 5001:5001 -n ljwx-system
|
||||
# 访问: http://localhost:5001
|
||||
```
|
||||
|
||||
## 运维管理
|
||||
|
||||
### 查看状态
|
||||
|
||||
```bash
|
||||
# 完整状态检查
|
||||
./k8s-status.sh
|
||||
|
||||
# 查看 Pods
|
||||
kubectl get pods -n ljwx-system -o wide
|
||||
|
||||
# 查看 Events
|
||||
kubectl get events -n ljwx-system --sort-by='.lastTimestamp'
|
||||
|
||||
# 查看资源使用
|
||||
kubectl top pods -n ljwx-system
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# 查看 Boot 后端日志
|
||||
kubectl logs -f deployment/ljwx-boot -n ljwx-system
|
||||
|
||||
# 查看 Bigscreen 日志
|
||||
kubectl logs -f deployment/ljwx-bigscreen -n ljwx-system
|
||||
|
||||
# 查看 MySQL 日志
|
||||
kubectl logs -f statefulset/ljwx-mysql -n ljwx-system
|
||||
|
||||
# 查看所有容器日志
|
||||
kubectl logs -f <pod-name> --all-containers -n ljwx-system
|
||||
```
|
||||
|
||||
### 扩缩容
|
||||
|
||||
```bash
|
||||
# 扩展 Boot 后端到 3 个副本
|
||||
kubectl scale deployment ljwx-boot --replicas=3 -n ljwx-system
|
||||
|
||||
# 扩展 Admin 前端到 3 个副本
|
||||
kubectl scale deployment ljwx-admin --replicas=3 -n ljwx-system
|
||||
|
||||
# 查看扩缩容状态
|
||||
kubectl get deployments -n ljwx-system
|
||||
```
|
||||
|
||||
### 滚动更新
|
||||
|
||||
```bash
|
||||
# 更新镜像版本
|
||||
kubectl set image deployment/ljwx-boot \
|
||||
boot=localhost:15000/ljwx/ljwx-boot:2.0.4 \
|
||||
-n ljwx-system
|
||||
|
||||
# 查看更新状态
|
||||
kubectl rollout status deployment/ljwx-boot -n ljwx-system
|
||||
|
||||
# 回滚到上一个版本
|
||||
kubectl rollout undo deployment/ljwx-boot -n ljwx-system
|
||||
|
||||
# 查看更新历史
|
||||
kubectl rollout history deployment/ljwx-boot -n ljwx-system
|
||||
```
|
||||
|
||||
### 重启服务
|
||||
|
||||
```bash
|
||||
# 重启 Boot 服务
|
||||
kubectl rollout restart deployment/ljwx-boot -n ljwx-system
|
||||
|
||||
# 重启 Bigscreen 服务
|
||||
kubectl rollout restart deployment/ljwx-bigscreen -n ljwx-system
|
||||
|
||||
# 重启 MySQL(慎用,会导致短暂服务中断)
|
||||
kubectl rollout restart statefulset/ljwx-mysql -n ljwx-system
|
||||
```
|
||||
|
||||
### 进入容器调试
|
||||
|
||||
```bash
|
||||
# 进入 Boot 容器
|
||||
kubectl exec -it deployment/ljwx-boot -n ljwx-system -- /bin/sh
|
||||
|
||||
# 进入 MySQL 容器
|
||||
kubectl exec -it statefulset/ljwx-mysql -n ljwx-system -- /bin/bash
|
||||
|
||||
# 在容器中执行命令
|
||||
kubectl exec deployment/ljwx-boot -n ljwx-system -- ps aux
|
||||
```
|
||||
|
||||
## 卸载
|
||||
|
||||
### 完全卸载(包括数据)
|
||||
|
||||
```bash
|
||||
# 删除所有资源和数据
|
||||
DELETE_PVC=true ./k8s-undeploy.sh
|
||||
```
|
||||
|
||||
### 保留数据卸载
|
||||
|
||||
```bash
|
||||
# 删除应用但保留数据(PVC)
|
||||
./k8s-undeploy.sh
|
||||
```
|
||||
|
||||
### 手动删除
|
||||
|
||||
```bash
|
||||
# 删除命名空间(会删除所有资源)
|
||||
kubectl delete namespace ljwx-system
|
||||
|
||||
# 仅删除特定资源
|
||||
kubectl delete deployment ljwx-boot -n ljwx-system
|
||||
kubectl delete svc ljwx-boot -n ljwx-system
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 1. Pod 无法启动
|
||||
|
||||
```bash
|
||||
# 查看 Pod 状态
|
||||
kubectl get pods -n ljwx-system
|
||||
|
||||
# 查看 Pod 详细信息
|
||||
kubectl describe pod <pod-name> -n ljwx-system
|
||||
|
||||
# 查看 Pod 日志
|
||||
kubectl logs <pod-name> -n ljwx-system
|
||||
|
||||
# 查看 Events
|
||||
kubectl get events -n ljwx-system | grep <pod-name>
|
||||
```
|
||||
|
||||
**常见问题**:
|
||||
- `ImagePullBackOff`: 镜像拉取失败,检查镜像名称和 Registry
|
||||
- `CrashLoopBackOff`: 容器启动失败,查看日志
|
||||
- `Pending`: 资源不足或 PVC 无法绑定
|
||||
|
||||
### 2. 镜像拉取失败
|
||||
|
||||
```bash
|
||||
# 检查镜像是否存在
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
|
||||
# 查看镜像详细信息
|
||||
curl http://localhost:15000/v2/ljwx/ljwx-boot/tags/list
|
||||
|
||||
# 重新构建和推送镜像
|
||||
./build-and-push.sh all
|
||||
```
|
||||
|
||||
### 3. 服务无法访问
|
||||
|
||||
```bash
|
||||
# 检查 Service
|
||||
kubectl get svc -n ljwx-system
|
||||
|
||||
# 检查 Endpoints
|
||||
kubectl get endpoints -n ljwx-system
|
||||
|
||||
# 检查 Ingress
|
||||
kubectl get ingress -n ljwx-system
|
||||
kubectl describe ingress ljwx-ingress -n ljwx-system
|
||||
|
||||
# 测试 Service 内部连接
|
||||
kubectl run test-pod --image=busybox -it --rm -n ljwx-system -- sh
|
||||
# 在容器内: wget -O- http://ljwx-boot:9998/actuator/health
|
||||
```
|
||||
|
||||
### 4. 数据库连接失败
|
||||
|
||||
```bash
|
||||
# 检查 MySQL Pod
|
||||
kubectl get pods -l app=ljwx-mysql -n ljwx-system
|
||||
|
||||
# 检查 MySQL 日志
|
||||
kubectl logs -f statefulset/ljwx-mysql -n ljwx-system
|
||||
|
||||
# 进入 MySQL 容器测试
|
||||
kubectl exec -it statefulset/ljwx-mysql -n ljwx-system -- mysql -u root -p
|
||||
|
||||
# 检查 ConfigMap 和 Secret
|
||||
kubectl get configmap ljwx-config -n ljwx-system -o yaml
|
||||
kubectl get secret ljwx-secret -n ljwx-system -o yaml
|
||||
```
|
||||
|
||||
### 5. 性能问题
|
||||
|
||||
```bash
|
||||
# 查看资源使用
|
||||
kubectl top pods -n ljwx-system
|
||||
kubectl top nodes
|
||||
|
||||
# 查看 Pod 限制
|
||||
kubectl describe pod <pod-name> -n ljwx-system | grep -A 5 "Limits"
|
||||
|
||||
# 调整资源限制(编辑 Deployment)
|
||||
kubectl edit deployment ljwx-boot -n ljwx-system
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 资源配置
|
||||
|
||||
根据环境调整资源限制:
|
||||
|
||||
```yaml
|
||||
# 开发环境(最小资源)
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# 生产环境(推荐配置)
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "2Gi"
|
||||
cpu: "1000m"
|
||||
```
|
||||
|
||||
### 2. 副本数量
|
||||
|
||||
```bash
|
||||
# 开发环境
|
||||
Boot: 1 副本
|
||||
Bigscreen: 1 副本
|
||||
Admin: 1 副本
|
||||
|
||||
# 生产环境
|
||||
Boot: 2-3 副本
|
||||
Bigscreen: 2-3 副本
|
||||
Admin: 2 副本
|
||||
MySQL: 1 副本(使用 StatefulSet)
|
||||
Redis: 1 副本(或使用 Redis Cluster)
|
||||
```
|
||||
|
||||
### 3. 持久化存储
|
||||
|
||||
```bash
|
||||
# 检查存储类
|
||||
kubectl get storageclass
|
||||
|
||||
# 为生产环境使用合适的 StorageClass
|
||||
# 编辑 k8s-deploy.sh 中的 volumeClaimTemplates
|
||||
storageClassName: "fast-ssd" # 根据集群实际情况
|
||||
```
|
||||
|
||||
### 4. 监控和日志
|
||||
|
||||
```bash
|
||||
# 启用 Prometheus 监控
|
||||
# Bigscreen 已配置 Prometheus 注解
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "5001"
|
||||
prometheus.io/path: "/metrics"
|
||||
|
||||
# 集中式日志收集
|
||||
# 使用 EFK/ELK 或 Loki Stack
|
||||
```
|
||||
|
||||
### 5. 健康检查
|
||||
|
||||
所有服务已配置:
|
||||
- `livenessProbe`: 存活检查(失败会重启 Pod)
|
||||
- `readinessProbe`: 就绪检查(失败不接收流量)
|
||||
- `startupProbe`: 启动检查(给应用足够启动时间)
|
||||
|
||||
### 6. 安全配置
|
||||
|
||||
```bash
|
||||
# 使用强密码
|
||||
MYSQL_ROOT_PASSWORD=$(openssl rand -base64 32)
|
||||
REDIS_PASSWORD=$(openssl rand -base64 32)
|
||||
|
||||
# 限制网络访问(NetworkPolicy)
|
||||
# 配置 RBAC 权限
|
||||
# 使用 Secrets 管理敏感信息
|
||||
# 定期更新镜像和依赖
|
||||
```
|
||||
|
||||
### 7. 备份策略
|
||||
|
||||
```bash
|
||||
# MySQL 数据备份
|
||||
kubectl exec statefulset/ljwx-mysql -n ljwx-system -- \
|
||||
mysqldump -u root -p$MYSQL_ROOT_PASSWORD --all-databases > backup.sql
|
||||
|
||||
# PVC 快照(如果存储支持)
|
||||
kubectl get pvc -n ljwx-system
|
||||
# 使用 VolumeSnapshot CRD
|
||||
```
|
||||
|
||||
## 生产环境部署
|
||||
|
||||
### 1. 使用 Helm(推荐)
|
||||
|
||||
```bash
|
||||
# TODO: 创建 Helm Chart
|
||||
helm install ljwx ./ljwx-chart \
|
||||
--namespace ljwx-prod \
|
||||
--create-namespace \
|
||||
--values values-prod.yaml
|
||||
```
|
||||
|
||||
### 2. GitOps(ArgoCD/Flux)
|
||||
|
||||
```bash
|
||||
# 将 K8s manifests 提交到 Git
|
||||
# 配置 ArgoCD 自动同步
|
||||
argocd app create ljwx \
|
||||
--repo https://github.com/your-org/ljwx-k8s \
|
||||
--path k8s \
|
||||
--dest-namespace ljwx-prod \
|
||||
--dest-server https://kubernetes.default.svc
|
||||
```
|
||||
|
||||
### 3. CI/CD 集成
|
||||
|
||||
```yaml
|
||||
# GitHub Actions 示例
|
||||
name: Deploy to K8s
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Deploy
|
||||
run: ./k8s-deploy.sh
|
||||
env:
|
||||
KUBECONFIG: ${{ secrets.KUBECONFIG }}
|
||||
```
|
||||
|
||||
## 常见问题 FAQ
|
||||
|
||||
### Q: 如何更新应用版本?
|
||||
|
||||
```bash
|
||||
# 1. 更新版本号
|
||||
vi monitoring-versions.env
|
||||
|
||||
# 2. 重新构建镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# 3. 重新部署
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### Q: 如何迁移数据?
|
||||
|
||||
```bash
|
||||
# 导出数据
|
||||
kubectl exec statefulset/ljwx-mysql -n ljwx-system -- \
|
||||
mysqldump -u root -p ljwx > ljwx-backup.sql
|
||||
|
||||
# 导入数据
|
||||
kubectl exec -i statefulset/ljwx-mysql -n ljwx-system -- \
|
||||
mysql -u root -p ljwx < ljwx-backup.sql
|
||||
```
|
||||
|
||||
### Q: 如何配置 HTTPS?
|
||||
|
||||
```bash
|
||||
# 1. 安装 cert-manager
|
||||
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
|
||||
|
||||
# 2. 配置 Let's Encrypt Issuer
|
||||
# 3. 更新 Ingress 添加 TLS 配置
|
||||
# 详见 cert-manager 文档
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [构建脚本使用说明](./build-and-push.sh) - 运行不带参数查看帮助
|
||||
- [本地 Registry 配置](./REGISTRY-CACHE-SETUP.md)
|
||||
- [监控版本配置](./monitoring-versions.env)
|
||||
|
||||
## 技术支持
|
||||
|
||||
遇到问题?
|
||||
|
||||
1. 运行状态检查: `./k8s-status.sh`
|
||||
2. 查看日志: `kubectl logs -f <pod-name> -n ljwx-system`
|
||||
3. 查看事件: `kubectl get events -n ljwx-system`
|
||||
4. 检查配置: `kubectl describe <resource> <name> -n ljwx-system`
|
||||
|
||||
---
|
||||
|
||||
**版本**: v1.0.0
|
||||
**更新时间**: 2025-11-26
|
||||
**适用环境**: Kubernetes 1.19+
|
||||
@@ -1,225 +0,0 @@
|
||||
# Kubernetes 一键部署 - 快速开始
|
||||
|
||||
快速将灵境万象系统部署到 Kubernetes 集群。
|
||||
|
||||
## 🚀 5 分钟快速部署
|
||||
|
||||
### 前提条件
|
||||
|
||||
1. **Kubernetes 集群** 已经运行
|
||||
```bash
|
||||
kubectl cluster-info
|
||||
```
|
||||
|
||||
2. **本地 Registry** 已经启动
|
||||
```bash
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
```
|
||||
|
||||
### 一键部署
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
cd /Users/brunogao/work/codes/shenye/release
|
||||
|
||||
# 执行一键部署
|
||||
./k8s-deploy.sh
|
||||
```
|
||||
|
||||
完成!系统将自动:
|
||||
- ✅ 构建所有 Docker 镜像
|
||||
- ✅ 推送到本地 Registry
|
||||
- ✅ 生成 K8s 配置文件
|
||||
- ✅ 部署到 Kubernetes
|
||||
- ✅ 等待服务就绪
|
||||
|
||||
## 📋 部署脚本
|
||||
|
||||
| 脚本 | 功能 | 用法 |
|
||||
|------|------|------|
|
||||
| `k8s-deploy.sh` | 一键部署 | `./k8s-deploy.sh` |
|
||||
| `k8s-status.sh` | 状态检查 | `./k8s-status.sh` |
|
||||
| `k8s-undeploy.sh` | 卸载系统 | `./k8s-undeploy.sh` |
|
||||
|
||||
## 🔍 访问应用
|
||||
|
||||
### 方式 1: 配置本地域名
|
||||
|
||||
```bash
|
||||
# 1. 获取节点 IP
|
||||
kubectl get nodes -o wide
|
||||
|
||||
# 2. 编辑 /etc/hosts
|
||||
sudo nano /etc/hosts
|
||||
|
||||
# 3. 添加域名映射
|
||||
192.168.65.4 ljwx.local
|
||||
|
||||
# 4. 访问应用
|
||||
open http://ljwx.local
|
||||
```
|
||||
|
||||
### 方式 2: 端口转发
|
||||
|
||||
```bash
|
||||
# 转发前端管理
|
||||
kubectl port-forward svc/ljwx-admin 8080:80 -n ljwx-system
|
||||
|
||||
# 访问
|
||||
open http://localhost:8080
|
||||
```
|
||||
|
||||
## 📊 查看状态
|
||||
|
||||
```bash
|
||||
# 完整状态检查
|
||||
./k8s-status.sh
|
||||
|
||||
# 查看 Pods
|
||||
kubectl get pods -n ljwx-system
|
||||
|
||||
# 查看日志
|
||||
kubectl logs -f deployment/ljwx-boot -n ljwx-system
|
||||
```
|
||||
|
||||
## 🛠️ 常用命令
|
||||
|
||||
### 扩容
|
||||
|
||||
```bash
|
||||
# 扩展到 3 个副本
|
||||
kubectl scale deployment ljwx-boot --replicas=3 -n ljwx-system
|
||||
```
|
||||
|
||||
### 重启
|
||||
|
||||
```bash
|
||||
# 重启服务
|
||||
kubectl rollout restart deployment/ljwx-boot -n ljwx-system
|
||||
```
|
||||
|
||||
### 更新
|
||||
|
||||
```bash
|
||||
# 1. 重新构建镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# 2. 重新部署
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### 卸载
|
||||
|
||||
```bash
|
||||
# 完全删除(包括数据)
|
||||
DELETE_PVC=true ./k8s-undeploy.sh
|
||||
|
||||
# 保留数据
|
||||
./k8s-undeploy.sh
|
||||
```
|
||||
|
||||
## 🎯 高级选项
|
||||
|
||||
### 使用已有镜像
|
||||
|
||||
```bash
|
||||
# 跳过镜像构建
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### 使用外部数据库
|
||||
|
||||
```bash
|
||||
# 跳过 MySQL 和 Redis 部署
|
||||
./k8s-deploy.sh --skip-mysql --skip-redis
|
||||
```
|
||||
|
||||
### 自定义配置
|
||||
|
||||
```bash
|
||||
# 自定义命名空间和域名
|
||||
K8S_NAMESPACE=ljwx-prod \
|
||||
LJWX_DOMAIN=ljwx.example.com \
|
||||
./k8s-deploy.sh
|
||||
```
|
||||
|
||||
### 查看帮助
|
||||
|
||||
```bash
|
||||
./k8s-deploy.sh --help
|
||||
```
|
||||
|
||||
## 🐛 故障排查
|
||||
|
||||
### Pod 无法启动
|
||||
|
||||
```bash
|
||||
# 查看 Pod 状态
|
||||
kubectl get pods -n ljwx-system
|
||||
|
||||
# 查看详细信息
|
||||
kubectl describe pod <pod-name> -n ljwx-system
|
||||
|
||||
# 查看日志
|
||||
kubectl logs <pod-name> -n ljwx-system
|
||||
```
|
||||
|
||||
### 镜像拉取失败
|
||||
|
||||
```bash
|
||||
# 检查本地 Registry
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
|
||||
# 重新构建镜像
|
||||
./build-and-push.sh all
|
||||
```
|
||||
|
||||
### 服务无法访问
|
||||
|
||||
```bash
|
||||
# 检查 Ingress
|
||||
kubectl get ingress -n ljwx-system
|
||||
|
||||
# 检查 Service
|
||||
kubectl get svc -n ljwx-system
|
||||
|
||||
# 使用端口转发测试
|
||||
kubectl port-forward svc/ljwx-admin 8080:80 -n ljwx-system
|
||||
```
|
||||
|
||||
## 📚 完整文档
|
||||
|
||||
详细文档请参考: [K8S-DEPLOYMENT-GUIDE.md](./K8S-DEPLOYMENT-GUIDE.md)
|
||||
|
||||
内容包括:
|
||||
- 🏗️ 系统架构详解
|
||||
- ⚙️ 详细配置说明
|
||||
- 🔧 运维管理指南
|
||||
- 🐞 完整故障排查
|
||||
- ✨ 最佳实践建议
|
||||
- 🚀 生产环境部署
|
||||
|
||||
## 💡 提示
|
||||
|
||||
1. **首次部署**较慢(需要构建镜像),后续部署会很快
|
||||
2. **确保 Registry 运行**,否则无法推送镜像
|
||||
3. **检查集群资源**,确保有足够的 CPU 和内存
|
||||
4. **使用 `./k8s-status.sh`** 随时查看系统状态
|
||||
|
||||
## 🎉 成功指标
|
||||
|
||||
部署成功后,您应该看到:
|
||||
|
||||
```
|
||||
✅ 所有 Pods 运行正常
|
||||
✅ 所有 Services 可访问
|
||||
✅ Ingress 配置正确
|
||||
✅ 应用可以通过域名访问
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**快速支持**:
|
||||
- 状态检查: `./k8s-status.sh`
|
||||
- 查看日志: `kubectl logs -f <pod> -n ljwx-system`
|
||||
- 完整文档: `K8S-DEPLOYMENT-GUIDE.md`
|
||||
-432
@@ -1,432 +0,0 @@
|
||||
# Kubernetes 一键部署工具集
|
||||
|
||||
灵境万象系统的 Kubernetes 完整部署解决方案。
|
||||
|
||||
## 📦 文件清单
|
||||
|
||||
### 核心脚本
|
||||
|
||||
| 文件 | 大小 | 功能说明 |
|
||||
|------|------|----------|
|
||||
| `k8s-deploy.sh` | 27KB | 🚀 **一键部署脚本** - 完整的自动化部署流程 |
|
||||
| `k8s-status.sh` | 5KB | 📊 **状态检查脚本** - 全面的系统状态监控 |
|
||||
| `k8s-undeploy.sh` | 2.4KB | 🗑️ **卸载脚本** - 安全地卸载系统 |
|
||||
|
||||
### 文档
|
||||
|
||||
| 文件 | 内容 |
|
||||
|------|------|
|
||||
| `K8S-QUICK-START.md` | ⚡ 快速开始指南 - 5分钟完成部署 |
|
||||
| `K8S-DEPLOYMENT-GUIDE.md` | 📚 完整部署文档 - 详细的配置和运维指南 |
|
||||
| `K8S-README.md` | 📝 本文件 - 工具集概览 |
|
||||
|
||||
### 生成的配置
|
||||
|
||||
部署时会在 `./k8s/` 目录自动生成:
|
||||
|
||||
```
|
||||
k8s/
|
||||
├── namespace/ # Namespace 配置
|
||||
├── configmap/ # ConfigMap 配置
|
||||
├── secret/ # Secret 配置(敏感信息)
|
||||
├── mysql/ # MySQL StatefulSet
|
||||
├── redis/ # Redis Deployment
|
||||
├── boot/ # Spring Boot 后端
|
||||
├── bigscreen/ # FastAPI 大屏
|
||||
├── admin/ # Vue 前端
|
||||
└── ingress/ # Ingress 路由
|
||||
```
|
||||
|
||||
## 🎯 核心功能
|
||||
|
||||
### k8s-deploy.sh - 一键部署
|
||||
|
||||
**自动化流程**:
|
||||
1. ✅ 检查前置条件(kubectl, docker, registry)
|
||||
2. ✅ 生成完整的 K8s manifests
|
||||
3. ✅ 构建所有 Docker 镜像
|
||||
4. ✅ 推送镜像到本地 Registry
|
||||
5. ✅ 部署 ConfigMap 和 Secret
|
||||
6. ✅ 部署 MySQL StatefulSet(可选)
|
||||
7. ✅ 部署 Redis(可选)
|
||||
8. ✅ 部署应用服务(Boot, Bigscreen, Admin)
|
||||
9. ✅ 配置 Ingress 路由
|
||||
10. ✅ 等待服务就绪
|
||||
11. ✅ 验证部署状态
|
||||
12. ✅ 显示访问信息
|
||||
|
||||
**特点**:
|
||||
- 🔄 幂等性:可重复执行,不会重复创建资源
|
||||
- 🎛️ 灵活性:支持跳过任意步骤
|
||||
- 🔒 安全性:使用 Secret 管理敏感信息
|
||||
- 📊 可观测:实时显示部署进度
|
||||
- ⚡ 高效性:并行部署,快速完成
|
||||
|
||||
### k8s-status.sh - 状态监控
|
||||
|
||||
**检查项目**:
|
||||
- 📦 Pods 状态和健康度
|
||||
- 🌐 Services 和 Endpoints
|
||||
- 🚀 Deployments 和 StatefulSets
|
||||
- 💾 PersistentVolumeClaims
|
||||
- 🔀 Ingress 路由配置
|
||||
- 📝 最近事件日志
|
||||
- 📊 资源使用情况
|
||||
- ⚠️ 不健康 Pods 列表
|
||||
- 🔄 重启次数统计
|
||||
|
||||
### k8s-undeploy.sh - 安全卸载
|
||||
|
||||
**两种模式**:
|
||||
1. **保留数据模式**(默认)
|
||||
- 删除所有应用和服务
|
||||
- 保留 PVC(持久化数据)
|
||||
- 下次部署可复用数据
|
||||
|
||||
2. **完全删除模式**
|
||||
```bash
|
||||
DELETE_PVC=true ./k8s-undeploy.sh
|
||||
```
|
||||
- 删除所有资源
|
||||
- 删除持久化数据
|
||||
- 完全清理环境
|
||||
|
||||
## 🚀 快速使用
|
||||
|
||||
### 1. 完整部署(新环境)
|
||||
|
||||
```bash
|
||||
./k8s-deploy.sh
|
||||
```
|
||||
|
||||
### 2. 更新已有部署
|
||||
|
||||
```bash
|
||||
# 构建新镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# 重新部署(跳过镜像构建)
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### 3. 查看系统状态
|
||||
|
||||
```bash
|
||||
./k8s-status.sh
|
||||
```
|
||||
|
||||
### 4. 卸载系统
|
||||
|
||||
```bash
|
||||
# 保留数据
|
||||
./k8s-undeploy.sh
|
||||
|
||||
# 完全删除
|
||||
DELETE_PVC=true ./k8s-undeploy.sh
|
||||
```
|
||||
|
||||
## 🎛️ 配置选项
|
||||
|
||||
### 环境变量
|
||||
|
||||
```bash
|
||||
# 基础配置
|
||||
K8S_NAMESPACE=ljwx-system # K8s 命名空间
|
||||
PRIVATE_REGISTRY=localhost:15000 # 镜像仓库地址
|
||||
LJWX_DOMAIN=ljwx.local # 访问域名
|
||||
|
||||
# 构建控制
|
||||
BUILD_IMAGES=true # 是否构建镜像
|
||||
PUSH_IMAGES=true # 是否推送镜像
|
||||
|
||||
# 部署控制
|
||||
DEPLOY_MYSQL=true # 是否部署 MySQL
|
||||
DEPLOY_REDIS=true # 是否部署 Redis
|
||||
DEPLOY_APPS=true # 是否部署应用
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_PASSWORD=123456 # MySQL 密码
|
||||
MYSQL_DATABASE=lj-06 # 数据库名称
|
||||
REDIS_PASSWORD=123456 # Redis 密码
|
||||
```
|
||||
|
||||
### 命令行选项
|
||||
|
||||
```bash
|
||||
# 跳过镜像构建
|
||||
./k8s-deploy.sh --skip-build
|
||||
|
||||
# 跳过数据库部署
|
||||
./k8s-deploy.sh --skip-mysql --skip-redis
|
||||
|
||||
# 自定义配置
|
||||
./k8s-deploy.sh \
|
||||
--namespace ljwx-prod \
|
||||
--registry registry.example.com:5000 \
|
||||
--domain ljwx.example.com
|
||||
```
|
||||
|
||||
## 📊 系统架构
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ Ingress Controller │
|
||||
│ (nginx/traefik) │
|
||||
└──────────────┬─────────────────────────────┘
|
||||
│
|
||||
┌─────────┴─────────┐
|
||||
│ │
|
||||
┌────▼──────┐ ┌──────▼────────┐
|
||||
│ Admin │ │ Bigscreen │
|
||||
│ (Vue) │ │ (FastAPI) │
|
||||
│ Port: 80 │ │ Port: 5001 │
|
||||
└───────────┘ └───────┬────────┘
|
||||
│
|
||||
┌─────────▼──────────┐
|
||||
│ Boot (Spring) │
|
||||
│ Port: 9998 │
|
||||
└──┬──────────────┬──┘
|
||||
│ │
|
||||
┌─────────▼──┐ ┌─────▼──────┐
|
||||
│ MySQL │ │ Redis │
|
||||
│ StatefulSet│ │ Deployment │
|
||||
└────────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## 🔍 使用场景
|
||||
|
||||
### 场景 1: 开发环境快速搭建
|
||||
|
||||
```bash
|
||||
# 单命令部署完整环境
|
||||
./k8s-deploy.sh
|
||||
```
|
||||
|
||||
### 场景 2: 生产环境部署
|
||||
|
||||
```bash
|
||||
# 使用外部数据库
|
||||
./k8s-deploy.sh \
|
||||
--skip-mysql \
|
||||
--skip-redis \
|
||||
--namespace ljwx-prod \
|
||||
--domain ljwx.company.com
|
||||
|
||||
# 然后配置外部数据库连接
|
||||
kubectl create secret generic ljwx-secret \
|
||||
--from-literal=mysql-host=prod-mysql.company.com \
|
||||
-n ljwx-prod
|
||||
```
|
||||
|
||||
### 场景 3: 测试环境部署
|
||||
|
||||
```bash
|
||||
# 使用已有镜像快速部署
|
||||
./k8s-deploy.sh \
|
||||
--skip-build \
|
||||
--namespace ljwx-test
|
||||
```
|
||||
|
||||
### 场景 4: 本地开发联调
|
||||
|
||||
```bash
|
||||
# 部署基础设施
|
||||
./k8s-deploy.sh --skip-build
|
||||
|
||||
# 使用 port-forward 访问
|
||||
kubectl port-forward svc/ljwx-boot 9998:9998 -n ljwx-system
|
||||
kubectl port-forward svc/ljwx-mysql 3306:3306 -n ljwx-system
|
||||
```
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### 快速诊断
|
||||
|
||||
```bash
|
||||
# 1. 运行状态检查
|
||||
./k8s-status.sh
|
||||
|
||||
# 2. 查看问题 Pod
|
||||
kubectl get pods -n ljwx-system | grep -v Running
|
||||
|
||||
# 3. 查看 Pod 详情
|
||||
kubectl describe pod <pod-name> -n ljwx-system
|
||||
|
||||
# 4. 查看日志
|
||||
kubectl logs -f <pod-name> -n ljwx-system
|
||||
```
|
||||
|
||||
### 常见问题
|
||||
|
||||
| 问题 | 解决方法 |
|
||||
|------|----------|
|
||||
| 镜像拉取失败 | 检查本地 Registry: `curl http://localhost:15000/v2/_catalog` |
|
||||
| Pod 启动失败 | 查看日志: `kubectl logs <pod> -n ljwx-system` |
|
||||
| 服务无法访问 | 检查 Service: `kubectl get svc -n ljwx-system` |
|
||||
| 数据库连接失败 | 检查 Secret: `kubectl get secret ljwx-secret -n ljwx-system -o yaml` |
|
||||
| 资源不足 | 调整 requests/limits 或增加节点 |
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
### 入门文档
|
||||
- [K8S-QUICK-START.md](./K8S-QUICK-START.md) - **⚡ 从这里开始**
|
||||
- 5 分钟快速部署
|
||||
- 基础使用方法
|
||||
- 常见问题解答
|
||||
|
||||
### 详细文档
|
||||
- [K8S-DEPLOYMENT-GUIDE.md](./K8S-DEPLOYMENT-GUIDE.md) - **📚 完整参考**
|
||||
- 系统架构详解
|
||||
- 详细配置说明
|
||||
- 运维管理指南
|
||||
- 完整故障排查
|
||||
- 最佳实践建议
|
||||
- 生产环境部署
|
||||
|
||||
### 相关工具
|
||||
- [build-and-push.sh](./build-and-push.sh) - Docker 镜像构建脚本
|
||||
- [REGISTRY-CACHE-SETUP.md](./REGISTRY-CACHE-SETUP.md) - 本地 Registry 配置
|
||||
- [monitoring-versions.env](./monitoring-versions.env) - 版本配置文件
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
### 1. 版本管理
|
||||
|
||||
```bash
|
||||
# 修改版本号
|
||||
vi monitoring-versions.env
|
||||
|
||||
# 构建新版本
|
||||
./build-and-push.sh all
|
||||
|
||||
# 部署新版本
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### 2. 环境隔离
|
||||
|
||||
```bash
|
||||
# 开发环境
|
||||
K8S_NAMESPACE=ljwx-dev ./k8s-deploy.sh
|
||||
|
||||
# 测试环境
|
||||
K8S_NAMESPACE=ljwx-test ./k8s-deploy.sh
|
||||
|
||||
# 生产环境
|
||||
K8S_NAMESPACE=ljwx-prod ./k8s-deploy.sh
|
||||
```
|
||||
|
||||
### 3. 资源优化
|
||||
|
||||
```bash
|
||||
# 开发环境:最小资源
|
||||
DEPLOY_MYSQL=true DEPLOY_REDIS=true ./k8s-deploy.sh
|
||||
|
||||
# 生产环境:使用外部数据库
|
||||
./k8s-deploy.sh --skip-mysql --skip-redis
|
||||
```
|
||||
|
||||
### 4. 监控和日志
|
||||
|
||||
```bash
|
||||
# 查看实时日志
|
||||
kubectl logs -f deployment/ljwx-boot -n ljwx-system
|
||||
|
||||
# 查看资源使用
|
||||
kubectl top pods -n ljwx-system
|
||||
|
||||
# 查看事件
|
||||
kubectl get events -n ljwx-system --sort-by='.lastTimestamp'
|
||||
```
|
||||
|
||||
## 🔄 更新和维护
|
||||
|
||||
### 日常维护
|
||||
|
||||
```bash
|
||||
# 每日检查
|
||||
./k8s-status.sh
|
||||
|
||||
# 重启服务(无停机)
|
||||
kubectl rollout restart deployment/ljwx-boot -n ljwx-system
|
||||
|
||||
# 扩缩容
|
||||
kubectl scale deployment/ljwx-boot --replicas=3 -n ljwx-system
|
||||
```
|
||||
|
||||
### 版本更新
|
||||
|
||||
```bash
|
||||
# 1. 更新代码
|
||||
git pull
|
||||
|
||||
# 2. 修改版本号
|
||||
vi monitoring-versions.env
|
||||
|
||||
# 3. 构建新镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# 4. 滚动更新
|
||||
./k8s-deploy.sh --skip-build
|
||||
```
|
||||
|
||||
### 数据备份
|
||||
|
||||
```bash
|
||||
# 备份 MySQL
|
||||
kubectl exec statefulset/ljwx-mysql -n ljwx-system -- \
|
||||
mysqldump -u root -p ljwx > backup-$(date +%Y%m%d).sql
|
||||
|
||||
# 备份 PVC(使用 Velero 等工具)
|
||||
velero backup create ljwx-backup --include-namespaces=ljwx-system
|
||||
```
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
### 快速支持
|
||||
|
||||
1. **状态检查**: `./k8s-status.sh`
|
||||
2. **查看日志**: `kubectl logs -f <pod> -n ljwx-system`
|
||||
3. **查看事件**: `kubectl get events -n ljwx-system`
|
||||
|
||||
### 详细诊断
|
||||
|
||||
```bash
|
||||
# 1. 收集信息
|
||||
./k8s-status.sh > status.log
|
||||
kubectl get all -n ljwx-system -o yaml > resources.yaml
|
||||
kubectl describe pod <pod> -n ljwx-system > pod-details.log
|
||||
|
||||
# 2. 查看日志
|
||||
kubectl logs <pod> -n ljwx-system --previous # 上次运行日志
|
||||
kubectl logs <pod> -n ljwx-system --all-containers # 所有容器日志
|
||||
|
||||
# 3. 进入容器调试
|
||||
kubectl exec -it <pod> -n ljwx-system -- /bin/sh
|
||||
```
|
||||
|
||||
## 🎉 成功案例
|
||||
|
||||
部署成功后,您将获得:
|
||||
|
||||
- ✅ **完整的微服务架构** - 前端、后端、大屏三个服务
|
||||
- ✅ **自动化运维** - 健康检查、自动重启、滚动更新
|
||||
- ✅ **弹性扩展** - 支持水平扩展和自动伸缩
|
||||
- ✅ **统一入口** - Ingress 路由管理
|
||||
- ✅ **数据持久化** - StatefulSet 和 PVC
|
||||
- ✅ **配置管理** - ConfigMap 和 Secret
|
||||
- ✅ **服务发现** - K8s Service 和 DNS
|
||||
- ✅ **监控就绪** - Prometheus 注解已配置
|
||||
|
||||
---
|
||||
|
||||
**版本**: v1.0.0
|
||||
**作者**: Claude Code
|
||||
**更新**: 2025-11-26
|
||||
**协议**: MIT License
|
||||
|
||||
**快速链接**:
|
||||
- 📖 [快速开始](./K8S-QUICK-START.md)
|
||||
- 📚 [完整文档](./K8S-DEPLOYMENT-GUIDE.md)
|
||||
- 🔧 [构建脚本](./build-and-push.sh)
|
||||
- 🐳 [Registry 配置](./REGISTRY-CACHE-SETUP.md)
|
||||
@@ -1,234 +0,0 @@
|
||||
# 🎉 LJWX Jenkins 完全自动化部署完成!
|
||||
|
||||
## ✅ 部署成功状态
|
||||
|
||||
### 核心服务
|
||||
- **Jenkins**: http://localhost:8081 (148个插件预装)
|
||||
- **Registry**: http://localhost:5001 (镜像仓库)
|
||||
- **初始密码**: `3a64e5b9c5064ec3ae86f16adee542bb`
|
||||
|
||||
### 自动化配置成果
|
||||
- ✅ **148个插件**自动安装完成
|
||||
- ✅ **Docker镜像**构建并推送到Registry成功
|
||||
- ✅ **完整持久化**配置,数据永不丢失
|
||||
- ✅ **多语言支持**准备就绪(Java, Vue3, Python)
|
||||
|
||||
## 🚀 立即开始使用
|
||||
|
||||
### 1. 登录Jenkins
|
||||
```bash
|
||||
# 访问地址
|
||||
http://localhost:8081
|
||||
|
||||
# 登录凭据
|
||||
初始密码: 3a64e5b9c5064ec3ae86f16adee542bb
|
||||
```
|
||||
|
||||
### 2. 完成初始设置
|
||||
1. 使用初始密码登录
|
||||
2. **跳过插件安装** (148个插件已预装)
|
||||
3. 创建管理员用户: `admin / admin123`
|
||||
4. 保存并完成设置
|
||||
|
||||
### 3. 关键功能已就绪
|
||||
- **Pipeline工作流**: 完整CI/CD支持
|
||||
- **Git集成**: 代码管理和Webhook
|
||||
- **Docker支持**: 容器构建和推送
|
||||
- **多语言工具**: Maven, Gradle, NodeJS
|
||||
- **代码质量**: JUnit, 静态分析
|
||||
- **现代UI**: BlueOcean界面
|
||||
|
||||
## 📋 CI/CD Pipeline配置
|
||||
|
||||
### Java SpringBoot项目
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps { git url: 'http://gitea:3000/user/java-project.git' }
|
||||
}
|
||||
stage('Build') {
|
||||
steps { sh 'mvn clean package' }
|
||||
}
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
sh '''
|
||||
docker build -t localhost:5001/java-app:${BUILD_NUMBER} .
|
||||
docker push localhost:5001/java-app:${BUILD_NUMBER}
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('Deploy') {
|
||||
steps {
|
||||
sh 'kubectl set image deployment/java-app java-app=localhost:5001/java-app:${BUILD_NUMBER}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Vue3前端项目
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps { git url: 'http://gitea:3000/user/vue3-project.git' }
|
||||
}
|
||||
stage('Install & Build') {
|
||||
steps {
|
||||
sh 'npm install'
|
||||
sh 'npm run build'
|
||||
}
|
||||
}
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
sh '''
|
||||
docker build -t localhost:5001/vue3-app:${BUILD_NUMBER} .
|
||||
docker push localhost:5001/vue3-app:${BUILD_NUMBER}
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python FastAPI项目
|
||||
```groovy
|
||||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps { git url: 'http://gitea:3000/user/python-project.git' }
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'pip install -r requirements.txt'
|
||||
sh 'pytest'
|
||||
}
|
||||
}
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
sh '''
|
||||
docker build -t localhost:5001/python-app:${BUILD_NUMBER} .
|
||||
docker push localhost:5001/python-app:${BUILD_NUMBER}
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔗 Gitea Webhook配置
|
||||
|
||||
### 配置步骤
|
||||
1. 在Gitea项目中进入 **Settings → Webhooks**
|
||||
2. 添加Webhook URL:
|
||||
```
|
||||
http://localhost:8081/generic-webhook-trigger/invoke?token=YOUR-PROJECT-TOKEN
|
||||
```
|
||||
3. 选择触发事件: **Push events**
|
||||
4. 保存配置
|
||||
|
||||
### 触发流程
|
||||
```
|
||||
Git Push → Gitea Webhook → Jenkins Pipeline → Docker Build → Registry Push → K8s Deploy
|
||||
```
|
||||
|
||||
## 🛠️ 凭据管理配置
|
||||
|
||||
### 必要凭据
|
||||
在Jenkins中配置以下凭据:
|
||||
|
||||
#### 1. Gitea凭据
|
||||
- **类型**: Username with password
|
||||
- **ID**: `gitea-credentials`
|
||||
- **用户名**: Gitea用户名
|
||||
- **密码**: Gitea密码或Personal Access Token
|
||||
|
||||
#### 2. Docker Registry凭据
|
||||
- **类型**: Username with password
|
||||
- **ID**: `docker-registry-auth`
|
||||
- **用户名**: `admin`
|
||||
- **密码**: `admin123`
|
||||
|
||||
#### 3. Kubernetes凭据
|
||||
- **类型**: Secret text
|
||||
- **ID**: `k8s-config`
|
||||
- **内容**: Kubernetes配置文件内容
|
||||
|
||||
## 📦 镜像管理
|
||||
|
||||
### 查看Registry中的镜像
|
||||
```bash
|
||||
# 查看所有镜像
|
||||
curl http://localhost:5001/v2/_catalog
|
||||
|
||||
# 查看ljwx-jenkins镜像标签
|
||||
curl http://localhost:5001/v2/ljwx-jenkins/tags/list
|
||||
```
|
||||
|
||||
### 使用ljwx-jenkins镜像
|
||||
```bash
|
||||
# 拉取镜像
|
||||
docker pull localhost:5001/ljwx-jenkins:latest
|
||||
|
||||
# 运行镜像
|
||||
docker run -d -p 8082:8080 localhost:5001/ljwx-jenkins:latest
|
||||
```
|
||||
|
||||
## 🔧 日常管理
|
||||
|
||||
### 常用命令
|
||||
```bash
|
||||
# 查看容器状态
|
||||
docker ps | grep ljwx
|
||||
|
||||
# 查看Jenkins日志
|
||||
docker logs ljwx-jenkins -f
|
||||
|
||||
# 重启Jenkins
|
||||
docker restart ljwx-jenkins
|
||||
|
||||
# 备份Jenkins数据
|
||||
docker run --rm -v ljwx-jenkins-data:/data -v $(pwd):/backup alpine tar czf /backup/jenkins-backup-$(date +%Y%m%d).tar.gz -C /data .
|
||||
|
||||
# 停止所有服务
|
||||
cd docker/compose && docker-compose -f ljwx-jenkins-basic.yml down
|
||||
```
|
||||
|
||||
### 升级Jenkins
|
||||
```bash
|
||||
# 重新构建镜像
|
||||
cd docker/compose && docker-compose -f ljwx-jenkins-basic.yml build --no-cache ljwx-jenkins
|
||||
|
||||
# 重新部署
|
||||
docker-compose -f ljwx-jenkins-basic.yml up -d
|
||||
```
|
||||
|
||||
## 📈 性能配置
|
||||
|
||||
### 当前配置
|
||||
- **内存**: 2GB堆内存
|
||||
- **垃圾回收**: G1GC
|
||||
- **执行器**: 默认2个
|
||||
- **插件**: 148个核心插件
|
||||
|
||||
### 优化建议
|
||||
- 大型项目建议增加内存到4GB
|
||||
- 可以通过Kubernetes动态扩展Agent
|
||||
- 定期清理旧构建和工作空间
|
||||
|
||||
## ✨ 总结
|
||||
|
||||
LJWX Jenkins已经完全部署成功,具备:
|
||||
|
||||
- **🚀 开箱即用**: 148个插件预装,支持完整CI/CD流程
|
||||
- **🐳 容器化部署**: Docker化部署,易于迁移和扩展
|
||||
- **📦 镜像仓库**: 内置Registry,支持私有镜像管理
|
||||
- **🔄 多语言支持**: Java, Vue3, Python完整工具链
|
||||
- **🔐 安全配置**: 凭据管理,角色权限控制
|
||||
- **📊 现代界面**: BlueOcean提供现代化CI/CD体验
|
||||
|
||||
现在可以立即开始构建强大的CI/CD流水线,支撑现代化应用开发!🎊
|
||||
@@ -1,463 +0,0 @@
|
||||
# 🚀 LJWX多租户系统全面优化方案
|
||||
|
||||
## 📋 项目概述
|
||||
|
||||
基于对ljwx-admin前端、ljwx-boot后端Java服务、ljwx-bigscreen Python服务的全面分析,制定企业级多租户数据隔离与查询性能优化的完整实施方案。
|
||||
|
||||
### 🎯 优化目标
|
||||
- **数据隔离**: 实现严格的租户数据隔离,确保隐私和安全
|
||||
- **性能提升**: 多租户查询性能提升60-80%,支持百万级数据
|
||||
- **零侵入**: 保持现有API接口完全兼容,渐进式升级
|
||||
- **企业级**: 支持大规模多租户部署,稳定可靠
|
||||
|
||||
## 🏗️ 当前系统状态分析
|
||||
|
||||
### ✅ 已完成的多租户支持
|
||||
- **ljwx-admin前端**: 全局customerId自动注入系统
|
||||
- **基础表结构**: sys_user, sys_org_units, sys_user_org, sys_role, sys_position
|
||||
- **索引优化**: 17个多租户专用索引,支持高效查询
|
||||
- **租户上下文**: Python服务已具备tenant_context.py基础架构
|
||||
|
||||
### ⏳ 需要完成的核心任务
|
||||
- **数据库扩展**: 12个核心业务表添加customer_id字段
|
||||
- **Java后端改造**: 15+实体类, 50+DTO类, 20+服务方法, 15+控制器
|
||||
- **Python服务改造**: 8个核心模型, 20+服务函数, 30+API端点
|
||||
|
||||
## 🎯 完整实施方案
|
||||
|
||||
### 📊 Phase 1: 数据库架构完善 (2-3天)
|
||||
|
||||
#### 1.1 数据库表结构扩展
|
||||
|
||||
**优先级1 - 核心业务表** (必须完成):
|
||||
- `t_user_health_data` - 用户健康数据 (最高优先级)
|
||||
- `t_device_info` - 设备信息
|
||||
- `t_alert_info` - 告警信息 (重命名tenant_id→customer_id)
|
||||
- `t_device_user` - 设备用户绑定
|
||||
|
||||
**优先级2 - 扩展业务表** (推荐完成):
|
||||
- `t_device_message` + `t_device_message_detail` - 设备消息
|
||||
- `t_alert_action_log` - 告警处理日志
|
||||
- `t_device_bind_request` - 设备绑定申请
|
||||
|
||||
**优先级3 - 分析数据表** (可选完成):
|
||||
- `t_health_baseline` + `t_org_health_baseline` - 健康基线
|
||||
- `t_health_score` + `t_org_health_score` - 健康评分
|
||||
|
||||
#### 1.2 数据库迁移脚本
|
||||
|
||||
```sql
|
||||
-- 已生成完整迁移脚本: business-tables-customer-id-migration.sql
|
||||
-- 包含: 字段添加、数据迁移、索引创建、数据验证
|
||||
-- 执行时间预估: 30-60分钟
|
||||
```
|
||||
|
||||
#### 1.3 性能优化索引
|
||||
|
||||
**创建18个专用索引**:
|
||||
- 时序查询优化: customer_id + timestamp + device_sn
|
||||
- 租户隔离优化: customer_id + user_id + org_id
|
||||
- 状态查询优化: customer_id + status + is_deleted
|
||||
|
||||
### ⚙️ Phase 2: ljwx-boot Java后端改造 (4-5天)
|
||||
|
||||
#### 2.1 实体类改造 (1天)
|
||||
|
||||
**需要添加customer_id的实体类**:
|
||||
```java
|
||||
// 高优先级实体类
|
||||
- TUserHealthData.java // 健康数据
|
||||
- TDeviceInfo.java // 设备信息
|
||||
- TAlertInfo.java // 告警信息
|
||||
- TDeviceUser.java // 设备用户绑定
|
||||
|
||||
// 中优先级实体类
|
||||
- TDeviceMessage.java // 设备消息
|
||||
- TAlertActionLog.java // 告警日志
|
||||
- THealthBaseline.java // 健康基线
|
||||
- THealthScore.java // 健康评分
|
||||
|
||||
// 实体类标准模式
|
||||
@Schema(description = "租户ID")
|
||||
private Long customerId;
|
||||
```
|
||||
|
||||
#### 2.2 DTO类改造 (1天)
|
||||
|
||||
**需要添加customer_id的DTO类**:
|
||||
```java
|
||||
// SearchDTO类 (15+个)
|
||||
- TUserHealthDataSearchDTO
|
||||
- TDeviceInfoSearchDTO
|
||||
- TAlertInfoSearchDTO
|
||||
// ... 其他业务搜索DTO
|
||||
|
||||
// Add/Update DTO类 (15+个)
|
||||
- TUserHealthDataAddDTO
|
||||
- TDeviceInfoAddDTO
|
||||
- TAlertInfoAddDTO
|
||||
// ... 其他业务操作DTO
|
||||
|
||||
// DTO标准模式
|
||||
@Schema(description = "租户ID")
|
||||
private Long customerId;
|
||||
```
|
||||
|
||||
#### 2.3 服务层改造 (2天)
|
||||
|
||||
**核心服务类重构**:
|
||||
```java
|
||||
// 高优先级服务类
|
||||
- TUserHealthDataServiceImpl // 健康数据服务
|
||||
- TDeviceInfoServiceImpl // 设备信息服务
|
||||
- TAlertInfoServiceImpl // 告警信息服务
|
||||
|
||||
// 租户感知查询模式 (参考TWechatAlertConfigServiceImpl)
|
||||
if (bo.getCustomerId() != null) {
|
||||
if (bo.getCustomerId() == 0L) {
|
||||
// admin用户:查看所有数据
|
||||
} else {
|
||||
// 租户用户:查看全局数据+自己租户数据
|
||||
queryWrapper.and(wrapper ->
|
||||
wrapper.eq(TEntity::getCustomerId, 0L)
|
||||
.or()
|
||||
.eq(TEntity::getCustomerId, bo.getCustomerId())
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**租户上下文服务**:
|
||||
```java
|
||||
@Component
|
||||
public class TenantContextService {
|
||||
public Long getCurrentCustomerId() {
|
||||
LoginUser loginUser = getCurrentLoginUser();
|
||||
return loginUser != null ? loginUser.getCustomerId() : 0L;
|
||||
}
|
||||
|
||||
public boolean isAdminUser() {
|
||||
return getCurrentCustomerId() == 0L;
|
||||
}
|
||||
|
||||
public void validateTenantAccess(Long resourceCustomerId) {
|
||||
Long currentCustomerId = getCurrentCustomerId();
|
||||
if (currentCustomerId != 0L && !currentCustomerId.equals(resourceCustomerId)) {
|
||||
throw new SecurityException("Tenant access denied");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.4 控制器改造 (1天)
|
||||
|
||||
**控制器租户上下文注入**:
|
||||
```java
|
||||
// 高优先级控制器
|
||||
- TUserHealthDataController // 健康数据控制器
|
||||
- TDeviceInfoController // 设备信息控制器
|
||||
- TAlertInfoController // 告警信息控制器
|
||||
|
||||
// 控制器标准模式
|
||||
@PostMapping("/page")
|
||||
public Result<Map<String,Object>> page(PageQuery pageQuery, TEntitySearchDTO dto) {
|
||||
// 自动注入租户上下文
|
||||
dto.setCustomerId(tenantContextService.getCurrentCustomerId());
|
||||
return Result.data(facade.listEntityPage(pageQuery, dto));
|
||||
}
|
||||
|
||||
// 租户访问验证
|
||||
@PostMapping("/{id}")
|
||||
public Result<Boolean> update(@PathVariable Long id, @RequestBody TEntityUpdateDTO dto) {
|
||||
// 验证资源访问权限
|
||||
TEntity existing = service.getById(id);
|
||||
tenantContextService.validateTenantAccess(existing.getCustomerId());
|
||||
|
||||
dto.setCustomerId(tenantContextService.getCurrentCustomerId());
|
||||
return Result.status(service.updateById(dto));
|
||||
}
|
||||
```
|
||||
|
||||
### 🐍 Phase 3: ljwx-bigscreen Python服务改造 (3-4天)
|
||||
|
||||
#### 3.1 数据模型改造 (1天)
|
||||
|
||||
**需要添加customer_id的模型类** (models.py):
|
||||
```python
|
||||
# 高优先级模型类
|
||||
class UserHealthData(db.Model):
|
||||
__tablename__ = 't_user_health_data'
|
||||
customer_id = db.Column(db.BigInteger, nullable=False, default=0,
|
||||
comment='租户ID')
|
||||
|
||||
class DeviceInfo(db.Model):
|
||||
__tablename__ = 't_device_info'
|
||||
customer_id = db.Column(db.BigInteger, nullable=False, default=0,
|
||||
comment='租户ID')
|
||||
|
||||
class AlertInfo(db.Model):
|
||||
__tablename__ = 't_alert_info'
|
||||
customer_id = db.Column(db.BigInteger, nullable=False, default=0,
|
||||
comment='租户ID')
|
||||
|
||||
# 中优先级模型类
|
||||
class DeviceMessage(db.Model):
|
||||
class AlertRules(db.Model):
|
||||
class HealthBaseline(db.Model):
|
||||
# ... 其他业务模型
|
||||
```
|
||||
|
||||
#### 3.2 服务层改造 (1天)
|
||||
|
||||
**核心服务函数重构**:
|
||||
```python
|
||||
# user.py - 用户健康数据服务
|
||||
@with_tenant_context
|
||||
def get_user_health_data_by_tenant(org_id=None, user_id=None, customer_id=None):
|
||||
customer_id = customer_id or get_current_customer_id()
|
||||
|
||||
query = UserHealthData.query.filter(
|
||||
UserHealthData.customer_id == customer_id,
|
||||
UserHealthData.is_deleted == False
|
||||
)
|
||||
|
||||
if org_id:
|
||||
query = query.filter(UserHealthData.org_id == org_id)
|
||||
if user_id:
|
||||
query = query.filter(UserHealthData.user_id == user_id)
|
||||
|
||||
return query.all()
|
||||
|
||||
# device.py - 设备管理服务
|
||||
@with_tenant_context
|
||||
def get_device_info_by_tenant(customer_id=None):
|
||||
customer_id = customer_id or get_current_customer_id()
|
||||
|
||||
devices = DeviceInfo.query.filter(
|
||||
DeviceInfo.customer_id == customer_id,
|
||||
DeviceInfo.is_deleted == False
|
||||
).all()
|
||||
|
||||
return [device.to_dict() for device in devices]
|
||||
|
||||
# alert.py - 告警处理服务
|
||||
@with_tenant_context
|
||||
def get_tenant_alerts(severity_level=None, status=None, customer_id=None):
|
||||
customer_id = customer_id or get_current_customer_id()
|
||||
|
||||
query = AlertInfo.query.filter(
|
||||
AlertInfo.customer_id == customer_id
|
||||
)
|
||||
|
||||
if severity_level:
|
||||
query = query.filter(AlertInfo.severity_level == severity_level)
|
||||
if status:
|
||||
query = query.filter(AlertInfo.status == status)
|
||||
|
||||
return query.order_by(AlertInfo.create_time.desc()).all()
|
||||
```
|
||||
|
||||
#### 3.3 API端点改造 (2天)
|
||||
|
||||
**主要API端点重构** (bigScreen.py):
|
||||
```python
|
||||
# 健康数据API端点
|
||||
@app.route('/api/tenant/health_data', methods=['GET'])
|
||||
@with_tenant_context
|
||||
def get_tenant_health_data():
|
||||
customer_id = get_current_customer_id()
|
||||
org_id = request.args.get('org_id', type=int)
|
||||
user_id = request.args.get('user_id', type=int)
|
||||
|
||||
# 验证租户权限
|
||||
if org_id and not validate_tenant_access(org_id, customer_id):
|
||||
return jsonify({"error": "Organization not accessible"}), 403
|
||||
|
||||
# 租户级健康数据查询
|
||||
health_data = get_user_health_data_by_tenant(org_id, user_id, customer_id)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"customer_id": customer_id,
|
||||
"total_count": len(health_data),
|
||||
"data": [item.to_dict() for item in health_data]
|
||||
})
|
||||
|
||||
# 设备管理API端点
|
||||
@app.route('/api/tenant/devices', methods=['GET'])
|
||||
@with_tenant_context
|
||||
def get_tenant_devices():
|
||||
customer_id = get_current_customer_id()
|
||||
|
||||
devices = get_device_info_by_tenant(customer_id)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"customer_id": customer_id,
|
||||
"devices": devices
|
||||
})
|
||||
|
||||
# 告警管理API端点
|
||||
@app.route('/api/tenant/alerts', methods=['GET'])
|
||||
@with_tenant_context
|
||||
def get_tenant_alerts_api():
|
||||
customer_id = get_current_customer_id()
|
||||
severity_level = request.args.get('severity_level')
|
||||
status = request.args.get('status')
|
||||
|
||||
alerts = get_tenant_alerts(severity_level, status, customer_id)
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"customer_id": customer_id,
|
||||
"alerts": [alert.to_dict() for alert in alerts]
|
||||
})
|
||||
```
|
||||
|
||||
### 🧪 Phase 4: 测试与验证 (2天)
|
||||
|
||||
#### 4.1 功能测试
|
||||
|
||||
**多租户数据隔离测试**:
|
||||
- [ ] 租户A无法访问租户B的健康数据
|
||||
- [ ] 租户A无法访问租户B的设备信息
|
||||
- [ ] 租户A无法访问租户B的告警信息
|
||||
- [ ] 超级管理员(customer_id=0)可以访问所有租户数据
|
||||
|
||||
**API接口测试**:
|
||||
- [ ] 健康数据API租户隔离验证
|
||||
- [ ] 设备管理API租户隔离验证
|
||||
- [ ] 告警管理API租户隔离验证
|
||||
- [ ] 用户权限边界测试
|
||||
|
||||
#### 4.2 性能测试
|
||||
|
||||
**查询性能验证**:
|
||||
- [ ] 多租户查询使用正确索引 (EXPLAIN验证)
|
||||
- [ ] 大数据量下的查询响应时间 (<3秒)
|
||||
- [ ] 并发多租户查询的稳定性测试
|
||||
- [ ] 索引命中率和查询计划分析
|
||||
|
||||
**数据完整性验证**:
|
||||
- [ ] 数据迁移完整性检查
|
||||
- [ ] 跨表数据关联一致性验证
|
||||
- [ ] 租户ID数据分布统计
|
||||
- [ ] 历史数据迁移准确性验证
|
||||
|
||||
### 📈 预期性能提升
|
||||
|
||||
#### 查询性能指标
|
||||
- **多租户查询性能提升**: 60-80%
|
||||
- **索引查询 vs 全表扫描**: 从数千行扫描减少到个位数
|
||||
- **查询响应时间**: 大数据量场景下 <3秒
|
||||
- **并发处理能力**: 支持100+并发租户查询
|
||||
|
||||
#### 数据处理能力
|
||||
- **支持租户数量**: 1000+独立租户
|
||||
- **单租户用户容量**: 10万+用户
|
||||
- **健康数据处理**: 千万级时序数据高效查询
|
||||
- **设备管理规模**: 10万+设备的企业级管理
|
||||
|
||||
## 📅 实施时间规划
|
||||
|
||||
### 总体时间线: 2-3周
|
||||
|
||||
**Week 1**: 数据库架构完善
|
||||
- Day 1-2: 执行数据库迁移脚本
|
||||
- Day 3: 数据完整性验证和索引优化
|
||||
- Day 4-5: Java后端实体类和DTO改造
|
||||
|
||||
**Week 2**: 服务层全面改造
|
||||
- Day 1-2: Java服务层和控制器改造
|
||||
- Day 3-4: Python服务层和模型改造
|
||||
- Day 5: API端点租户上下文集成
|
||||
|
||||
**Week 3**: 测试优化和上线
|
||||
- Day 1-2: 功能测试和性能验证
|
||||
- Day 3-4: 缺陷修复和优化调整
|
||||
- Day 5: 生产环境部署和监控
|
||||
|
||||
## 🛡️ 风险控制
|
||||
|
||||
### 数据安全风险
|
||||
- **数据备份**: 完整数据库备份和恢复方案
|
||||
- **迁移验证**: 严格的数据完整性和一致性检查
|
||||
- **权限控制**: 多层次的租户访问权限验证
|
||||
|
||||
### 性能风险
|
||||
- **索引优化**: 预创建所有必要的多租户查询索引
|
||||
- **查询监控**: 实时监控慢查询和性能指标
|
||||
- **降级方案**: 性能问题时的服务降级策略
|
||||
|
||||
### 兼容性风险
|
||||
- **API兼容**: 保持所有现有API接口的向后兼容
|
||||
- **渐进迁移**: 支持新旧版本并行运行的平滑过渡
|
||||
- **回滚机制**: 快速回滚到迁移前状态的应急方案
|
||||
|
||||
## 🎯 成功标准
|
||||
|
||||
### 功能标准
|
||||
- ✅ 100%数据租户隔离,零数据泄露
|
||||
- ✅ 所有核心业务功能支持多租户
|
||||
- ✅ 管理员和租户用户权限正确区分
|
||||
- ✅ 新老API接口完全兼容
|
||||
|
||||
### 性能标准
|
||||
- ✅ 多租户查询性能提升60%以上
|
||||
- ✅ 大数据量查询响应时间<3秒
|
||||
- ✅ 支持1000+租户并发访问
|
||||
- ✅ 系统稳定性和可用性99.9%+
|
||||
|
||||
### 技术标准
|
||||
- ✅ 代码质量和规范符合企业标准
|
||||
- ✅ 完整的单元测试和集成测试覆盖
|
||||
- ✅ 详细的技术文档和操作手册
|
||||
- ✅ 监控报警和运维工具完善
|
||||
|
||||
## 📋 执行清单
|
||||
|
||||
### Phase 1: 数据库架构
|
||||
- [ ] 备份生产数据库
|
||||
- [ ] 执行business-tables-customer-id-migration.sql
|
||||
- [ ] 验证数据迁移完整性
|
||||
- [ ] 创建性能监控索引
|
||||
- [ ] 数据分布统计和验证
|
||||
|
||||
### Phase 2: Java后端改造
|
||||
- [ ] 添加customer_id到15+实体类
|
||||
- [ ] 更新50+DTO类支持customer_id
|
||||
- [ ] 实现TenantContextService租户上下文
|
||||
- [ ] 重构20+服务方法实现租户隔离
|
||||
- [ ] 更新15+控制器支持租户上下文
|
||||
|
||||
### Phase 3: Python服务改造
|
||||
- [ ] 更新8个核心模型类添加customer_id
|
||||
- [ ] 重构20+服务函数实现租户过滤
|
||||
- [ ] 更新30+API端点添加租户装饰器
|
||||
- [ ] 完善tenant_context.py租户上下文管理
|
||||
- [ ] 集成现有admin_helper.py权限体系
|
||||
|
||||
### Phase 4: 测试验证
|
||||
- [ ] 多租户数据隔离功能测试
|
||||
- [ ] API接口租户权限测试
|
||||
- [ ] 查询性能和索引使用验证
|
||||
- [ ] 并发访问和稳定性测试
|
||||
- [ ] 生产环境部署和监控配置
|
||||
|
||||
---
|
||||
|
||||
## 🚀 总结
|
||||
|
||||
这个完整的多租户优化方案基于对现有系统的深入分析,提供了从数据库到应用层的全栈解决方案。通过分阶段实施,可以在保证系统稳定性的前提下,实现企业级的多租户数据隔离和查询性能优化。
|
||||
|
||||
**关键优势**:
|
||||
- 🔒 **严格数据隔离**: 确保租户数据安全和隐私
|
||||
- ⚡ **显著性能提升**: 60-80%的查询性能改进
|
||||
- 🔄 **零侵入升级**: 完全向后兼容,平滑过渡
|
||||
- 🏢 **企业级扩展**: 支持大规模多租户部署
|
||||
|
||||
**预期收益**:
|
||||
- 支持1000+独立租户的企业级部署
|
||||
- 健康数据查询性能提升60-80%
|
||||
- 系统安全性和可靠性显著增强
|
||||
- 为未来业务扩展奠定坚实基础
|
||||
@@ -1,351 +0,0 @@
|
||||
# OrbStack 全局配置指南
|
||||
|
||||
## 📋 配置概述
|
||||
|
||||
已为 OrbStack 配置全局设置,无需每次构建时手动设置代理和 Harbor 配置。
|
||||
|
||||
## ✅ 已完成的配置
|
||||
|
||||
### 配置文件位置
|
||||
```
|
||||
~/.orbstack/config/docker.json
|
||||
```
|
||||
|
||||
### 配置内容
|
||||
|
||||
```json
|
||||
{
|
||||
"ipv6": true,
|
||||
"insecure-registries": [
|
||||
"127.0.0.1:8080",
|
||||
"localhost:8080"
|
||||
],
|
||||
"proxies": {
|
||||
"default": {
|
||||
"httpProxy": "http://127.0.0.1:7890",
|
||||
"httpsProxy": "http://127.0.0.1:7890",
|
||||
"noProxy": "localhost,127.0.0.1,*.local,host.docker.internal"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 配置说明
|
||||
|
||||
1. **insecure-registries**: 允许连接到本地 Harbor (127.0.0.1:8080)
|
||||
2. **proxies**: 全局代理配置,自动使用 7890 端口代理
|
||||
3. **ipv6**: 保持启用 IPv6 支持
|
||||
|
||||
## 🔧 IPv4 vs IPv6 问题
|
||||
|
||||
### 问题原因
|
||||
|
||||
当使用 `localhost:8080` 时,OrbStack 会优先尝试 IPv6 地址 `[::1]:8080`,但 Harbor 可能没有监听 IPv6,导致连接被拒绝。
|
||||
|
||||
### 解决方案
|
||||
|
||||
**使用 IPv4 地址 `127.0.0.1:8080` 而不是 `localhost:8080`**
|
||||
|
||||
```bash
|
||||
# ❌ 错误 - 可能解析为 IPv6
|
||||
REGISTRY=localhost:8080/ljwx
|
||||
|
||||
# ✅ 正确 - 强制使用 IPv4
|
||||
REGISTRY=127.0.0.1:8080/ljwx
|
||||
```
|
||||
|
||||
## 🚀 应用配置
|
||||
|
||||
### 重启 OrbStack
|
||||
|
||||
配置修改后需要重启 OrbStack 使其生效:
|
||||
|
||||
```bash
|
||||
# 方法 1: 使用命令行
|
||||
killall OrbStack
|
||||
sleep 2
|
||||
open -a OrbStack
|
||||
|
||||
# 方法 2: 手动操作
|
||||
# 1. 退出 OrbStack (菜单栏 > OrbStack > Quit)
|
||||
# 2. 重新启动 OrbStack
|
||||
```
|
||||
|
||||
### 验证配置
|
||||
|
||||
```bash
|
||||
# 1. 检查 Docker 配置
|
||||
docker info | grep -A 5 "Insecure Registries"
|
||||
|
||||
# 应该看到:
|
||||
# Insecure Registries:
|
||||
# 127.0.0.1:8080
|
||||
# localhost:8080
|
||||
|
||||
# 2. 检查代理配置
|
||||
docker info | grep -i proxy
|
||||
|
||||
# 应该看到代理信息
|
||||
```
|
||||
|
||||
### 测试连接
|
||||
|
||||
```bash
|
||||
# 1. 测试 Harbor 连接
|
||||
curl -L http://127.0.0.1:8080/api/v2.0/health
|
||||
|
||||
# 应该返回:
|
||||
# {"status":"healthy",...}
|
||||
|
||||
# 2. 测试 Docker 登录
|
||||
docker login 127.0.0.1:8080
|
||||
# Username: admin
|
||||
# Password: admin123
|
||||
|
||||
# 3. 测试代理拉取
|
||||
docker pull mysql:8.0
|
||||
# 应该很快完成,通过代理拉取
|
||||
```
|
||||
|
||||
## 📦 构建流程
|
||||
|
||||
配置完成后,构建流程自动使用全局配置:
|
||||
|
||||
```bash
|
||||
# 1. 重启 OrbStack(如果刚配置)
|
||||
killall OrbStack && sleep 2 && open -a OrbStack
|
||||
|
||||
# 2. 等待 OrbStack 启动(约 10 秒)
|
||||
sleep 10
|
||||
|
||||
# 3. 开始构建
|
||||
./build-and-push.sh mysql
|
||||
|
||||
# 脚本会:
|
||||
# ✅ 自动使用代理拉取基础镜像
|
||||
# ✅ 自动登录 Harbor (127.0.0.1:8080)
|
||||
# ✅ 自动推送到 Harbor
|
||||
```
|
||||
|
||||
## 🔍 配置详解
|
||||
|
||||
### 1. insecure-registries
|
||||
|
||||
允许连接到不使用 HTTPS 的私有仓库:
|
||||
|
||||
```json
|
||||
"insecure-registries": [
|
||||
"127.0.0.1:8080", // IPv4 地址
|
||||
"localhost:8080" // 主机名(可能解析为 IPv6)
|
||||
]
|
||||
```
|
||||
|
||||
### 2. proxies
|
||||
|
||||
全局代理配置,所有 Docker 操作自动使用代理:
|
||||
|
||||
```json
|
||||
"proxies": {
|
||||
"default": {
|
||||
"httpProxy": "http://127.0.0.1:7890", // HTTP 代理
|
||||
"httpsProxy": "http://127.0.0.1:7890", // HTTPS 代理
|
||||
"noProxy": "localhost,127.0.0.1,*.local,host.docker.internal" // 不使用代理的地址
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### noProxy 说明
|
||||
|
||||
- `localhost` - 本地主机名
|
||||
- `127.0.0.1` - 本地 IPv4 地址
|
||||
- `*.local` - 本地域名
|
||||
- `host.docker.internal` - Docker 内部主机地址
|
||||
|
||||
这些地址不会使用代理,确保本地服务(如 Harbor)的连接不经过代理。
|
||||
|
||||
### 3. ipv6
|
||||
|
||||
保持启用 IPv6 支持:
|
||||
|
||||
```json
|
||||
"ipv6": true
|
||||
```
|
||||
|
||||
虽然启用了 IPv6,但通过使用 `127.0.0.1` 而不是 `localhost`,可以强制使用 IPv4 连接。
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### 问题 1: 配置未生效
|
||||
|
||||
**症状**:
|
||||
```bash
|
||||
docker info | grep -i proxy
|
||||
# 没有代理信息
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查配置文件是否正确
|
||||
cat ~/.orbstack/config/docker.json
|
||||
|
||||
# 2. 确保 JSON 格式正确(无语法错误)
|
||||
python3 -m json.tool ~/.orbstack/config/docker.json
|
||||
|
||||
# 3. 重启 OrbStack
|
||||
killall OrbStack
|
||||
sleep 2
|
||||
open -a OrbStack
|
||||
```
|
||||
|
||||
### 问题 2: Harbor 连接仍然失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
dial tcp [::1]:8080: connect: connection refused
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 确认使用 IPv4 地址
|
||||
echo $HARBOR_HOST
|
||||
# 应该是: 127.0.0.1:8080
|
||||
|
||||
# 2. 检查 Harbor 监听地址
|
||||
cd ~/work/codes/tools/macos/harbor
|
||||
docker-compose ps | grep nginx
|
||||
# 应该看到: 0.0.0.0:8080->8080/tcp
|
||||
|
||||
# 3. 测试直接连接
|
||||
telnet 127.0.0.1 8080
|
||||
# 应该能连接
|
||||
```
|
||||
|
||||
### 问题 3: 代理不工作
|
||||
|
||||
**症状**:
|
||||
```
|
||||
docker pull mysql:8.0
|
||||
# 超时或很慢
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查代理服务
|
||||
lsof -i :7890
|
||||
# 应该看到代理进程
|
||||
|
||||
# 2. 测试代理
|
||||
curl --proxy http://127.0.0.1:7890 https://registry-1.docker.io/v2/
|
||||
|
||||
# 3. 检查 Docker 代理配置
|
||||
docker info | grep -i proxy
|
||||
|
||||
# 4. 重启 OrbStack
|
||||
killall OrbStack && sleep 2 && open -a OrbStack
|
||||
```
|
||||
|
||||
### 问题 4: 推送到 Harbor 失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
unauthorized: authentication required
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 登录 Harbor
|
||||
docker login 127.0.0.1:8080
|
||||
# Username: admin
|
||||
# Password: admin123
|
||||
|
||||
# 2. 检查凭证
|
||||
cat ~/.docker/config.json | grep 127.0.0.1:8080
|
||||
|
||||
# 3. 在 Harbor 中创建 ljwx 项目
|
||||
# 访问 http://127.0.0.1:8080
|
||||
# 登录后创建名为 "ljwx" 的项目(公开)
|
||||
```
|
||||
|
||||
## 📝 Harbor 项目配置
|
||||
|
||||
### 创建项目
|
||||
|
||||
1. 访问 Harbor: http://127.0.0.1:8080
|
||||
2. 登录: admin / admin123
|
||||
3. 点击 "Projects" > "New Project"
|
||||
4. 填写项目信息:
|
||||
- **Project Name**: ljwx
|
||||
- **Access Level**: Public
|
||||
- **Storage Quota**: -1 (无限制)
|
||||
5. 点击 "OK" 创建
|
||||
|
||||
### 检查项目
|
||||
|
||||
```bash
|
||||
# 使用 API 检查项目
|
||||
curl -u admin:admin123 http://127.0.0.1:8080/api/v2.0/projects/ljwx
|
||||
|
||||
# 应该返回项目信息
|
||||
```
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
### 1. 配置检查清单
|
||||
|
||||
在构建前检查:
|
||||
|
||||
```bash
|
||||
# ✅ OrbStack 运行中
|
||||
ps aux | grep OrbStack
|
||||
|
||||
# ✅ 配置文件正确
|
||||
cat ~/.orbstack/config/docker.json | python3 -m json.tool
|
||||
|
||||
# ✅ 代理服务运行
|
||||
lsof -i :7890
|
||||
|
||||
# ✅ Harbor 服务运行
|
||||
curl -L http://127.0.0.1:8080/api/v2.0/health
|
||||
|
||||
# ✅ Docker 登录
|
||||
docker login 127.0.0.1:8080
|
||||
|
||||
# ✅ ljwx 项目存在
|
||||
curl -u admin:admin123 http://127.0.0.1:8080/api/v2.0/projects/ljwx
|
||||
```
|
||||
|
||||
### 2. 日常使用
|
||||
|
||||
```bash
|
||||
# 直接构建,无需设置环境变量
|
||||
./build-and-push.sh mysql
|
||||
|
||||
# 脚本会自动:
|
||||
# - 使用全局代理配置
|
||||
# - 登录 Harbor
|
||||
# - 推送到 127.0.0.1:8080/ljwx
|
||||
```
|
||||
|
||||
### 3. 临时禁用代理
|
||||
|
||||
如果需要临时禁用代理:
|
||||
|
||||
```bash
|
||||
# 方法 1: 使用环境变量覆盖
|
||||
HTTP_PROXY="" HTTPS_PROXY="" ./build-and-push.sh mysql
|
||||
|
||||
# 方法 2: 修改 noProxy
|
||||
# 编辑 ~/.orbstack/config/docker.json
|
||||
# 添加 Docker Hub 到 noProxy 列表
|
||||
```
|
||||
|
||||
## 🔗 相关文档
|
||||
|
||||
- [BUILD_WITH_HARBOR.md](./BUILD_WITH_HARBOR.md) - Harbor 构建指南
|
||||
- [PROXY_CONFIG.md](./PROXY_CONFIG.md) - 代理配置详解
|
||||
- [DOCKER_README.md](./DOCKER_README.md) - Docker Compose 使用指南
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-26
|
||||
**版本**: 1.0.0
|
||||
@@ -1,222 +0,0 @@
|
||||
# OrbStack配置指南 - 移除国内镜像源
|
||||
|
||||
## 🎯 目标
|
||||
- 移除所有国内Docker镜像源
|
||||
- 配置使用原生Docker Hub
|
||||
- 支持私有GitLab Registry
|
||||
- 优化网络连接
|
||||
|
||||
## ✅ 已完成配置
|
||||
|
||||
### 1. Docker Daemon配置 (`~/.docker/daemon.json`)
|
||||
```json
|
||||
{
|
||||
"experimental": true,
|
||||
"features": {
|
||||
"buildkit": true
|
||||
},
|
||||
"insecure-registries": [
|
||||
"localhost:5001"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2. OrbStack配置 (`~/.orbstack/config/docker.json`)
|
||||
```json
|
||||
{
|
||||
"builder" : {
|
||||
"gc" : {
|
||||
"defaultKeepStorage" : "20GB",
|
||||
"enabled" : true
|
||||
}
|
||||
},
|
||||
"insecure-registries" : [
|
||||
"192.168.1.83:5002",
|
||||
"localhost:5001"
|
||||
],
|
||||
"ipv6" : true,
|
||||
"experimental" : false
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Jenkins配置更新
|
||||
- 移除了国内镜像加速: `JENKINS_UC_DOWNLOAD`
|
||||
- 配置使用官方更新源
|
||||
|
||||
## 🔧 网络问题解决方案
|
||||
|
||||
### ✅ 已解决:DNS解析问题
|
||||
通过修改hosts文件解决Docker Registry DNS解析问题:
|
||||
|
||||
```bash
|
||||
# 运行修复脚本
|
||||
chmod +x deployment/scripts/docker-hosts-fix.sh
|
||||
./deployment/scripts/docker-hosts-fix.sh
|
||||
```
|
||||
|
||||
**修复内容:**
|
||||
- 阻止Grammarly证书劫持: `127.0.0.1 iosapp-beta.grammarly.com`
|
||||
- 添加Docker Registry解析: `54.87.120.168 registry-1.docker.io`
|
||||
- 添加认证服务解析: `54.87.120.168 auth.docker.io`
|
||||
|
||||
### ExpressVPN TLS证书问题
|
||||
如果遇到TLS证书错误,可以:
|
||||
|
||||
1. **使用hosts文件修复** (推荐)
|
||||
```bash
|
||||
./deployment/scripts/docker-hosts-fix.sh
|
||||
```
|
||||
|
||||
2. **配置Docker使用特定DNS**
|
||||
```bash
|
||||
# 在 ~/.orbstack/config/docker.json 中添加
|
||||
{
|
||||
"dns": ["8.8.8.8", "1.1.1.1"]
|
||||
}
|
||||
```
|
||||
|
||||
3. **ExpressVPN设置优化**
|
||||
- 选择美国洛杉矶服务器
|
||||
- 禁用"阻止WebRTC"功能
|
||||
- 使用"Automatic"协议而非"OpenVPN"
|
||||
|
||||
## 🚀 验证步骤
|
||||
|
||||
### 1. 检查配置状态
|
||||
```bash
|
||||
# 检查Docker info,应该没有Registry Mirrors
|
||||
docker info | grep -A3 "Registry Mirrors"
|
||||
|
||||
# 检查DNS解析
|
||||
nslookup docker.io
|
||||
```
|
||||
|
||||
### 2. 测试镜像拉取
|
||||
```bash
|
||||
# 测试小镜像
|
||||
docker pull hello-world:latest
|
||||
|
||||
# 测试常用镜像
|
||||
docker pull alpine:latest
|
||||
docker pull nginx:latest
|
||||
```
|
||||
|
||||
### 3. 本地Registry测试
|
||||
```bash
|
||||
# 启动本地Registry
|
||||
cd /Users/brunogao/work/infra
|
||||
docker-compose -f docker/compose/jenkins-compose.yml up -d registry
|
||||
|
||||
# 测试推送
|
||||
docker tag alpine:latest localhost:5001/alpine:test
|
||||
docker push localhost:5001/alpine:test
|
||||
```
|
||||
|
||||
## 📝 GitLab Registry配置
|
||||
|
||||
### 1. 配置GitLab认证
|
||||
```bash
|
||||
# 登录GitLab Registry
|
||||
docker login gitlab.example.com:5050
|
||||
# 输入用户名和Personal Access Token
|
||||
```
|
||||
|
||||
### 2. 推送到GitLab
|
||||
```bash
|
||||
# 标记镜像
|
||||
docker tag my-app:latest gitlab.example.com:5050/group/project/my-app:latest
|
||||
|
||||
# 推送镜像
|
||||
docker push gitlab.example.com:5050/group/project/my-app:latest
|
||||
```
|
||||
|
||||
## 🛠️ 故障排除
|
||||
|
||||
### 问题1: DNS解析失败
|
||||
```bash
|
||||
# 解决方案:更新DNS设置
|
||||
sudo networksetup -setdnsservers Wi-Fi 8.8.8.8 1.1.1.1
|
||||
```
|
||||
|
||||
### 问题2: TLS证书错误
|
||||
```bash
|
||||
# 临时解决:重启ExpressVPN
|
||||
# 或切换到其他美国服务器节点
|
||||
```
|
||||
|
||||
### 问题3: 镜像拉取慢
|
||||
```bash
|
||||
# 检查网络延迟
|
||||
ping registry-1.docker.io
|
||||
|
||||
# 使用CDN加速(仅限官方)
|
||||
export DOCKER_REGISTRY_MIRROR=""
|
||||
```
|
||||
|
||||
## 🎭 性能优化建议
|
||||
|
||||
### 1. 构建缓存优化
|
||||
```dockerfile
|
||||
# 多阶段构建
|
||||
FROM node:18-alpine AS builder
|
||||
# ... 构建步骤
|
||||
|
||||
FROM nginx:alpine AS runtime
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
```
|
||||
|
||||
### 2. 镜像大小优化
|
||||
```bash
|
||||
# 使用.dockerignore
|
||||
echo "node_modules" >> .dockerignore
|
||||
echo ".git" >> .dockerignore
|
||||
|
||||
# 清理构建缓存
|
||||
docker system prune -af --volumes
|
||||
```
|
||||
|
||||
### 3. Registry策略
|
||||
- 本地开发: `localhost:5001`
|
||||
- CI/CD: GitLab Registry
|
||||
- 生产: 私有Registry或Docker Hub
|
||||
|
||||
## 📊 监控和维护
|
||||
|
||||
### 定期检查
|
||||
```bash
|
||||
# 检查镜像大小
|
||||
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
|
||||
|
||||
# 清理无用镜像
|
||||
docker image prune -af
|
||||
|
||||
# 检查网络配置
|
||||
docker network ls
|
||||
```
|
||||
|
||||
### 自动化脚本
|
||||
使用 `deployment/scripts/orbstack-config.sh` 进行定期检查和维护。
|
||||
|
||||
## ✨ 下一步计划
|
||||
|
||||
1. **配置GitLab CI/CD**
|
||||
- 创建`.gitlab-ci.yml`
|
||||
- 配置Runner
|
||||
|
||||
2. **设置监控**
|
||||
- Registry使用情况
|
||||
- 构建性能指标
|
||||
|
||||
3. **安全增强**
|
||||
- 镜像扫描
|
||||
- 漏洞检测
|
||||
|
||||
---
|
||||
|
||||
## 📞 支持
|
||||
|
||||
如遇问题:
|
||||
1. 检查ExpressVPN连接状态
|
||||
2. 验证DNS解析
|
||||
3. 查看Docker日志: `docker logs <container>`
|
||||
4. 运行诊断脚本: `./deployment/scripts/orbstack-config.sh`
|
||||
-302
@@ -1,302 +0,0 @@
|
||||
# Docker 代理配置指南
|
||||
|
||||
## 问题说明
|
||||
|
||||
在国内网络环境下,直接拉取 Docker Hub 镜像可能遇到以下问题:
|
||||
- ❌ 连接超时 (i/o timeout)
|
||||
- ❌ 拉取速度慢
|
||||
- ❌ TLS handshake timeout
|
||||
|
||||
## 解决方案
|
||||
|
||||
使用本地代理(ClashX、V2rayU 等)来加速 Docker 镜像拉取。
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 确认代理服务运行
|
||||
|
||||
```bash
|
||||
# 检查代理端口是否可用(默认 7890)
|
||||
curl --proxy http://127.0.0.1:7890 https://www.google.com
|
||||
|
||||
# 如果成功,说明代理正常工作
|
||||
```
|
||||
|
||||
### 2. 测试代理配置
|
||||
|
||||
```bash
|
||||
# 运行测试脚本
|
||||
./test-proxy.sh
|
||||
|
||||
# 输出示例:
|
||||
# 🔍 测试 Docker 代理配置
|
||||
# 🔧 代理配置:
|
||||
# HTTP_PROXY: http://127.0.0.1:7890
|
||||
# HTTPS_PROXY: http://127.0.0.1:7890
|
||||
# 🌐 测试代理连接 Docker Hub...
|
||||
# ✅ 代理连接正常
|
||||
# 📥 测试拉取基础镜像 (mysql:8.0)...
|
||||
# ✅ 镜像拉取成功
|
||||
```
|
||||
|
||||
### 3. 构建镜像
|
||||
|
||||
```bash
|
||||
# 使用默认代理配置(7890 端口)
|
||||
./build-and-push.sh mysql
|
||||
|
||||
# 或者自定义代理端口
|
||||
PROXY_PORT=7891 ./build-and-push.sh mysql
|
||||
```
|
||||
|
||||
## 📋 配置说明
|
||||
|
||||
### 方式一:环境变量(临时)
|
||||
|
||||
```bash
|
||||
# 设置代理
|
||||
export HTTP_PROXY=http://127.0.0.1:7890
|
||||
export HTTPS_PROXY=http://127.0.0.1:7890
|
||||
export NO_PROXY=localhost,127.0.0.1,*.local
|
||||
|
||||
# 构建镜像
|
||||
./build-and-push.sh mysql
|
||||
```
|
||||
|
||||
### 方式二:修改配置文件(永久)
|
||||
|
||||
编辑 `monitoring-versions.env`:
|
||||
|
||||
```bash
|
||||
# 代理配置 (用于拉取 Docker Hub 镜像)
|
||||
PROXY_PORT=7890
|
||||
HTTP_PROXY=http://127.0.0.1:7890
|
||||
HTTPS_PROXY=http://127.0.0.1:7890
|
||||
NO_PROXY=localhost,127.0.0.1,*.local
|
||||
```
|
||||
|
||||
### 方式三:命令行参数(一次性)
|
||||
|
||||
```bash
|
||||
# 自定义代理端口
|
||||
PROXY_PORT=7891 ./build-and-push.sh mysql
|
||||
|
||||
# 完全自定义代理地址
|
||||
HTTP_PROXY=http://proxy.example.com:8080 \
|
||||
HTTPS_PROXY=http://proxy.example.com:8080 \
|
||||
./build-and-push.sh mysql
|
||||
```
|
||||
|
||||
## 🔧 代理原理
|
||||
|
||||
### 构建时代理配置
|
||||
|
||||
脚本会自动将代理配置传递给 Docker 构建过程:
|
||||
|
||||
```bash
|
||||
docker buildx build \
|
||||
--build-arg HTTP_PROXY=http://127.0.0.1:7890 \
|
||||
--build-arg HTTPS_PROXY=http://127.0.0.1:7890 \
|
||||
--build-arg NO_PROXY=localhost,127.0.0.1,*.local \
|
||||
...
|
||||
```
|
||||
|
||||
### 代理生效范围
|
||||
|
||||
代理配置在以下场景生效:
|
||||
|
||||
1. **Docker 拉取基础镜像**
|
||||
```dockerfile
|
||||
FROM mysql:8.0 # 通过代理从 Docker Hub 拉取
|
||||
```
|
||||
|
||||
2. **Dockerfile 中的网络请求**
|
||||
```dockerfile
|
||||
RUN apt-get update # 通过代理访问软件源
|
||||
RUN pip install -r requirements.txt # 通过代理下载 Python 包
|
||||
```
|
||||
|
||||
3. **构建过程中的网络操作**
|
||||
- Maven 依赖下载
|
||||
- NPM 包下载
|
||||
- Go modules 下载
|
||||
|
||||
## 🌐 常见代理端口
|
||||
|
||||
| 代理工具 | 默认端口 |
|
||||
|---------|---------|
|
||||
| ClashX | 7890 |
|
||||
| ClashX Pro | 7890 |
|
||||
| V2rayU | 1087 |
|
||||
| Surge | 6152 |
|
||||
| Shadowsocks | 1080 |
|
||||
|
||||
## 🔍 验证代理生效
|
||||
|
||||
### 方法 1: 查看构建日志
|
||||
|
||||
```bash
|
||||
./build-and-push.sh mysql 2>&1 | grep -i proxy
|
||||
|
||||
# 应该看到:
|
||||
# 🔧 代理配置:
|
||||
# HTTP_PROXY: http://127.0.0.1:7890
|
||||
# HTTPS_PROXY: http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
### 方法 2: 手动拉取镜像
|
||||
|
||||
```bash
|
||||
# 设置代理
|
||||
export HTTP_PROXY=http://127.0.0.1:7890
|
||||
export HTTPS_PROXY=http://127.0.0.1:7890
|
||||
|
||||
# 拉取镜像
|
||||
docker pull mysql:8.0
|
||||
|
||||
# 如果速度很快,说明代理生效
|
||||
```
|
||||
|
||||
### 方法 3: 检查网络流量
|
||||
|
||||
在代理工具(如 ClashX)的日志中查看是否有 Docker 相关的连接记录。
|
||||
|
||||
## 🛠️ 故障排查
|
||||
|
||||
### 问题 1: 代理连接失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
⚠️ 代理连接可能有问题,将尝试继续...
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查代理服务是否运行
|
||||
lsof -i :7890
|
||||
|
||||
# 2. 测试代理连接
|
||||
curl --proxy http://127.0.0.1:7890 https://www.google.com
|
||||
|
||||
# 3. 检查代理配置
|
||||
cat ~/.config/clash/config.yaml # ClashX 配置
|
||||
```
|
||||
|
||||
### 问题 2: 镜像拉取仍然超时
|
||||
|
||||
**症状**:
|
||||
```
|
||||
ERROR: failed to do request: Head "https://registry-1.docker.io/...": dial tcp: i/o timeout
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 确认代理规则包含 Docker Hub
|
||||
# 在 ClashX 中确保 docker.io 走代理
|
||||
|
||||
# 2. 尝试使用 SOCKS5 代理
|
||||
export HTTP_PROXY=socks5://127.0.0.1:7891
|
||||
export HTTPS_PROXY=socks5://127.0.0.1:7891
|
||||
|
||||
# 3. 增加超时时间
|
||||
export DOCKER_CLIENT_TIMEOUT=120
|
||||
export COMPOSE_HTTP_TIMEOUT=120
|
||||
```
|
||||
|
||||
### 问题 3: 部分下载仍然失败
|
||||
|
||||
**症状**:
|
||||
```
|
||||
apt-get update 超时
|
||||
pip install 超时
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
|
||||
在 Dockerfile 中显式使用代理:
|
||||
|
||||
```dockerfile
|
||||
# APT 使用代理
|
||||
RUN apt-get update -o Acquire::http::Proxy="http://host.docker.internal:7890"
|
||||
|
||||
# pip 使用代理
|
||||
RUN pip install --proxy http://host.docker.internal:7890 -r requirements.txt
|
||||
|
||||
# Maven 使用代理
|
||||
ENV MAVEN_OPTS="-DproxySet=true -DproxyHost=host.docker.internal -DproxyPort=7890"
|
||||
```
|
||||
|
||||
### 问题 4: NO_PROXY 配置错误
|
||||
|
||||
**症状**:
|
||||
```
|
||||
无法连接到 localhost:8080 (Harbor)
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 确保 NO_PROXY 包含本地地址
|
||||
export NO_PROXY=localhost,127.0.0.1,*.local,host.docker.internal
|
||||
```
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
### 1. 混合使用代理和镜像源
|
||||
|
||||
```bash
|
||||
# 使用代理拉取基础镜像
|
||||
export HTTP_PROXY=http://127.0.0.1:7890
|
||||
|
||||
# 在 Dockerfile 中使用国内镜像源
|
||||
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
|
||||
RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
|
||||
```
|
||||
|
||||
### 2. 分层代理配置
|
||||
|
||||
```bash
|
||||
# Docker 守护进程代理(全局)
|
||||
# 编辑 ~/.docker/config.json
|
||||
{
|
||||
"proxies": {
|
||||
"default": {
|
||||
"httpProxy": "http://127.0.0.1:7890",
|
||||
"httpsProxy": "http://127.0.0.1:7890",
|
||||
"noProxy": "localhost,127.0.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 构建时代理(临时)
|
||||
./build-and-push.sh mysql
|
||||
```
|
||||
|
||||
### 3. 自动代理检测
|
||||
|
||||
脚本已内置代理检测功能:
|
||||
|
||||
```bash
|
||||
# 脚本会自动检测代理是否可用
|
||||
🔧 代理配置:
|
||||
HTTP_PROXY: http://127.0.0.1:7890
|
||||
HTTPS_PROXY: http://127.0.0.1:7890
|
||||
NO_PROXY: localhost,127.0.0.1,*.local
|
||||
✅ 代理连接正常
|
||||
```
|
||||
|
||||
## 📚 相关资源
|
||||
|
||||
- [Docker 代理配置文档](https://docs.docker.com/network/proxy/)
|
||||
- [Docker Buildx 代理配置](https://docs.docker.com/engine/reference/builder/#automatic-build-arguments)
|
||||
- [ClashX 使用指南](https://github.com/yichengchen/clashX)
|
||||
|
||||
## 🔗 相关文档
|
||||
|
||||
- [BUILD_WITH_HARBOR.md](./BUILD_WITH_HARBOR.md) - Harbor 构建指南
|
||||
- [DOCKER_README.md](./DOCKER_README.md) - Docker Compose 使用指南
|
||||
- [monitoring-versions.env](./monitoring-versions.env) - 版本和配置文件
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-25
|
||||
**版本**: 1.0.0
|
||||
@@ -1,303 +0,0 @@
|
||||
# LJWX v2.0 快速开始指南
|
||||
|
||||
## 🎯 5分钟快速部署
|
||||
|
||||
### 步骤1: 准备配置文件
|
||||
|
||||
```bash
|
||||
# 复制统一配置模板
|
||||
cp .env.unified .env
|
||||
|
||||
# 编辑配置(可选,使用默认值也可以)
|
||||
vim .env
|
||||
```
|
||||
|
||||
**关键配置项**:
|
||||
```bash
|
||||
LJWX_VERSION=2.0.3 # 版本号
|
||||
MYSQL_ROOT_PASSWORD=123456 # MySQL root密码
|
||||
MYSQL_DATABASE=test # 数据库名
|
||||
REDIS_PASSWORD=123456 # Redis密码
|
||||
REGISTRY=localhost:15000/ljwx # 镜像仓库
|
||||
```
|
||||
|
||||
### 步骤2: 导出数据库(如果有现有数据)
|
||||
|
||||
```bash
|
||||
# 从宿主机导出test数据库
|
||||
./db-migrate.sh export
|
||||
|
||||
# 查看导出的文件
|
||||
ls -lh docker/mysql/data.sql
|
||||
ls -lh docker/mysql/migrations/V2.0.3__baseline.sql
|
||||
```
|
||||
|
||||
### 步骤3: 一键构建、推送、部署
|
||||
|
||||
```bash
|
||||
# 方式1: 一键完成所有操作
|
||||
./build-and-push-v2.sh -e -a
|
||||
|
||||
# 方式2: 分步执行(推荐)
|
||||
./build-and-push-v2.sh -e # 导出数据库
|
||||
./build-and-push-v2.sh -b # 构建镜像
|
||||
./build-and-push-v2.sh -p # 推送镜像
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
```
|
||||
|
||||
### 步骤4: 验证部署
|
||||
|
||||
```bash
|
||||
# 查看服务状态
|
||||
docker-compose -f docker-compose.prod.v2.yml ps
|
||||
|
||||
# 查看迁移状态
|
||||
./db-migrate.sh status
|
||||
|
||||
# 测试服务
|
||||
curl http://localhost:9998/actuator/health # 后端
|
||||
curl http://localhost:8000/api/health # 大屏
|
||||
open http://localhost:8080 # 管理界面
|
||||
```
|
||||
|
||||
## 📋 核心命令速查
|
||||
|
||||
### 构建脚本
|
||||
|
||||
```bash
|
||||
# 构建
|
||||
./build-and-push-v2.sh -b # 构建所有镜像
|
||||
./build-and-push-v2.sh -b -c ljwx-boot # 构建单个组件
|
||||
|
||||
# 推送
|
||||
./build-and-push-v2.sh -p # 推送所有镜像
|
||||
./build-and-push-v2.sh -p -c ljwx-boot # 推送单个组件
|
||||
|
||||
# 部署
|
||||
./build-and-push-v2.sh -d # 部署所有服务
|
||||
|
||||
# 一键部署
|
||||
./build-and-push-v2.sh -a # build + push + deploy
|
||||
|
||||
# 数据库
|
||||
./build-and-push-v2.sh -e # 导出数据库
|
||||
./build-and-push-v2.sh -m # 应用迁移
|
||||
|
||||
# 帮助
|
||||
./build-and-push-v2.sh -h # 查看帮助
|
||||
```
|
||||
|
||||
### 数据库迁移
|
||||
|
||||
```bash
|
||||
# 导出基线
|
||||
./db-migrate.sh export 2.0.3
|
||||
|
||||
# 创建迁移
|
||||
./db-migrate.sh create 2.0.4 add_features
|
||||
|
||||
# 应用迁移
|
||||
./db-migrate.sh apply 2.0.4 # 应用特定版本
|
||||
./db-migrate.sh apply-all # 应用所有待执行迁移
|
||||
|
||||
# 查看状态
|
||||
./db-migrate.sh status
|
||||
|
||||
# 回滚
|
||||
./db-migrate.sh rollback 2.0.3
|
||||
|
||||
# 帮助
|
||||
./db-migrate.sh help
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```bash
|
||||
# 使用v2配置文件
|
||||
export COMPOSE_FILE=docker-compose.prod.v2.yml
|
||||
|
||||
# 启动服务
|
||||
docker-compose up -d
|
||||
|
||||
# 查看状态
|
||||
docker-compose ps
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f ljwx-boot
|
||||
|
||||
# 重启服务
|
||||
docker-compose restart ljwx-boot
|
||||
|
||||
# 停止服务
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
## 🔄 常见场景
|
||||
|
||||
### 场景1: 代码修改后快速测试
|
||||
|
||||
```bash
|
||||
# 1. 构建修改的组件
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
|
||||
# 2. 推送镜像
|
||||
./build-and-push-v2.sh -p -c ljwx-boot
|
||||
|
||||
# 3. 重启服务
|
||||
docker-compose -f docker-compose.prod.v2.yml restart ljwx-boot
|
||||
|
||||
# 4. 查看日志
|
||||
docker-compose -f docker-compose.prod.v2.yml logs -f ljwx-boot
|
||||
```
|
||||
|
||||
### 场景2: 数据库表结构变更
|
||||
|
||||
```bash
|
||||
# 1. 创建迁移脚本
|
||||
./db-migrate.sh create 2.0.4 add_user_fields
|
||||
|
||||
# 2. 编辑迁移SQL
|
||||
vim docker/mysql/migrations/V2.0.4__add_user_fields.sql
|
||||
|
||||
# 3. 测试应用
|
||||
./db-migrate.sh apply 2.0.4
|
||||
|
||||
# 4. 如有问题回滚
|
||||
./db-migrate.sh rollback 2.0.3
|
||||
|
||||
# 5. 确认无误后,重新构建MySQL镜像
|
||||
./build-and-push-v2.sh -b -c ljwx-mysql
|
||||
./build-and-push-v2.sh -p -c ljwx-mysql
|
||||
```
|
||||
|
||||
### 场景3: 版本升级
|
||||
|
||||
```bash
|
||||
# 1. 备份当前数据
|
||||
docker exec ljwx-mysql mysqldump -u root -p123456 test > backup_$(date +%Y%m%d).sql
|
||||
|
||||
# 2. 更新版本号
|
||||
vim .env
|
||||
# 修改: LJWX_VERSION=2.0.4
|
||||
|
||||
# 3. 导出最新数据库
|
||||
./db-migrate.sh export 2.0.4
|
||||
|
||||
# 4. 构建新版本
|
||||
./build-and-push-v2.sh -b
|
||||
|
||||
# 5. 推送镜像
|
||||
./build-and-push-v2.sh -p
|
||||
|
||||
# 6. 部署新版本
|
||||
./build-and-push-v2.sh -d
|
||||
```
|
||||
|
||||
### 场景4: 问题排查
|
||||
|
||||
```bash
|
||||
# 查看所有服务状态
|
||||
docker-compose -f docker-compose.prod.v2.yml ps
|
||||
|
||||
# 查看特定服务日志
|
||||
docker-compose -f docker-compose.prod.v2.yml logs --tail=100 ljwx-boot
|
||||
|
||||
# 进入容器排查
|
||||
docker exec -it ljwx-boot bash
|
||||
|
||||
# 查看数据库迁移历史
|
||||
./db-migrate.sh status
|
||||
|
||||
# 检查数据库连接
|
||||
docker exec ljwx-mysql mysql -u root -p123456 test -e "SELECT 1"
|
||||
|
||||
# 检查Redis连接
|
||||
docker exec ljwx-redis redis-cli -a 123456 ping
|
||||
```
|
||||
|
||||
## 📁 文件结构
|
||||
|
||||
```
|
||||
release/
|
||||
├── .env.unified # 配置模板 ⭐
|
||||
├── .env # 实际配置 ⭐
|
||||
├── docker-compose.prod.v2.yml # v2 Compose文件 ⭐
|
||||
├── build-and-push-v2.sh # v2 构建脚本 ⭐
|
||||
├── db-migrate.sh # 迁移工具 ⭐
|
||||
├── QUICK-START-V2.md # 本文档
|
||||
├── DEPLOYMENT-GUIDE-V2.md # 详细指南
|
||||
└── docker/mysql/
|
||||
├── data.sql # 当前数据库快照
|
||||
└── migrations/ # 迁移脚本目录
|
||||
├── README.md
|
||||
├── V2.0.3__baseline.sql
|
||||
└── rollback/
|
||||
```
|
||||
|
||||
## 🆚 v1 vs v2 对比
|
||||
|
||||
| 特性 | v1.x | v2.0 |
|
||||
|------|------|------|
|
||||
| 配置管理 | 多文件分散 | 单一.env文件 ✅ |
|
||||
| 构建方式 | 一体化执行 | 分阶段执行 ✅ |
|
||||
| 数据库管理 | 手动导出 | 版本化迁移 ✅ |
|
||||
| 回滚支持 | ❌ | ✅ |
|
||||
| 迁移历史 | ❌ | ✅ |
|
||||
| 错误恢复 | 困难 | 容易 ✅ |
|
||||
|
||||
## 🚨 注意事项
|
||||
|
||||
### 首次使用前必做
|
||||
|
||||
1. ✅ 复制并编辑 `.env` 配置文件
|
||||
2. ✅ 确保宿主机MySQL可访问(用于导出数据)
|
||||
3. ✅ 确保本地Registry运行(localhost:15000)
|
||||
4. ✅ 备份重要数据
|
||||
|
||||
### 生产环境部署
|
||||
|
||||
1. ✅ 使用分阶段部署(-b → -p → -d)
|
||||
2. ✅ 部署前备份数据库
|
||||
3. ✅ 在测试环境验证后再上生产
|
||||
4. ✅ 准备回滚方案
|
||||
|
||||
### 数据库迁移
|
||||
|
||||
1. ✅ 迁移脚本必须幂等
|
||||
2. ✅ 编写对应的回滚脚本
|
||||
3. ✅ 测试环境验证后再生产
|
||||
4. ✅ 迁移前备份数据
|
||||
|
||||
## 🔗 相关文档
|
||||
|
||||
- [详细部署指南](DEPLOYMENT-GUIDE-V2.md)
|
||||
- [数据库迁移文档](docker/mysql/migrations/README.md)
|
||||
- [配置文件说明](.env.unified)
|
||||
|
||||
## 💡 快速技巧
|
||||
|
||||
```bash
|
||||
# 设置别名简化命令
|
||||
alias build='./build-and-push-v2.sh -b'
|
||||
alias deploy='./build-and-push-v2.sh -d'
|
||||
alias logs='docker-compose -f docker-compose.prod.v2.yml logs -f'
|
||||
|
||||
# 使用
|
||||
build -c ljwx-boot # 构建boot组件
|
||||
deploy # 部署服务
|
||||
logs ljwx-boot # 查看boot日志
|
||||
```
|
||||
|
||||
## 🆘 遇到问题?
|
||||
|
||||
1. 查看构建日志:`ls -lt logs/build/`
|
||||
2. 查看部署日志:`ls -lt logs/deploy/`
|
||||
3. 查看服务日志:`docker-compose -f docker-compose.prod.v2.yml logs`
|
||||
4. 检查配置文件:`cat .env`
|
||||
5. 参考详细文档:`cat DEPLOYMENT-GUIDE-V2.md`
|
||||
|
||||
---
|
||||
|
||||
**祝部署顺利!** 🎉
|
||||
|
||||
如有问题,请参考 [DEPLOYMENT-GUIDE-V2.md](DEPLOYMENT-GUIDE-V2.md) 获取更多详细信息。
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
# 🚀 快速开始指南
|
||||
|
||||
## 一键部署 (推荐)
|
||||
|
||||
```bash
|
||||
# 进入项目目录
|
||||
cd /Users/brunogao/work/infra
|
||||
|
||||
# 一键自动部署所有服务
|
||||
./build-infra.sh --full-auto
|
||||
```
|
||||
|
||||
## 服务访问地址
|
||||
|
||||
部署完成后,您可以通过以下地址访问服务:
|
||||
|
||||
| 服务 | 地址 | 用途 |
|
||||
|------|------|------|
|
||||
| **Gitea** | http://localhost:33000 | Git代码仓库 |
|
||||
| **Jenkins** | http://localhost:38080 | CI/CD平台 (admin/admin123) |
|
||||
| **Registry** | http://localhost:35001 | Docker镜像仓库 |
|
||||
| **Registry UI** | http://localhost:35002 | 镜像仓库管理界面 |
|
||||
|
||||
## SSH访问
|
||||
|
||||
```bash
|
||||
# Gitea SSH克隆 (端口32222)
|
||||
git clone ssh://git@localhost:32222/username/repository.git
|
||||
```
|
||||
|
||||
## 验证部署
|
||||
|
||||
```bash
|
||||
# 检查所有服务健康状态
|
||||
./scripts/maintenance/health-check.sh
|
||||
|
||||
# 查看服务日志
|
||||
./scripts/utils/show-logs.sh all
|
||||
```
|
||||
|
||||
## 常用管理命令
|
||||
|
||||
```bash
|
||||
# 完全自动化部署
|
||||
./build-infra.sh --full-auto
|
||||
|
||||
# 分步骤部署 (逐步确认)
|
||||
./build-infra.sh --step-by-step
|
||||
|
||||
# 清理所有服务
|
||||
./build-infra.sh --cleanup
|
||||
|
||||
# 仅运行验证测试
|
||||
./build-infra.sh --verify
|
||||
|
||||
# 健康检查
|
||||
./scripts/maintenance/health-check.sh
|
||||
|
||||
# 查看日志
|
||||
./scripts/utils/show-logs.sh [gitea|jenkins|registry|all]
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 端口冲突
|
||||
如果遇到端口占用问题:
|
||||
```bash
|
||||
# 检查端口占用
|
||||
lsof -i :33000,38080,35001,35002,32222,35000
|
||||
|
||||
# 清理现有服务
|
||||
./build-infra.sh --cleanup
|
||||
```
|
||||
|
||||
### 服务启动失败
|
||||
```bash
|
||||
# 查看具体服务日志
|
||||
./scripts/utils/show-logs.sh [服务名] -f
|
||||
|
||||
# 重新部署
|
||||
./build-infra.sh --cleanup
|
||||
./build-infra.sh --full-auto
|
||||
```
|
||||
|
||||
### 配置修改
|
||||
主要配置文件:
|
||||
- `configs/global.env` - 全局环境变量
|
||||
- `docker/compose/*.yml` - 服务编排配置
|
||||
- `jenkins/casc/jenkins.yaml` - Jenkins自动配置
|
||||
|
||||
修改配置后重新部署:
|
||||
```bash
|
||||
./build-infra.sh --cleanup
|
||||
./build-infra.sh --full-auto
|
||||
```
|
||||
|
||||
## 下一步操作
|
||||
|
||||
1. **配置Gitea**
|
||||
- 访问 http://localhost:33000
|
||||
- 创建管理员账号
|
||||
- 创建组织和仓库
|
||||
|
||||
2. **配置Jenkins**
|
||||
- 访问 http://localhost:38080
|
||||
- 使用 admin/admin123 登录
|
||||
- 验证自动配置是否生效
|
||||
|
||||
3. **测试CI/CD流程**
|
||||
- 在Gitea中推送代码
|
||||
- 观察Jenkins自动构建
|
||||
- 验证镜像推送到Registry
|
||||
|
||||
## 技术支持
|
||||
|
||||
- 部署问题: 查看 `BUILD_PLAN.md`
|
||||
- 配置详情: 查看 `CLAUDE.md`
|
||||
- 故障排查: 查看 `docs/troubleshooting.md`
|
||||
@@ -1,712 +0,0 @@
|
||||
<<<<<<< HEAD
|
||||
# Mac Studio M2 企业级 CI/CD 基础设施
|
||||
|
||||
## 🚀 完全自动化部署 - 已验证可用 ✅
|
||||
|
||||
这是一套完整的企业级CI/CD基础设施,专为Mac Studio M2环境优化,支持**一键自动化部署**,无需手动配置。
|
||||
|
||||
### ⚡ 快速开始
|
||||
|
||||
```bash
|
||||
# 一键自动化部署所有服务
|
||||
./build-infra.sh --full-auto
|
||||
|
||||
# 分步骤部署(逐步确认)
|
||||
./build-infra.sh --step-by-step
|
||||
|
||||
# 验证现有服务
|
||||
./build-infra.sh --verify
|
||||
```
|
||||
|
||||
### 🌐 服务访问地址
|
||||
|
||||
部署完成后,通过以下地址访问服务:
|
||||
|
||||
| 服务 | 地址 | 用途 | 默认账号 |
|
||||
|------|------|------|----------|
|
||||
| **Gitea** | http://localhost:33000 | Git代码仓库 + Actions | 需要初始化 |
|
||||
| **Jenkins** | http://localhost:38080 | CI/CD平台 | admin / admin123 |
|
||||
| **Registry** | http://localhost:35001 | Docker镜像仓库 | 无认证 |
|
||||
| **Registry UI** | http://localhost:35002 | 镜像管理界面 | 无认证 |
|
||||
|
||||
**SSH访问:**
|
||||
```bash
|
||||
# Gitea SSH克隆 (端口32222)
|
||||
git clone ssh://git@localhost:32222/username/repository.git
|
||||
```
|
||||
|
||||
### 🎯 核心特性
|
||||
|
||||
- ✅ **一键部署**: 完全自动化,15分钟内完成所有配置
|
||||
- ✅ **端口优化**: 统一使用3开头端口,避免冲突
|
||||
- ✅ **多平台构建**: 支持 linux/amd64 + linux/arm64
|
||||
- ✅ **Configuration as Code**: Jenkins零手动配置
|
||||
- ✅ **企业级功能**: 完整的CI/CD流水线支持
|
||||
- ✅ **健康监控**: 自动化服务状态检查
|
||||
- ✅ **数据持久化**: 所有数据自动备份和恢复
|
||||
|
||||
### 📋 端口分配
|
||||
|
||||
```
|
||||
服务端口分配(避免冲突):
|
||||
├── Gitea: 33000 (Web) + 32222 (SSH)
|
||||
├── Jenkins: 38080 (Web) + 35000 (Agent)
|
||||
├── Docker Registry: 35001 (API) + 35002 (UI)
|
||||
└── 预留监控端口: 37001+ (Prometheus等)
|
||||
```
|
||||
|
||||
### 🏗️ 架构组件
|
||||
|
||||
**核心服务:**
|
||||
- **Jenkins LTS**: CI/CD服务器,基于JDK21
|
||||
- **Gitea 1.21**: 轻量级Git服务,支持Actions
|
||||
- **Docker Registry**: 本地镜像仓库
|
||||
- **Registry UI**: 可视化镜像管理
|
||||
|
||||
**环境信息:**
|
||||
- **硬件**: Mac Studio M2 Ultra (24核CPU, 76核GPU, 192GB内存)
|
||||
- **系统**: macOS Sequoia 15.7
|
||||
- **容器**: Docker Desktop + OrbStack优化
|
||||
- **网络**: 统一cicd-network网络
|
||||
|
||||
### 📂 项目结构
|
||||
|
||||
```
|
||||
infra/
|
||||
├── build-infra.sh # 🌟 一键部署脚本
|
||||
├── configs/
|
||||
│ └── global.env # 统一环境配置
|
||||
├── docker/compose/ # Docker编排配置
|
||||
│ ├── gitea-compose.yml # Gitea服务
|
||||
│ ├── jenkins-simple.yml # Jenkins服务
|
||||
│ └── registry-simple.yml # Registry服务
|
||||
├── jenkins/
|
||||
│ ├── casc/jenkins.yaml # Jenkins自动配置
|
||||
│ ├── shared-library/ # Pipeline共享库
|
||||
│ └── templates/ # 项目模板
|
||||
├── scripts/
|
||||
│ ├── maintenance/ # 维护脚本
|
||||
│ └── utils/ # 工具脚本
|
||||
└── docs/ # 文档
|
||||
```
|
||||
|
||||
### 🔧 管理命令
|
||||
|
||||
```bash
|
||||
# 部署管理
|
||||
./build-infra.sh --full-auto # 完全自动化部署 (推荐)
|
||||
./build-infra.sh --step-by-step # 分步骤部署
|
||||
./build-infra.sh --cleanup # 清理所有服务
|
||||
./build-infra.sh --verify # 验证服务状态
|
||||
|
||||
# 日常维护
|
||||
./scripts/maintenance/health-check.sh # 健康检查
|
||||
./scripts/utils/show-logs.sh [service] # 查看日志
|
||||
|
||||
# 传统管理脚本 (保留兼容)
|
||||
./jenkins-manager.sh [status|start|stop|backup|health]
|
||||
```
|
||||
|
||||
### 🚀 CI/CD功能特性
|
||||
|
||||
#### Jenkins自动配置 (CasC)
|
||||
- ✅ **50+插件自动安装**: Docker, Gitea, Pipeline, 多平台构建等
|
||||
- ✅ **工具自动配置**: Git, Maven, Gradle, NodeJS, Docker, Python
|
||||
- ✅ **凭据模板**: Gitea, Registry, SSH凭据预配置
|
||||
- ✅ **云配置**: Docker和Kubernetes云支持
|
||||
- ✅ **示例作业**: 多平台构建和系统监控作业
|
||||
|
||||
#### 多平台构建支持
|
||||
```groovy
|
||||
// 自动支持的构建平台
|
||||
pipeline {
|
||||
environment {
|
||||
PLATFORMS = 'linux/amd64,linux/arm64'
|
||||
REGISTRY = 'localhost:35001'
|
||||
}
|
||||
stages {
|
||||
stage('多平台构建') {
|
||||
steps {
|
||||
buildMultiPlatformImage([
|
||||
imageName: "${REGISTRY}/app:${BUILD_NUMBER}",
|
||||
platforms: env.PLATFORMS
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 📊 部署验证
|
||||
|
||||
部署完成后,系统会自动验证:
|
||||
|
||||
- ✅ **容器状态**: 所有服务容器正常运行
|
||||
- ✅ **端口监听**: 所有端口正确绑定
|
||||
- ✅ **API响应**: 所有服务API正常响应
|
||||
- ✅ **健康检查**: Gitea和Registry健康检查通过
|
||||
- ✅ **Web界面**: 所有Web界面可正常访问
|
||||
|
||||
### 🛠️ 故障排查
|
||||
|
||||
#### 常见问题
|
||||
|
||||
**端口占用:**
|
||||
```bash
|
||||
# 检查端口占用
|
||||
lsof -i :33000,38080,35001,35002
|
||||
|
||||
# 清理并重新部署
|
||||
./build-infra.sh --cleanup
|
||||
./build-infra.sh --full-auto
|
||||
```
|
||||
|
||||
**服务启动失败:**
|
||||
```bash
|
||||
# 查看服务日志
|
||||
./scripts/utils/show-logs.sh [gitea|jenkins|registry|all]
|
||||
|
||||
# 健康检查
|
||||
./scripts/maintenance/health-check.sh
|
||||
```
|
||||
|
||||
**配置修改:**
|
||||
- 主配置文件: `configs/global.env`
|
||||
- Jenkins配置: `docker/compose/jenkins/casc/jenkins.yaml`
|
||||
- 修改后重新部署生效
|
||||
|
||||
### 💡 最佳实践
|
||||
|
||||
#### CI/CD流程
|
||||
1. **代码管理**: 在Gitea中创建仓库和组织
|
||||
2. **Pipeline配置**: 使用预置模板快速创建
|
||||
3. **多平台构建**: 自动支持AMD64和ARM64
|
||||
4. **镜像管理**: Registry UI可视化管理镜像
|
||||
|
||||
#### 维护建议
|
||||
- **定期备份**: 使用内置备份脚本
|
||||
- **健康监控**: 定期运行健康检查
|
||||
- **更新管理**: 定期更新Docker镜像
|
||||
- **日志管理**: 定期清理服务日志
|
||||
|
||||
### 📈 性能优化
|
||||
|
||||
**资源配置优化:**
|
||||
- Jenkins JVM: `-Xmx2g -Xms1g`
|
||||
- 构建并发: 支持多个并行构建
|
||||
- 镜像缓存: 本地Registry加速构建
|
||||
- 网络优化: 统一Docker网络提高通信效率
|
||||
|
||||
### 🔄 升级和扩展
|
||||
|
||||
#### 监控扩展 (预留)
|
||||
```bash
|
||||
# 监控服务端口预留
|
||||
PROMETHEUS_PORT=37001
|
||||
GRAFANA_PORT=37002
|
||||
```
|
||||
|
||||
#### Kubernetes集成
|
||||
- Jenkins Kubernetes插件已预配置
|
||||
- 支持K8s动态Agent
|
||||
- 多环境部署支持
|
||||
|
||||
### 📞 技术支持
|
||||
|
||||
- **快速开始**: 查看 `QUICK_START.md`
|
||||
- **详细规划**: 查看 `BUILD_PLAN.md`
|
||||
- **配置说明**: 查看 `CLAUDE.md`
|
||||
- **问题排查**: 查看 `docs/troubleshooting.md`
|
||||
|
||||
### 🎉 版本信息
|
||||
|
||||
- **当前版本**: v2.0 (统一端口版本)
|
||||
- **Jenkins版本**: LTS (JDK21)
|
||||
- **Gitea版本**: 1.21
|
||||
- **Registry版本**: 2.x
|
||||
- **最后更新**: 2025-01-23
|
||||
|
||||
### 📄 许可证
|
||||
|
||||
MIT License
|
||||
|
||||
---
|
||||
|
||||
## 🚀 立即开始
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone <your-repo-url>
|
||||
cd infra
|
||||
|
||||
# 一键部署所有服务
|
||||
./build-infra.sh --full-auto
|
||||
|
||||
# 访问服务
|
||||
open http://localhost:33000 # Gitea
|
||||
open http://localhost:38080 # Jenkins (admin/admin123)
|
||||
open http://localhost:35002 # Registry UI
|
||||
```
|
||||
|
||||
**部署时间**: 约10-15分钟
|
||||
**服务数量**: 4个核心服务
|
||||
**支持平台**: Mac Studio M2 + Docker Desktop
|
||||
=======
|
||||
# 灵境万象健康管理系统 (LJWX)
|
||||
|
||||

|
||||
[](./LICENSE)
|
||||

|
||||
|
||||
## 📋 项目概述
|
||||
|
||||
灵境万象健康管理系统(LJWX)是一套完整的企业级健康监测解决方案,专为工业环境下的可穿戴设备健康数据监控而设计。系统集成了数据采集、实时分析、智能告警、可视化大屏等功能模块,为企业提供全方位的员工健康安全保障。
|
||||
|
||||
### 🎯 核心特性
|
||||
|
||||
- **🏥 健康数据监控**: 实时采集心率、血压、体温、运动数据等多维度健康指标
|
||||
- **🚨 智能告警系统**: 多租户告警规则管理,支持微信、消息、大屏推送
|
||||
- **📊 可视化大屏**: 专业级监控大屏,实时展示健康状态和告警信息
|
||||
- **📱 移动端应用**: Flutter开发的移动APP,支持数据查看和设备管理
|
||||
- **⌚ 智能手表集成**: 支持华为Watch4等智能穿戴设备数据采集
|
||||
- **🏢 多租户架构**: 企业级权限管理,支持租户隔离和告警规则隔离
|
||||
|
||||
## 🏗️ 系统架构
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ ljwx-watch │ │ ljwx-phone │ │ ljwx-admin │ │ljwx-bigscreen│
|
||||
│ 智能手表 │ ──▶ │ 移动应用 │ ──▶ │ 管理后台 │ ──▶ │ 监控大屏 │
|
||||
│ (HarmonyOS)│ │ (Flutter) │ │ (Vue3) │ │ (Python) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
||||
│ │ │ │
|
||||
└───────────────────┼───────────────────┼───────────────────┘
|
||||
│ │
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ ljwx-boot │ │ 数据存储 │
|
||||
│ 后端API │◄──▶│ MySQL+Redis │
|
||||
│(Spring Boot)│ │ │
|
||||
└─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
## 📂 项目结构
|
||||
|
||||
### 🔧 后端服务 (ljwx-boot)
|
||||
- **Spring Boot 3.3.2 + Java 21** - 现代化微服务架构
|
||||
- **健康管理模块**: 10+健康指标实时监控、睡眠分析、运动追踪
|
||||
- **系统管理模块**: 多租户架构、RBAC权限控制、组织管理
|
||||
- **设备管理模块**: IoT设备生命周期管理、状态监控
|
||||
- **多租户告警系统**: 智能阈值监控、多级告警处理、租户级别告警规则隔离
|
||||
- **地理围栏**: 虚拟边界监控、位置告警
|
||||
|
||||
### 🖥️ 前端管理 (ljwx-admin)
|
||||
- **Vue3 + TypeScript + Naive UI** - 现代化管理界面
|
||||
- **健康数据管理**: ECharts可视化、Excel导出、时间序列分析
|
||||
- **设备管理**: 电池监控、佩戴状态、设备配置
|
||||
- **告警管理**: 实时告警监控、规则配置、微信集成
|
||||
- **用户组织管理**: 分层权限、角色管理、部门架构
|
||||
- **系统监控**: 性能指标、日志管理、缓存监控
|
||||
|
||||
### 📊 监控大屏 (ljwx-bigscreen)
|
||||
- **Python Flask + Socket.IO** - 高性能实时监控
|
||||
- **实时数据处理**: 支持1000+设备并发、QPS>1400
|
||||
- **告警处理引擎**: 多渠道通知、层级分发、WebSocket推送
|
||||
- **健康分析系统**: AI健康画像、个人基线、Z-score异常检测
|
||||
- **地图可视化**: 实时位置追踪、告警地点标记
|
||||
- **性能优化**: Redis缓存、批量查询、连接池管理
|
||||
|
||||
### 📱 移动应用 (ljwx-phone)
|
||||
- **Flutter 3.0+ 跨平台** - 统一iOS/Android体验
|
||||
- **蓝牙BLE集成**: 自动设备发现、二进制协议、实时同步
|
||||
- **健康数据可视化**: FL Chart图表、雷达图健康评分
|
||||
- **管理员模式**: 嵌入式Web界面、SHA认证、角色切换
|
||||
- **数据同步**: 蓝牙/WiFi双模式、本地缓存、批量上传
|
||||
- **告警通知**: 实时推送、声音提醒、状态指示
|
||||
|
||||
### ⌚ 智能手表 (ljwx-watch)
|
||||
- **HarmonyOS 3.0 原生应用** - 深度系统集成
|
||||
- **健康传感器**: 心率、血氧、体温、压力、步数监测
|
||||
- **电源优化**: 统一定时器、15-18小时续航、智能调度
|
||||
- **通信协议**: 高级TLV二进制格式、50%数据压缩
|
||||
- **紧急功能**: SOS按钮、跌倒检测、一键告警
|
||||
- **实时同步**: 蓝牙BLE/WiFi双通道、离线缓存
|
||||
|
||||
## 🚀 最新功能 v1.3.8
|
||||
|
||||
### 🔧 Excel导出功能修复与静态文件优化 (2025-08-29)
|
||||
|
||||
#### **Excel导出功能完善**
|
||||
- **导出故障修复**: 修复health_table.html中Excel导出无错误日志的问题
|
||||
- **XLSX库路径修复**: 解决Flask静态文件路径配置导致的XLSX库加载失败
|
||||
- **增强错误处理**: 添加详细的调试日志和错误提示,提升用户体验
|
||||
- **CDN备用机制**: 实现本地XLSX库失败时的CDN自动降级加载
|
||||
|
||||
#### **自定义弹窗系统**
|
||||
- **统一弹窗组件**: 创建可复用的`showCustomAlert`组件替代原生alert
|
||||
- **视觉效果升级**: 科技感弹窗设计,支持键盘快捷键(ESC、Enter)
|
||||
- **模块化设计**: 提取为独立的`custom-alert.js`文件供全局复用
|
||||
- **增强功能**: 支持确认框、回调函数、动画效果
|
||||
|
||||
#### **静态文件架构优化**
|
||||
- **路径问题诊断**: 发现并修复静态文件错误放置在`/bigScreen/static/`的问题
|
||||
- **Flask配置确认**: 验证`static_folder='../static'`指向正确的`/bigscreen/static/`
|
||||
- **CDN文件迁移**: 将Bootstrap、FontAwesome、ECharts等离线CDN文件移至正确位置
|
||||
- **重复文件清理**: 删除错误位置的重复文件,避免开发者混淆
|
||||
|
||||
```bash
|
||||
# 修复前的问题路径结构
|
||||
/bigscreen/bigScreen/static/ # ❌ 错误位置 - Flask无法访问
|
||||
├── css/bootstrap-5.1.3.min.css
|
||||
├── js/echarts.min.js
|
||||
└── js/xlsx-0.18.5.full.min.js
|
||||
|
||||
# 修复后的正确路径结构
|
||||
/bigscreen/static/ # ✅ 正确位置 - Flask可以访问
|
||||
├── css/bootstrap-5.1.3.min.css
|
||||
├── js/echarts.min.js
|
||||
└── js/xlsx-0.18.5.full.min.js
|
||||
```
|
||||
|
||||
#### **技术改进详情**
|
||||
- **依赖库完整性**: 确保所有CDN离线文件在正确位置并可被Flask访问
|
||||
- **版本同步更新**: 使用最新版本的ECharts (1MB+) 替换旧版本 (700KB)
|
||||
- **开发体验优化**: 清理重复文件,建立清晰的静态文件组织结构
|
||||
- **系统稳定性**: 解决Excel导出"导出失败,请重试"无具体错误信息的问题
|
||||
|
||||
---
|
||||
|
||||
## 🚀 历史版本 v1.3.6
|
||||
|
||||
### 🔧 多租户告警规则系统实现 (2025-08-26)
|
||||
|
||||
#### **告警规则多租户隔离**
|
||||
- **租户级规则隔离**: 实现告警规则基于 `customer_id` 的完全隔离,不同租户拥有独立的告警规则集
|
||||
- **默认规则自动克隆**: 新建租户时自动从 `customer_id=0` 克隆默认告警规则
|
||||
- **多级告警支持**: 支持同一健康指标配置多个告警级别(如心率120-140中级,140-160高级)
|
||||
- **系统事件匹配**: 告警规则类型与手表系统事件完全匹配,支持直接规则匹配
|
||||
|
||||
#### **告警类型国际化支持**
|
||||
- **英文键值系统**: 告警规则类型使用标准英文格式(如 `HEARTRATE_HIGH_ALERT`)
|
||||
- **中文显示支持**: 通过数据字典实现英文→中文映射,前端显示用户友好的中文
|
||||
- **完整映射体系**: 覆盖15种告警类型的完整中英文映射
|
||||
- **专业化命名**: 与智能手表系统事件命名规范保持一致
|
||||
|
||||
#### **数据库优化**
|
||||
```sql
|
||||
-- 告警规则表新增字段
|
||||
ALTER TABLE t_alert_rules ADD COLUMN customer_id BIGINT;
|
||||
|
||||
-- 支持多级告警的唯一约束
|
||||
ALTER TABLE t_alert_rules ADD UNIQUE KEY uk_alert_multi_level
|
||||
(rule_type, physical_sign, severity_level, customer_id);
|
||||
|
||||
-- 完整的告警类型字典映射
|
||||
INSERT INTO sys_dict_item (dict_code, value, zh_cn, en_us) VALUES
|
||||
('alert_type', 'HEARTRATE_HIGH_ALERT', '心率过高告警', 'HEARTRATE_HIGH_ALERT'),
|
||||
('alert_type', 'SOS_EVENT', 'SOS紧急求助', 'SOS_EVENT');
|
||||
```
|
||||
|
||||
#### **系统架构升级**
|
||||
- **OrgUnitsChangeListener 扩展**: 新建租户时自动触发告警规则克隆
|
||||
- **多租户数据隔离**: 查询、创建、更新、删除操作均基于租户ID过滤
|
||||
- **Redis 缓存优化**: 告警规则缓存键支持租户级别隔离 `alert_rules_{customerId}`
|
||||
- **前端上下文传递**: 管理界面自动传递当前用户的 `customerId`
|
||||
|
||||
---
|
||||
|
||||
## 🚀 历史版本 v1.3.3
|
||||
|
||||
### 🔧 客户部署配置系统修复 (2025-08-20)
|
||||
|
||||
#### **端口配置动态化修复**
|
||||
- **配置文件读取**: `generate-docker-compose.sh` 现在正确读取 `custom-config.env` 配置
|
||||
- **端口配置灵活**: 支持客户完全自定义 MySQL、Redis、大屏等服务端口
|
||||
- **镜像版本同步**: 自动从 `docker-compose.yml` 读取最新镜像版本标签
|
||||
- **环境变量传递**: 确保所有自定义配置正确传递到生成的容器配置中
|
||||
|
||||
#### **修复前后对比**
|
||||
```bash
|
||||
# 修复前: 硬编码默认端口
|
||||
ports:
|
||||
- "3306:3306" # 固定MySQL端口
|
||||
- "8001:8001" # 固定大屏端口
|
||||
|
||||
# 修复后: 动态配置端口
|
||||
ports:
|
||||
- "$MYSQL_PORT:3306" # 从custom-config.env读取
|
||||
- "$BIGSCREEN_PORT:$APP_PORT" # 支持自定义端口映射
|
||||
```
|
||||
|
||||
### 🐳 Docker构建系统优化修复 (2025-08-20)
|
||||
|
||||
#### **ljwx-boot Docker构建修复**
|
||||
- **Maven镜像源优化**: 配置阿里云Maven镜像,解决`No route to host`网络连接问题
|
||||
- **超时配置优化**: 增加Maven连接和读取超时时间,提高构建稳定性
|
||||
- **多阶段构建**: 优化Dockerfile,支持ljwx-boot-starter依赖构建和主应用构建
|
||||
- **网络连接修复**: 解决Docker构建环境中Maven依赖下载失败的问题
|
||||
|
||||
#### **技术改进详情**
|
||||
```dockerfile
|
||||
# 配置Maven阿里云镜像源
|
||||
RUN mkdir -p /root/.m2 && \
|
||||
echo '<settings>...<mirror>...<url>https://maven.aliyun.com/repository/public</url>...' > /root/.m2/settings.xml
|
||||
|
||||
# 增加超时配置
|
||||
RUN mvn clean install -DskipTests -Dmaven.wagon.http.connectTimeout=60000 -Dmaven.wagon.http.readTimeout=120000
|
||||
```
|
||||
|
||||
### 🔧 蓝牙健康数据上传修复 (2025-08-19)
|
||||
|
||||
#### **移动端数据传输优化**
|
||||
- **数据结构简化**: 移除ljwx-phone上传健康数据最外层的data结构,直接传输核心数据
|
||||
- **蓝牙传输稳定性**: 优化BLE数据包格式,提高传输成功率和稳定性
|
||||
- **数据同步效率**: 简化数据封装层次,减少传输开销,提升同步速度
|
||||
- **兼容性增强**: 确保手表端和服务端数据格式完全匹配,避免解析错误
|
||||
|
||||
### 📋 代码分析与文档完善 (2025-08-16)
|
||||
|
||||
#### **完整系统分析**
|
||||
- **深度模块分析**: 完成所有5个模块的详细代码分析
|
||||
- **技术架构文档**: 新增完整的系统功能模块清单文档
|
||||
- **API接口梳理**: 详细整理各模块核心API和功能特性
|
||||
- **性能指标确认**: 验证系统性能数据和技术参数
|
||||
|
||||
#### **技术文档体系**
|
||||
- **[系统功能模块清单](./docs/系统功能模块清单.md)**: 109KB综合技术文档
|
||||
- **模块功能清单**: ljwx-boot、ljwx-admin、ljwx-bigscreen、ljwx-phone、ljwx-watch
|
||||
- **架构设计说明**: 详细的技术栈和系统架构分析
|
||||
- **部署运维指南**: 完整的部署和监控方案
|
||||
|
||||
---
|
||||
|
||||
## 🚀 历史版本 v1.3.2
|
||||
|
||||
### ✨ 告警通知系统完整升级
|
||||
|
||||
#### **多渠道通知**
|
||||
- **企业微信**: 支持企业微信应用消息推送
|
||||
- **公众号微信**: 支持微信公众号模板消息
|
||||
- **系统消息**: 内置消息系统,层级分发通知
|
||||
- **大屏推送**: Critical级别告警实时推送到监控大屏
|
||||
|
||||
#### **智能层级通知**
|
||||
```
|
||||
设备告警事件
|
||||
↓
|
||||
告警规则匹配
|
||||
↓
|
||||
┌─────────────┐
|
||||
│ 通知分发策略 │
|
||||
└─────────────┘
|
||||
↓ ↓ ↓
|
||||
用户通知 部门主管 租户管理员
|
||||
↓ ↓
|
||||
(无主管时) (最终兜底)
|
||||
```
|
||||
|
||||
#### **实时大屏集成**
|
||||
- **WebSocket实时推送**: Socket.IO支持秒级告警推送
|
||||
- **专业告警界面**: 科技感弹窗设计,包含告警详情
|
||||
- **交互功能**: 支持告警确认、音效提醒、ESC关闭
|
||||
- **地图标记**: 可选的告警位置地图标记功能
|
||||
|
||||
### 🛠️ 技术亮点
|
||||
|
||||
- **多架构支持**: Docker支持AMD64/ARM64多架构部署
|
||||
- **性能优化**: 解决N+1查询问题,响应时间从181s优化到<5s
|
||||
- **高并发处理**: QPS >1400,支持2000+设备并发
|
||||
- **容错设计**: 微信通知失败自动降级,确保告警可达性
|
||||
- **智能手表集成**: HarmonyOS原生应用,支持15+小时续航
|
||||
- **二进制协议**: TLV格式数据传输,压缩率达50%
|
||||
- **AI健康分析**: 集成DeepSeek R1模型,智能健康建议
|
||||
|
||||
## 📋 快速开始
|
||||
|
||||
### 环境要求
|
||||
|
||||
| 组件 | 版本要求 | 说明 |
|
||||
|-----|---------|------|
|
||||
| Java | ≥ JDK 21 | 后端运行环境 |
|
||||
| Node.js | ≥ 18.0 | 前端构建环境 |
|
||||
| Python | ≥ 3.8 | 大屏系统环境 |
|
||||
| MySQL | ≥ 8.0 | 数据存储 |
|
||||
| Redis | ≥ 6.0 | 缓存存储 |
|
||||
| Docker | ≥ 20.10 | 容器化部署(可选) |
|
||||
|
||||
### 🐳 快速部署 (推荐)
|
||||
|
||||
```bash
|
||||
# 1. 克隆项目
|
||||
git clone https://github.com/your-org/ljwx-system.git
|
||||
cd ljwx-system
|
||||
|
||||
# 2. 构建所有Docker镜像
|
||||
./build-and-push.sh boot # 构建后端服务
|
||||
./build-and-push.sh admin # 构建前端管理
|
||||
./build-and-push.sh bigscreen # 构建监控大屏
|
||||
|
||||
# 3. 一键启动所有服务
|
||||
docker-compose up -d
|
||||
|
||||
# 4. 初始化数据库
|
||||
mysql -u root -p123456 < client-deployment/client-data.sql
|
||||
|
||||
# 5. 访问系统
|
||||
# 管理后台: http://localhost:3000
|
||||
# 监控大屏: http://localhost:5001
|
||||
# API文档: http://localhost:9998/doc.html
|
||||
```
|
||||
|
||||
### 🔧 Docker构建说明
|
||||
|
||||
系统已优化Docker构建流程,解决了网络连接问题:
|
||||
|
||||
```bash
|
||||
# 单独构建各组件
|
||||
./build-and-push.sh boot # 后端API服务 (Spring Boot)
|
||||
./build-and-push.sh admin # 前端管理系统 (Vue3)
|
||||
./build-and-push.sh bigscreen # 监控大屏系统 (Python Flask)
|
||||
|
||||
# 构建支持多架构 (AMD64/ARM64)
|
||||
# 镜像自动推送到阿里云容器镜像仓库
|
||||
```
|
||||
|
||||
### ⚙️ 客户部署配置
|
||||
|
||||
系统支持完全自定义的端口和服务配置:
|
||||
|
||||
```bash
|
||||
# 修改 custom-config.env 文件
|
||||
BIGSCREEN_PORT=8002 # 自定义大屏端口
|
||||
MYSQL_PORT=3307 # 自定义MySQL端口
|
||||
REDIS_PORT=6380 # 自定义Redis端口
|
||||
VITE_BIGSCREEN_URL=http://192.168.1.10:8002 # 大屏访问地址
|
||||
|
||||
# 生成动态配置并部署
|
||||
./deploy-client.sh custom-config.env
|
||||
```
|
||||
|
||||
**特性**:
|
||||
- 🔄 **动态端口配置**: 根据客户环境自动调整端口映射
|
||||
- 📦 **镜像版本同步**: 自动使用最新的镜像版本标签
|
||||
- 🔧 **环境变量传递**: 完整的配置文件支持
|
||||
- ✅ **向后兼容**: 保持现有部署的稳定性
|
||||
|
||||
### 🔧 开发环境部署
|
||||
|
||||
#### 后端服务
|
||||
```bash
|
||||
cd ljwx-boot
|
||||
./run-local.sh
|
||||
```
|
||||
|
||||
#### 前端管理
|
||||
```bash
|
||||
cd ljwx-admin
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
#### 监控大屏
|
||||
```bash
|
||||
cd ljwx-bigscreen/bigscreen
|
||||
python run_bigscreen.py
|
||||
```
|
||||
|
||||
## 📊 系统展示
|
||||
|
||||
### 管理后台
|
||||
- 健康数据总览、实时设备状态监控
|
||||
- 告警配置管理、用户权限控制
|
||||
- 数据可视化图表、统计分析报表
|
||||
|
||||
### 监控大屏
|
||||
- 实时健康数据地图、告警状态展示
|
||||
- Critical告警弹窗、WebSocket实时推送
|
||||
- 系统性能监控、设备在线状态
|
||||
|
||||
### 移动应用
|
||||
- 个人健康档案、历史数据查询
|
||||
- 设备绑定管理、消息通知中心
|
||||
- 健康评分分析、趋势图表展示
|
||||
|
||||
## 🔧 配置说明
|
||||
|
||||
### 数据库配置
|
||||
```yaml
|
||||
# application.yml
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/test
|
||||
username: root
|
||||
password: 123456
|
||||
```
|
||||
|
||||
### 告警通知配置
|
||||
```python
|
||||
# 企业微信配置
|
||||
WECHAT_CORP_ID = "your_corp_id"
|
||||
WECHAT_AGENT_ID = "your_agent_id"
|
||||
WECHAT_SECRET = "your_secret"
|
||||
|
||||
# 公众号配置
|
||||
WECHAT_APPID = "your_appid"
|
||||
WECHAT_APPSECRET = "your_appsecret"
|
||||
WECHAT_TEMPLATE_ID = "your_template_id"
|
||||
```
|
||||
|
||||
## 📈 性能指标
|
||||
|
||||
- **响应时间**: <3秒 (1000设备规模)
|
||||
- **并发处理**: QPS >1400
|
||||
- **系统可用性**: 99.9%
|
||||
- **告警及时性**: <5秒 (Critical级别)
|
||||
|
||||
## 🔒 安全特性
|
||||
|
||||
- **多租户隔离**: 数据完全隔离,权限严格控制
|
||||
- **API安全**: Sa-Token鉴权,接口权限细化
|
||||
- **数据加密**: 敏感数据AES加密存储
|
||||
- **SQL注入防护**: MyBatis-Plus参数化查询
|
||||
|
||||
## 📚 技术文档
|
||||
|
||||
### 核心文档
|
||||
- **[系统功能模块清单](./docs/系统功能模块清单.md)** - 完整的系统功能和技术架构说明
|
||||
- **[告警通知功能完整实现方案](./docs/告警通知功能完整实现方案.md)** - 告警通知系统技术方案
|
||||
|
||||
### 部署文档
|
||||
- **[系统部署指南](./client-deployment/DEPLOY_GUIDE.md)** - Docker容器化部署
|
||||
- **[离线部署完整指南](./client-deployment/离线部署完整指南.md)** - 离线环境部署
|
||||
|
||||
### 开发文档
|
||||
- **[二次开发文档](./ljwx-bigscreen/docs/二次开发文档.md)** - 大屏系统开发指南
|
||||
- **[技术架构方案文档](./ljwx-bigscreen/docs/技术架构方案文档.md)** - 系统架构设计
|
||||
- **[API接口文档](http://localhost:9998/doc.html)** - 在线API文档
|
||||
|
||||
### 移动端文档
|
||||
- **[数据监控解决方案使用指南](./ljwx-phone/数据监控解决方案使用指南.md)** - 移动端使用说明
|
||||
- **[手表开发和使用指南](./ljwx-watch/手表开发和使用指南.md)** - 智能手表开发指南
|
||||
|
||||
## 🤝 贡献指南
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
|
||||
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||
5. 打开 Pull Request
|
||||
|
||||
## 📄 开源协议
|
||||
|
||||
本项目基于 [Apache License 2.0](./LICENSE) 开源协议,仅供学习参考使用。
|
||||
|
||||
## 👥 联系我们
|
||||
|
||||
- **项目主页**: [GitHub](https://github.com/your-org/ljwx-system)
|
||||
- **问题反馈**: [Issues](https://github.com/your-org/ljwx-system/issues)
|
||||
- **技术支持**: support@ljwx.com
|
||||
|
||||
---
|
||||
|
||||
**© 2024 灵境万象健康管理系统 (LJWX). All rights reserved.**
|
||||
>>>>>>> gitea/main
|
||||
@@ -1,372 +0,0 @@
|
||||
# 本地 Docker Registry 缓存优化指南
|
||||
|
||||
本文档说明如何使用本地 Docker Registry 缓存加速镜像构建和部署。
|
||||
|
||||
## 系统架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ macOS 开发环境 │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ registry-private │ │ registry-cache │ │
|
||||
│ │ localhost:15000 │ │ localhost:15001 │ │
|
||||
│ │ (业务镜像) │ │ (Docker Hub缓存) │ │
|
||||
│ └────────┬─────────┘ └────────┬─────────┘ │
|
||||
│ │ │ │
|
||||
│ 推送业务镜像 自动缓存公共镜像 │
|
||||
│ │ │ │
|
||||
│ ┌────────▼─────────────────────────▼─────────┐ │
|
||||
│ │ OrbStack / Docker Desktop │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 功能特性
|
||||
|
||||
1. **本地私有镜像仓库** (localhost:15000)
|
||||
- 存储业务镜像 (ljwx-*)
|
||||
- 支持推送/拉取
|
||||
- Web UI 管理界面
|
||||
|
||||
2. **Docker Hub 缓存代理** (localhost:15001)
|
||||
- 自动缓存 Docker Hub 公共镜像
|
||||
- 显著加速基础镜像拉取
|
||||
- 第二次拉取秒速完成
|
||||
|
||||
3. **优化构建流程**
|
||||
- 自动检测本地缓存可用性
|
||||
- 统计拉取时间和加速效果
|
||||
- 多架构构建支持
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 安装本地 Registry
|
||||
|
||||
```bash
|
||||
# 进入 registry 工具目录
|
||||
cd ~/work/codes/tools/macos/registery
|
||||
|
||||
# 一键安装本地 Registry
|
||||
./install-local-registry-macos.sh
|
||||
```
|
||||
|
||||
安装完成后将启动 4 个容器:
|
||||
- `registry-private` - 私有镜像仓库 (15000)
|
||||
- `registry-cache` - 缓存代理 (15001)
|
||||
- `registry-ui` - 私有仓库 Web UI (8082)
|
||||
- `registry-cache-ui` - 缓存仓库 Web UI (8083)
|
||||
|
||||
### 2. 验证配置
|
||||
|
||||
```bash
|
||||
# 返回项目目录
|
||||
cd ~/work/codes/shenye/release
|
||||
|
||||
# 运行验证脚本
|
||||
./verify-registry-setup.sh
|
||||
```
|
||||
|
||||
验证脚本将检查:
|
||||
- Docker 服务状态
|
||||
- 私有 Registry 连通性
|
||||
- 缓存 Registry 连通性
|
||||
- Registry 容器状态
|
||||
- 缓存加速效果测试
|
||||
- Web UI 可访问性
|
||||
|
||||
### 3. 预拉取基础镜像
|
||||
|
||||
```bash
|
||||
# 预拉取所有基础镜像到本地缓存
|
||||
./build-and-push.sh cache-pull
|
||||
```
|
||||
|
||||
这将拉取以下基础镜像:
|
||||
- node:18-alpine
|
||||
- nginx:alpine
|
||||
- eclipse-temurin:21-jdk-alpine
|
||||
- eclipse-temurin:21-jre-alpine
|
||||
- python:3.12-slim
|
||||
- mysql:8.0
|
||||
- redis:7-alpine
|
||||
- 监控组件镜像 (grafana, prometheus, loki, etc.)
|
||||
|
||||
第一次拉取会较慢,但会自动缓存到本地。后续构建将极快。
|
||||
|
||||
### 4. 构建镜像
|
||||
|
||||
```bash
|
||||
# 构建所有镜像
|
||||
./build-and-push.sh all
|
||||
|
||||
# 或者单独构建
|
||||
./build-and-push.sh boot # 后端服务
|
||||
./build-and-push.sh admin # 前端管理
|
||||
./build-and-push.sh bigscreen # 大屏展示
|
||||
./build-and-push.sh mysql redis # 数据库
|
||||
```
|
||||
|
||||
## 访问地址
|
||||
|
||||
| 服务 | 地址 | 说明 |
|
||||
|------|------|------|
|
||||
| 私有仓库 API | http://localhost:15000 | 推送/拉取业务镜像 |
|
||||
| 缓存仓库 API | http://localhost:15001 | Docker Hub 缓存代理 |
|
||||
| 私有仓库 UI | http://localhost:8082 | 可视化管理业务镜像 |
|
||||
| 缓存仓库 UI | http://localhost:8083 | 查看缓存的公共镜像 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 推送自定义镜像
|
||||
|
||||
```bash
|
||||
# 构建镜像
|
||||
docker build -t localhost:15000/ljwx/myapp:v1.0.0 .
|
||||
|
||||
# 推送到私有仓库
|
||||
docker push localhost:15000/ljwx/myapp:v1.0.0
|
||||
|
||||
# 验证推送成功
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
```
|
||||
|
||||
### 拉取镜像
|
||||
|
||||
```bash
|
||||
# 从私有仓库拉取业务镜像
|
||||
docker pull localhost:15000/ljwx/ljwx-boot:1.2.16
|
||||
|
||||
# 从缓存拉取公共镜像(自动使用缓存)
|
||||
docker pull nginx:alpine # 第二次会很快
|
||||
```
|
||||
|
||||
### 查看镜像列表
|
||||
|
||||
```bash
|
||||
# 通过 API 查询私有镜像
|
||||
curl http://localhost:15000/v2/_catalog | jq .
|
||||
|
||||
# 查询特定镜像的 tags
|
||||
curl http://localhost:15000/v2/ljwx/ljwx-boot/tags/list | jq .
|
||||
|
||||
# 查看缓存的镜像
|
||||
curl http://localhost:15001/v2/_catalog | jq .
|
||||
```
|
||||
|
||||
## 高级配置
|
||||
|
||||
### 环境变量
|
||||
|
||||
```bash
|
||||
# 禁用本地缓存(使用外部镜像源)
|
||||
CACHE_REGISTRY_ENABLED=false ./build-and-push.sh all
|
||||
|
||||
# 使用自定义 Registry 地址
|
||||
PRIVATE_REGISTRY_HOST=registry.company.com:5000 ./build-and-push.sh boot
|
||||
|
||||
# 本地单架构构建(更快)
|
||||
LOCAL_BUILD=true PLATFORMS=linux/amd64 ./build-and-push.sh boot
|
||||
```
|
||||
|
||||
### 配置 Docker daemon
|
||||
|
||||
如果需要全局配置 Docker 使用本地缓存:
|
||||
|
||||
```bash
|
||||
# 运行配置脚本
|
||||
./configure-cache-registry.sh
|
||||
```
|
||||
|
||||
这将修改 `~/.orbstack/config/docker.json` 并添加:
|
||||
- registry-mirrors: 指向本地缓存
|
||||
- insecure-registries: 允许 HTTP 连接
|
||||
|
||||
## 性能对比
|
||||
|
||||
### 未使用缓存
|
||||
|
||||
```
|
||||
拉取 eclipse-temurin:21-jdk-alpine: 45s
|
||||
拉取 node:18-alpine: 30s
|
||||
拉取 mysql:8.0: 120s
|
||||
总计: ~195s
|
||||
```
|
||||
|
||||
### 使用本地缓存(第二次)
|
||||
|
||||
```
|
||||
拉取 eclipse-temurin:21-jdk-alpine: 2s (22.5x)
|
||||
拉取 node:18-alpine: 1s (30x)
|
||||
拉取 mysql:8.0: 5s (24x)
|
||||
总计: ~8s (24.4x 加速)
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 1. 端口被占用
|
||||
|
||||
**错误**: `Bind for 0.0.0.0:15000 failed: port is already allocated`
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 停止旧容器
|
||||
docker stop registry-private registry-cache
|
||||
|
||||
# 重新运行安装脚本
|
||||
cd ~/work/codes/tools/macos/registery
|
||||
./install-local-registry-macos.sh
|
||||
```
|
||||
|
||||
### 2. 缓存不生效
|
||||
|
||||
**原因**: Docker daemon 配置未生效
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 运行配置脚本
|
||||
./configure-cache-registry.sh
|
||||
|
||||
# 重启 Docker/OrbStack
|
||||
```
|
||||
|
||||
### 3. 镜像推送失败
|
||||
|
||||
**错误**: `denied: requested access to the resource is denied`
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 检查私有 Registry 是否运行
|
||||
curl http://localhost:15000/v2/_catalog
|
||||
|
||||
# 如果未运行,启动服务
|
||||
cd ~/work/codes/tools/macos/registery
|
||||
./install-local-registry-macos.sh
|
||||
```
|
||||
|
||||
### 4. Web UI 无法访问
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 检查 UI 容器状态
|
||||
docker ps --filter "name=registry-ui"
|
||||
|
||||
# 查看日志
|
||||
docker logs registry-ui --tail 20
|
||||
|
||||
# 重启 UI 容器
|
||||
docker restart registry-ui registry-cache-ui
|
||||
```
|
||||
|
||||
## 维护操作
|
||||
|
||||
### 查看容器状态
|
||||
|
||||
```bash
|
||||
docker ps --filter "name=registry"
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# 私有仓库日志
|
||||
docker logs registry-private --tail 50
|
||||
|
||||
# 缓存仓库日志
|
||||
docker logs registry-cache --tail 50
|
||||
```
|
||||
|
||||
### 重启服务
|
||||
|
||||
```bash
|
||||
# 重启所有 Registry 容器
|
||||
docker restart registry-private registry-cache registry-ui registry-cache-ui
|
||||
```
|
||||
|
||||
### 清理缓存
|
||||
|
||||
```bash
|
||||
# 清理构建缓存
|
||||
./build-and-push.sh cache-clean
|
||||
|
||||
# 清理未使用的镜像
|
||||
./build-and-push.sh cache-prune
|
||||
|
||||
# 清理缓存仓库数据
|
||||
docker stop registry-cache
|
||||
rm -rf ~/registry/cache/data/*
|
||||
docker start registry-cache
|
||||
```
|
||||
|
||||
### 备份数据
|
||||
|
||||
```bash
|
||||
# 备份私有镜像数据
|
||||
tar -czf ~/registry-backup-$(date +%Y%m%d).tar.gz ~/registry/private/data
|
||||
|
||||
# 恢复数据
|
||||
docker stop registry-private
|
||||
tar -xzf ~/registry-backup-20250126.tar.gz -C ~/
|
||||
docker start registry-private
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 1. 定期更新基础镜像缓存
|
||||
|
||||
```bash
|
||||
# 每周运行一次,更新缓存
|
||||
./build-and-push.sh cache-pull
|
||||
```
|
||||
|
||||
### 2. 镜像命名规范
|
||||
|
||||
```bash
|
||||
# 推荐格式
|
||||
localhost:15000/ljwx/<component>:<version>
|
||||
|
||||
# 示例
|
||||
localhost:15000/ljwx/ljwx-boot:1.2.16
|
||||
localhost:15000/ljwx/ljwx-admin:20250126
|
||||
localhost:15000/ljwx/ljwx-bigscreen:abc123def
|
||||
```
|
||||
|
||||
### 3. 监控磁盘使用
|
||||
|
||||
```bash
|
||||
# 查看数据目录大小
|
||||
du -sh ~/registry/private/data
|
||||
du -sh ~/registry/cache/data
|
||||
|
||||
# 设置告警阈值 (>10GB)
|
||||
```
|
||||
|
||||
### 4. 定期备份
|
||||
|
||||
```bash
|
||||
# 添加到 crontab 每日备份
|
||||
crontab -e
|
||||
|
||||
# 添加以下行(每天凌晨 2 点)
|
||||
0 2 * * * tar -czf ~/backups/registry-$(date +\%Y\%m\%d).tar.gz ~/registry/private/data
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [本地 Registry 安装文档](../../tools/macos/registery/README-MACOS.md)
|
||||
- [构建脚本使用说明](./build-and-push.sh) - 运行不带参数查看帮助
|
||||
- [监控版本配置](./monitoring-versions.env)
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题,请:
|
||||
1. 运行 `./verify-registry-setup.sh` 检查配置
|
||||
2. 查看容器日志: `docker logs registry-private`
|
||||
3. 检查端口占用: `lsof -i :15000`
|
||||
4. 参考完整文档: [DEV-REGISTRY-SETUP.md](../../tools/macos/registery/DEV-REGISTRY-SETUP.md)
|
||||
|
||||
---
|
||||
|
||||
**版本**: v1.4.0
|
||||
**更新时间**: 2025-11-26
|
||||
**适用环境**: macOS + OrbStack/Docker Desktop
|
||||
@@ -1,228 +0,0 @@
|
||||
# SysOrgClosureService 为什么需要 customerId 参数分析
|
||||
|
||||
## 🔍 核心问题分析
|
||||
|
||||
你提出了一个很重要的架构设计问题:为什么 `SysOrgClosureService.findAllDescendants` 需要 `customerId` 作为入参,不能仅凭 `orgId` 查询?
|
||||
|
||||
## 📊 数据库表结构分析
|
||||
|
||||
### sys_org_closure 表结构
|
||||
```sql
|
||||
CREATE TABLE `sys_org_closure` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`ancestor_id` BIGINT NOT NULL COMMENT '祖先节点ID',
|
||||
`descendant_id` BIGINT NOT NULL COMMENT '后代节点ID',
|
||||
`depth` INT NOT NULL DEFAULT 0 COMMENT '层级深度',
|
||||
`customer_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户ID', -- ⚠️ 关键字段
|
||||
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_closure_ancestor_descendant` (`ancestor_id`, `descendant_id`, `customer_id`), -- ⚠️ 包含租户ID
|
||||
KEY `idx_closure_ancestor` (`ancestor_id`, `customer_id`), -- ⚠️ 联合索引
|
||||
KEY `idx_closure_descendant` (`descendant_id`, `customer_id`) -- ⚠️ 联合索引
|
||||
);
|
||||
```
|
||||
|
||||
### 关键发现
|
||||
1. **唯一约束包含租户ID**: `uk_closure_ancestor_descendant` 索引包含了 `customer_id`
|
||||
2. **所有索引都包含租户ID**: 所有查询索引都设计为租户隔离
|
||||
3. **数据隔离设计**: 相同的 `ancestor_id` 和 `descendant_id` 在不同租户中可以存在
|
||||
|
||||
## 🏢 多租户架构的必要性
|
||||
|
||||
### 1. 租户数据隔离
|
||||
```sql
|
||||
-- 优化后的查询SQL
|
||||
SELECT org.*
|
||||
FROM sys_org_closure c
|
||||
INNER JOIN sys_org_units org ON c.descendant_id = org.id
|
||||
WHERE c.ancestor_id = #{ancestorId}
|
||||
AND c.customer_id = #{customerId} -- ⚠️ 租户隔离的关键
|
||||
AND c.depth > 0
|
||||
```
|
||||
|
||||
**为什么必要?**
|
||||
- **数据安全**: 防止租户A查询到租户B的组织结构
|
||||
- **业务隔离**: 不同租户的组织ID可能重复
|
||||
- **性能优化**: 索引设计基于租户隔离,查询效率更高
|
||||
|
||||
### 2. 组织ID重复问题
|
||||
|
||||
#### 场景示例
|
||||
```sql
|
||||
-- 可能的数据情况
|
||||
sys_org_closure 表数据:
|
||||
| ancestor_id | descendant_id | depth | customer_id |
|
||||
|------------|---------------|-------|-------------|
|
||||
| 1000 | 1001 | 1 | 100 | -- 租户A的组织关系
|
||||
| 1000 | 1002 | 1 | 100 | -- 租户A的组织关系
|
||||
| 1000 | 1001 | 1 | 200 | -- 租户B的组织关系 (相同的org_id!)
|
||||
| 1000 | 1003 | 1 | 200 | -- 租户B的组织关系
|
||||
```
|
||||
|
||||
**如果只用 orgId 查询会发生什么?**
|
||||
```sql
|
||||
-- 🚫 错误查询 (没有租户隔离)
|
||||
SELECT org.* FROM sys_org_closure c
|
||||
INNER JOIN sys_org_units org ON c.descendant_id = org.id
|
||||
WHERE c.ancestor_id = 1000; -- 会返回所有租户的数据!
|
||||
|
||||
-- 结果: 租户A会看到租户B的组织数据 - 严重的安全问题!
|
||||
```
|
||||
|
||||
## 🔧 技术架构考虑
|
||||
|
||||
### 1. 索引性能优化
|
||||
```sql
|
||||
-- 当前的索引设计
|
||||
KEY `idx_closure_ancestor` (`ancestor_id`, `customer_id`)
|
||||
```
|
||||
|
||||
**分析**:
|
||||
- 联合索引 `(ancestor_id, customer_id)` 比单独的 `ancestor_id` 索引更高效
|
||||
- 查询时同时过滤租户ID,减少了扫描的数据量
|
||||
- 利用索引覆盖优化,避免回表查询
|
||||
|
||||
### 2. 数据库分区策略
|
||||
```sql
|
||||
-- 闭包表可能按 customer_id 进行分区
|
||||
PARTITION BY HASH(customer_id) PARTITIONS 10;
|
||||
```
|
||||
|
||||
**优势**:
|
||||
- 每个租户的数据物理隔离
|
||||
- 查询时只需访问特定分区
|
||||
- 提高并发性能和数据安全性
|
||||
|
||||
## 💡 替代方案分析
|
||||
|
||||
### 方案1: 仅使用 orgId 查询
|
||||
```java
|
||||
// 假设的实现
|
||||
List<SysOrgUnits> findAllDescendants(Long orgId) {
|
||||
// 问题: 如何确定该 orgId 属于哪个租户?
|
||||
// 需要额外查询 sys_org_units 表获取 customer_id
|
||||
return sysOrgClosureMapper.findByOrgIdOnly(orgId);
|
||||
}
|
||||
```
|
||||
|
||||
**问题**:
|
||||
1. **额外查询开销**: 需要先查 `sys_org_units` 获取 `customer_id`
|
||||
2. **安全风险**: 无法保证查询的 `orgId` 属于当前用户的租户
|
||||
3. **索引效率低**: 无法利用 `(ancestor_id, customer_id)` 联合索引
|
||||
4. **缓存复杂性**: 缓存键无法区分不同租户的相同orgId
|
||||
|
||||
### 方案2: 从 orgId 推导 customerId
|
||||
```java
|
||||
// 理论上的实现
|
||||
List<SysOrgUnits> findAllDescendants(Long orgId) {
|
||||
// 1. 先查询获取 customerId
|
||||
Long customerId = sysOrgUnitsMapper.getCustomerIdByOrgId(orgId);
|
||||
// 2. 再执行闭包查询
|
||||
return sysOrgClosureMapper.findAllDescendants(orgId, customerId);
|
||||
}
|
||||
```
|
||||
|
||||
**问题**:
|
||||
1. **N+1 查询问题**: 每次都需要额外查询获取 `customerId`
|
||||
2. **性能下降**: 两次数据库访问 vs 一次访问
|
||||
3. **一致性风险**: 两次查询之间数据可能发生变化
|
||||
4. **权限检查复杂**: 需要额外验证用户是否有权访问该 orgId
|
||||
|
||||
## 🎯 当前设计的优势
|
||||
|
||||
### 1. 性能优势
|
||||
```java
|
||||
@Cacheable(value = CACHE_NAME, key = "'all_descendants_' + #ancestorId + '_' + #customerId")
|
||||
public List<SysOrgUnits> findAllDescendants(Long ancestorId, Long customerId) {
|
||||
// 直接使用联合索引,一次查询完成
|
||||
return sysOrgClosureMapper.findAllDescendants(ancestorId, customerId);
|
||||
}
|
||||
```
|
||||
|
||||
**优势**:
|
||||
- **单次查询**: 避免了额外的 `customerId` 查询
|
||||
- **索引优化**: 充分利用 `(ancestor_id, customer_id)` 联合索引
|
||||
- **缓存精确**: 缓存键区分了不同租户,避免数据混乱
|
||||
|
||||
### 2. 安全优势
|
||||
```java
|
||||
// 调用方必须明确提供租户信息
|
||||
List<SysUser> users = sysUserService.getUsersByOrgId(orgId, customerId);
|
||||
```
|
||||
|
||||
**优势**:
|
||||
- **显式租户控制**: 调用方必须明确指定租户,防止越权访问
|
||||
- **权限边界清晰**: 在接口层面就确保了租户隔离
|
||||
- **审计友好**: 日志中可以清楚看到租户信息
|
||||
|
||||
### 3. 业务逻辑清晰
|
||||
```java
|
||||
public Result<SysUserMapVO> getUsersByOrgId(
|
||||
@RequestParam String orgId,
|
||||
@RequestParam Long customerId) { // 明确要求前端传递租户ID
|
||||
// 业务逻辑清晰:在指定租户下查询指定组织的用户
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 设计决策总结
|
||||
|
||||
### 为什么需要 customerId 参数?
|
||||
|
||||
1. **数据安全第一**: 防止跨租户数据泄露
|
||||
2. **性能最优**: 利用联合索引,避免额外查询
|
||||
3. **架构一致性**: 所有多租户接口都遵循相同模式
|
||||
4. **业务清晰**: 调用方明确知道在操作哪个租户的数据
|
||||
|
||||
### 替代方案的成本
|
||||
|
||||
| 方案 | 查询次数 | 安全性 | 性能 | 复杂度 |
|
||||
|------|----------|--------|------|--------|
|
||||
| 当前方案 (需要customerId) | 1次 | 高 | 优 | 低 |
|
||||
| 仅orgId查询 | 2次 | 低 | 差 | 高 |
|
||||
| 推导customerId | 2次 | 中 | 差 | 中 |
|
||||
|
||||
## 🔮 架构建议
|
||||
|
||||
### 短期保持当前设计
|
||||
当前的设计是正确的,因为:
|
||||
- 符合多租户架构最佳实践
|
||||
- 性能和安全性都达到最优
|
||||
- 代码逻辑清晰,维护成本低
|
||||
|
||||
### 可能的优化方向
|
||||
如果确实想简化调用,可以考虑:
|
||||
|
||||
```java
|
||||
// 在上下文中获取当前用户的租户信息
|
||||
@Component
|
||||
public class TenantContextHolder {
|
||||
private static final ThreadLocal<Long> CURRENT_CUSTOMER_ID = new ThreadLocal<>();
|
||||
|
||||
public static Long getCurrentCustomerId() {
|
||||
return CURRENT_CUSTOMER_ID.get();
|
||||
}
|
||||
}
|
||||
|
||||
// 提供重载方法
|
||||
public List<SysOrgUnits> findAllDescendants(Long ancestorId) {
|
||||
Long customerId = TenantContextHolder.getCurrentCustomerId();
|
||||
if (customerId == null) {
|
||||
throw new BizException("无法获取当前租户信息");
|
||||
}
|
||||
return findAllDescendants(ancestorId, customerId);
|
||||
}
|
||||
```
|
||||
|
||||
但这种方式增加了复杂性,当前的显式传参方式更安全可靠。
|
||||
|
||||
## 🎉 结论
|
||||
|
||||
`SysOrgClosureService.findAllDescendants` 需要 `customerId` 参数是**必要且正确的设计决策**,主要原因:
|
||||
|
||||
1. **多租户数据隔离**是系统安全的基本要求
|
||||
2. **性能优化**需要利用包含租户ID的联合索引
|
||||
3. **业务清晰性**要求调用方明确指定操作范围
|
||||
4. **架构一致性**保证所有多租户接口的统一性
|
||||
|
||||
这个设计虽然增加了一个参数,但换来了更好的安全性、性能和维护性,是值得的架构权衡。
|
||||
@@ -1,170 +0,0 @@
|
||||
# upload_health_data 数据插入失败问题修复报告
|
||||
|
||||
## 🎯 问题概述
|
||||
|
||||
**问题现象**: ljwx-bigscreen 的 `upload_health_data` 接口返回成功状态,但健康数据无法插入到 `t_user_health_data` 表中。
|
||||
|
||||
**触发背景**: 今天的代码修改将 `customer_id` 从固定值 `0` 改为实际的客户ID值(如 `1939964806110937090`)后,数据插入功能完全失效。
|
||||
|
||||
## 🔍 问题根因分析
|
||||
|
||||
通过详细的调试和日志分析,发现了两个核心问题:
|
||||
|
||||
### 1. upload_method 字段类型限制
|
||||
```sql
|
||||
-- 数据库表结构
|
||||
upload_method ENUM('wifi','bluetooth','common_event') NOT NULL DEFAULT 'wifi'
|
||||
|
||||
-- 实际数据
|
||||
"upload_method": "4g" -- ❌ 不在允许的枚举值中
|
||||
```
|
||||
|
||||
**错误信息**: `Data truncated for column 'upload_method' at row 1`
|
||||
|
||||
### 2. SQL占位符数量不匹配
|
||||
```sql
|
||||
-- SQL语句字段 (20个字段)
|
||||
INSERT INTO t_user_health_data
|
||||
(device_sn, user_id, org_id, customer_id, heart_rate, blood_oxygen, temperature,
|
||||
pressure_high, pressure_low, stress, step, distance, calorie,
|
||||
latitude, longitude, altitude, sleep, timestamp, upload_method, create_time)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
|
||||
↑ 只有18个%s占位符,但需要19个参数(除create_time外)
|
||||
```
|
||||
|
||||
**错误信息**: `TypeError: not all arguments converted during string formatting`
|
||||
|
||||
## ✅ 修复方案实施
|
||||
|
||||
### 1. 数据库表结构修改
|
||||
```sql
|
||||
-- 修改 upload_method 字段,添加 esim 支持
|
||||
ALTER TABLE t_user_health_data
|
||||
MODIFY COLUMN upload_method ENUM('wifi','bluetooth','common_event','esim') NOT NULL DEFAULT 'wifi';
|
||||
```
|
||||
|
||||
### 2. 代码逻辑修复
|
||||
|
||||
#### A. 添加 upload_method 值映射
|
||||
```python
|
||||
# 处理upload_method字段,将4g映射为esim
|
||||
upload_method = raw_data.get("upload_method", "wifi")
|
||||
if upload_method == "4g":
|
||||
upload_method = "esim"
|
||||
```
|
||||
|
||||
#### B. 修复SQL占位符数量
|
||||
```python
|
||||
# 修复前(缺少customer_id)
|
||||
insert_sql = """
|
||||
INSERT INTO t_user_health_data
|
||||
(device_sn, user_id, org_id, heart_rate, blood_oxygen, temperature,
|
||||
pressure_high, pressure_low, stress, step, distance, calorie,
|
||||
latitude, longitude, altitude, sleep, timestamp, upload_method, create_time)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
|
||||
"""
|
||||
|
||||
# 修复后(添加customer_id字段和占位符)
|
||||
insert_sql = """
|
||||
INSERT INTO t_user_health_data
|
||||
(device_sn, user_id, org_id, customer_id, heart_rate, blood_oxygen, temperature,
|
||||
pressure_high, pressure_low, stress, step, distance, calorie,
|
||||
latitude, longitude, altitude, sleep, timestamp, upload_method, create_time)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
|
||||
"""
|
||||
```
|
||||
|
||||
#### C. 增强错误处理
|
||||
```python
|
||||
# 添加批量插入失败时的fallback机制
|
||||
try:
|
||||
# 批量插入
|
||||
for record in main_records:
|
||||
cursor.execute(insert_sql, params)
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
# 单条插入处理重复记录
|
||||
for record in main_records:
|
||||
# 检查重复
|
||||
existing = cursor.execute("SELECT id FROM t_user_health_data WHERE device_sn = %s AND timestamp = %s")
|
||||
if not existing:
|
||||
cursor.execute(insert_sql, params)
|
||||
```
|
||||
|
||||
### 3. 调试信息完善
|
||||
```python
|
||||
print(f"✅ 批处理器和定时清理已启动,队列状态: empty={self.batch_queue.empty()}")
|
||||
print(f"📦 批处理器收到数据项: device_sn={item.get('device_sn')}")
|
||||
print(f"❌ 主表批量插入失败详细错误: {str(e)}")
|
||||
```
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
### 测试数据
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"deviceSn": "CRFTQ23409001894",
|
||||
"customerId": 1939964806110937090,
|
||||
"orgId": 1939964806110937090,
|
||||
"userId": "1940034481851260929",
|
||||
"heart_rate": 82,
|
||||
"upload_method": "4g",
|
||||
"timestamp": "2025-09-02 16:09:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 验证结果
|
||||
```sql
|
||||
-- 数据库查询结果
|
||||
SELECT device_sn, heart_rate, upload_method, customer_id, create_time
|
||||
FROM t_user_health_data
|
||||
WHERE device_sn = 'CRFTQ23409001894';
|
||||
|
||||
-- 结果
|
||||
device_sn: CRFTQ23409001894
|
||||
heart_rate: 82
|
||||
upload_method: esim -- ✅ 4g正确映射为esim
|
||||
customer_id: 1939964806110937090 -- ✅ 实际customer_id值
|
||||
create_time: 2025-09-12 21:27:46 -- ✅ 成功插入
|
||||
```
|
||||
|
||||
## 📊 修复效果
|
||||
|
||||
### ✅ 成功指标
|
||||
- **数据插入成功率**: 0% → 100%
|
||||
- **upload_method映射**: 4g → esim 正确映射
|
||||
- **customer_id处理**: 支持实际ID值而非固定0值
|
||||
- **错误处理**: 完善的fallback机制和详细日志
|
||||
|
||||
### 🔧 技术改进
|
||||
1. **健壮性提升**: 添加批量插入失败时的单条插入fallback
|
||||
2. **数据兼容性**: 支持多种upload_method值的映射
|
||||
3. **调试能力**: 详细的错误日志和处理过程跟踪
|
||||
4. **重复处理**: 完善的重复数据检测和跳过机制
|
||||
|
||||
## 📁 影响文件
|
||||
|
||||
- `ljwx-bigscreen/bigscreen/bigScreen/health_data_batch_processor.py`
|
||||
- 数据库表: `t_user_health_data` (字段类型修改)
|
||||
|
||||
## 🚀 部署说明
|
||||
|
||||
1. **数据库变更**: 已通过Python脚本自动执行表结构修改
|
||||
2. **应用代码**: 已提交到Git (commit: bff1e6a)
|
||||
3. **重启要求**: 需要重启ljwx-bigscreen应用以加载新代码
|
||||
|
||||
## 🎉 结论
|
||||
|
||||
问题已**完全修复**!upload_health_data功能恢复正常,支持:
|
||||
- ✅ 实际customer_id值的数据插入
|
||||
- ✅ 4g/esim上传方式的数据处理
|
||||
- ✅ 完善的错误处理和重复数据检测
|
||||
- ✅ 详细的调试日志和监控能力
|
||||
|
||||
---
|
||||
**修复时间**: 2025-09-12 21:30
|
||||
**修复状态**: ✅ 完成
|
||||
**验证状态**: ✅ 通过
|
||||
@@ -1,217 +0,0 @@
|
||||
# LJWX v2.0 文件清单
|
||||
|
||||
## ✅ 已创建的文件
|
||||
|
||||
### 核心配置文件
|
||||
- [x] `.env.unified` - 统一配置模板
|
||||
- [x] `.env` - 实际配置文件(已添加v2配置)
|
||||
|
||||
### 核心脚本
|
||||
- [x] `build-and-push-v2.sh` - v2构建脚本(可执行)
|
||||
- [x] `db-migrate.sh` - 数据库迁移工具(可执行)
|
||||
- [x] `verify-setup.sh` - 环境验证脚本(可执行)
|
||||
|
||||
### Docker配置
|
||||
- [x] `docker-compose.prod.v2.yml` - v2版本Compose文件
|
||||
|
||||
### 数据库迁移
|
||||
- [x] `docker/mysql/migrations/README.md` - 迁移文档(详细说明)
|
||||
- [x] `docker/mysql/migrations/` - 迁移脚本目录
|
||||
- [x] `docker/mysql/migrations/rollback/` - 回滚脚本目录
|
||||
|
||||
### 文档
|
||||
- [x] `DEPLOYMENT-GUIDE-V2.md` - 完整部署指南(~2000行)
|
||||
- [x] `QUICK-START-V2.md` - 快速开始指南(~400行)
|
||||
- [x] `V2-MIGRATION-SUMMARY.md` - v2重构总结
|
||||
- [x] `V2-FILES-CHECKLIST.md` - 本文件
|
||||
|
||||
## 📋 快速验证
|
||||
|
||||
```bash
|
||||
# 1. 检查所有文件是否存在
|
||||
ls -la .env.unified
|
||||
ls -la .env
|
||||
ls -la docker-compose.prod.v2.yml
|
||||
ls -la build-and-push-v2.sh
|
||||
ls -la db-migrate.sh
|
||||
ls -la verify-setup.sh
|
||||
ls -la DEPLOYMENT-GUIDE-V2.md
|
||||
ls -la QUICK-START-V2.md
|
||||
ls -la V2-MIGRATION-SUMMARY.md
|
||||
ls -la docker/mysql/migrations/README.md
|
||||
|
||||
# 2. 检查脚本权限
|
||||
ls -l *.sh
|
||||
|
||||
# 3. 运行环境验证
|
||||
./verify-setup.sh
|
||||
```
|
||||
|
||||
## 🚀 下一步操作
|
||||
|
||||
### 1. 阅读文档
|
||||
```bash
|
||||
# 快速上手(5分钟)
|
||||
cat QUICK-START-V2.md
|
||||
|
||||
# 完整指南(详细了解)
|
||||
cat DEPLOYMENT-GUIDE-V2.md
|
||||
|
||||
# 迁移文档
|
||||
cat docker/mysql/migrations/README.md
|
||||
```
|
||||
|
||||
### 2. 配置环境
|
||||
```bash
|
||||
# 如果还没有创建.env
|
||||
cp .env.unified .env
|
||||
|
||||
# 编辑配置
|
||||
vim .env
|
||||
|
||||
# 验证配置
|
||||
./verify-setup.sh
|
||||
```
|
||||
|
||||
### 3. 首次部署
|
||||
```bash
|
||||
# 方式1: 一键部署
|
||||
./build-and-push-v2.sh -e -a
|
||||
|
||||
# 方式2: 分步部署(推荐)
|
||||
./build-and-push-v2.sh -e # 导出数据库
|
||||
./build-and-push-v2.sh -b # 构建镜像
|
||||
./build-and-push-v2.sh -p # 推送镜像
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
```
|
||||
|
||||
## 📖 文件说明
|
||||
|
||||
### .env.unified(配置模板)
|
||||
- 包含所有可配置项的模板
|
||||
- 包含详细的配置说明
|
||||
- 使用时复制为.env并修改
|
||||
|
||||
### build-and-push-v2.sh(核心构建脚本)
|
||||
功能:
|
||||
- `-b` 构建镜像
|
||||
- `-p` 推送镜像
|
||||
- `-d` 部署服务
|
||||
- `-a` 全部执行
|
||||
- `-c <组件>` 指定组件
|
||||
- `-e` 导出数据库
|
||||
- `-m` 应用迁移
|
||||
|
||||
特性:
|
||||
- 从.env读取所有配置
|
||||
- 支持单组件操作
|
||||
- 完整的日志记录
|
||||
- 错误处理和恢复
|
||||
|
||||
### db-migrate.sh(数据库迁移工具)
|
||||
功能:
|
||||
- `export` 导出数据库基线
|
||||
- `create` 创建迁移脚本
|
||||
- `apply` 应用迁移
|
||||
- `apply-all` 应用所有待执行迁移
|
||||
- `status` 查看迁移状态
|
||||
- `rollback` 回滚迁移
|
||||
|
||||
特性:
|
||||
- 版本化管理
|
||||
- 自动历史追踪
|
||||
- 支持幂等性
|
||||
- 自动备份
|
||||
|
||||
### docker-compose.prod.v2.yml(Compose配置)
|
||||
特性:
|
||||
- 全部使用环境变量
|
||||
- 无硬编码值
|
||||
- 支持健康检查
|
||||
- 依赖关系管理
|
||||
|
||||
### 文档文件说明
|
||||
|
||||
| 文件 | 页数 | 内容 | 适用场景 |
|
||||
|------|------|------|----------|
|
||||
| QUICK-START-V2.md | ~10页 | 快速开始、常用命令 | 快速上手 |
|
||||
| DEPLOYMENT-GUIDE-V2.md | ~50页 | 完整指南、最佳实践 | 深入学习 |
|
||||
| V2-MIGRATION-SUMMARY.md | ~10页 | v1迁移到v2、改进对比 | 了解改进 |
|
||||
| docker/mysql/migrations/README.md | ~15页 | 数据库迁移详解 | 数据库管理 |
|
||||
|
||||
## 🎯 核心改进
|
||||
|
||||
### 1. 配置统一化
|
||||
- **Before**: monitoring-versions.env + docker-compose硬编码
|
||||
- **After**: 单一.env文件
|
||||
|
||||
### 2. 脚本灵活化
|
||||
- **Before**: 一体化执行
|
||||
- **After**: 支持-b/-p/-d/-a分阶段
|
||||
|
||||
### 3. 数据库版本化
|
||||
- **Before**: 手动导出data.sql
|
||||
- **After**: 版本化迁移脚本 + 自动追踪
|
||||
|
||||
## ✨ 使用建议
|
||||
|
||||
### 开发环境
|
||||
```bash
|
||||
# 快速迭代
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
./build-and-push-v2.sh -p -c ljwx-boot
|
||||
docker-compose restart ljwx-boot
|
||||
```
|
||||
|
||||
### 生产环境
|
||||
```bash
|
||||
# 分步部署
|
||||
./db-migrate.sh export # 备份数据库
|
||||
./build-and-push-v2.sh -b # 构建镜像
|
||||
./build-and-push-v2.sh -p # 推送Registry
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
```
|
||||
|
||||
### 数据库升级
|
||||
```bash
|
||||
./db-migrate.sh create 2.0.4 add_features
|
||||
vim docker/mysql/migrations/V2.0.4__add_features.sql
|
||||
./db-migrate.sh apply 2.0.4
|
||||
./build-and-push-v2.sh -b -c ljwx-mysql
|
||||
```
|
||||
|
||||
## 🔗 相关链接
|
||||
|
||||
- 项目主README: `README.md`
|
||||
- v1构建脚本: `build-and-push.sh`(保留)
|
||||
- v1 Compose: `docker-compose.prod.yml`(保留)
|
||||
- 监控配置: `monitoring-versions.env`(保留)
|
||||
|
||||
## 📊 完成度
|
||||
|
||||
- ✅ 配置管理: 100%
|
||||
- ✅ 构建脚本: 100%
|
||||
- ✅ 数据库迁移: 100%
|
||||
- ✅ Docker配置: 100%
|
||||
- ✅ 文档完整性: 100%
|
||||
- ✅ 测试验证: 100%
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
v2.0重构已100%完成!
|
||||
|
||||
**核心成果**:
|
||||
1. ✅ 单一配置源(.env)
|
||||
2. ✅ 灵活构建脚本(支持分阶段)
|
||||
3. ✅ 数据库版本管理(迁移+回滚)
|
||||
4. ✅ 完整文档体系
|
||||
5. ✅ 自动化工具链
|
||||
|
||||
**立即开始**:
|
||||
```bash
|
||||
./verify-setup.sh # 验证环境
|
||||
cat QUICK-START-V2.md # 阅读快速指南
|
||||
./build-and-push-v2.sh -e -a # 一键部署
|
||||
```
|
||||
|
||||
祝使用愉快!🚀
|
||||
@@ -1,424 +0,0 @@
|
||||
# LJWX v2.0 重构方案总结
|
||||
|
||||
## 📋 概览
|
||||
|
||||
本次重构完美解决了您提出的三个核心问题:
|
||||
|
||||
### ✅ 问题1: 配置管理统一化
|
||||
|
||||
**改进前**:
|
||||
- `monitoring-versions.env` - 版本配置
|
||||
- `docker-compose.prod.yml` - 硬编码配置值
|
||||
- `build-and-push.sh` - 脚本内硬编码逻辑
|
||||
|
||||
**改进后**:
|
||||
- **单一配置源**: `.env` 文件
|
||||
- 所有版本号、密码、端口等配置统一管理
|
||||
- Docker Compose 使用环境变量替换
|
||||
- 构建脚本从 .env 读取所有配置
|
||||
|
||||
### ✅ 问题2: 脚本分阶段执行
|
||||
|
||||
**改进前**:
|
||||
- 一体化执行,无法分步操作
|
||||
- 出错后难以定位和恢复
|
||||
- 无法单独构建某个组件
|
||||
|
||||
**改进后**:
|
||||
```bash
|
||||
./build-and-push-v2.sh -b # 仅构建
|
||||
./build-and-push-v2.sh -p # 仅推送
|
||||
./build-and-push-v2.sh -d # 仅部署
|
||||
./build-and-push-v2.sh -a # 全部执行
|
||||
|
||||
# 支持单组件操作
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
./build-and-push-v2.sh -p -c ljwx-mysql
|
||||
```
|
||||
|
||||
### ✅ 问题3: 数据库版本管理
|
||||
|
||||
**改进前**:
|
||||
- 手动导出 data.sql
|
||||
- 容易出现版本不一致
|
||||
- 无法追踪变更历史
|
||||
- 升级困难且易出错
|
||||
|
||||
**改进后**:
|
||||
- **版本化迁移**: Flyway风格的迁移脚本
|
||||
- **自动追踪**: schema_migrations 表记录历史
|
||||
- **优雅升级**: 增量迁移脚本
|
||||
- **支持回滚**: 每个迁移有对应回滚脚本
|
||||
- **幂等性**: 脚本可重复执行
|
||||
|
||||
## 📁 新增文件清单
|
||||
|
||||
### 核心配置文件
|
||||
|
||||
| 文件 | 说明 | 用途 |
|
||||
|------|------|------|
|
||||
| `.env.unified` | 统一配置模板 | 复制后作为实际配置 |
|
||||
| `.env` | 实际配置文件 | 所有配置的唯一来源 |
|
||||
|
||||
### 核心脚本
|
||||
|
||||
| 文件 | 说明 | 主要功能 |
|
||||
|------|------|----------|
|
||||
| `build-and-push-v2.sh` | v2构建脚本 | 分阶段构建、推送、部署 |
|
||||
| `db-migrate.sh` | 数据库迁移工具 | 导出、迁移、回滚管理 |
|
||||
| `verify-setup.sh` | 安装验证脚本 | 检查环境和配置 |
|
||||
|
||||
### Docker配置
|
||||
|
||||
| 文件 | 说明 | 改进点 |
|
||||
|------|------|--------|
|
||||
| `docker-compose.prod.v2.yml` | v2版本Compose | 全部使用环境变量 |
|
||||
|
||||
### 数据库迁移
|
||||
|
||||
| 目录/文件 | 说明 |
|
||||
|-----------|------|
|
||||
| `docker/mysql/migrations/` | 迁移脚本目录 |
|
||||
| `docker/mysql/migrations/README.md` | 迁移文档 |
|
||||
| `docker/mysql/migrations/V*.sql` | 版本化迁移脚本 |
|
||||
| `docker/mysql/migrations/rollback/` | 回滚脚本目录 |
|
||||
|
||||
### 文档
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `DEPLOYMENT-GUIDE-V2.md` | 完整部署指南(25页) |
|
||||
| `QUICK-START-V2.md` | 快速开始指南 |
|
||||
| `V2-MIGRATION-SUMMARY.md` | 本文档 |
|
||||
|
||||
## 🔄 从v1迁移到v2
|
||||
|
||||
### 步骤1: 备份现有配置
|
||||
|
||||
```bash
|
||||
# 备份现有文件
|
||||
cp .env .env.v1.bak
|
||||
cp docker-compose.prod.yml docker-compose.prod.v1.yml
|
||||
cp build-and-push.sh build-and-push.v1.sh
|
||||
```
|
||||
|
||||
### 步骤2: 创建v2配置
|
||||
|
||||
```bash
|
||||
# 复制统一配置模板
|
||||
cp .env.unified .env
|
||||
|
||||
# 从旧配置迁移设置
|
||||
# 参考 monitoring-versions.env 和 docker-compose.prod.yml 中的值
|
||||
vim .env
|
||||
```
|
||||
|
||||
### 步骤3: 导出数据库基线
|
||||
|
||||
```bash
|
||||
# 确保 .env 中配置了宿主机MySQL连接信息
|
||||
./db-migrate.sh export 2.0.3
|
||||
```
|
||||
|
||||
### 步骤4: 测试新脚本
|
||||
|
||||
```bash
|
||||
# 验证环境
|
||||
./verify-setup.sh
|
||||
|
||||
# 测试构建(先测试单个组件)
|
||||
./build-and-push-v2.sh -b -c ljwx-mysql
|
||||
|
||||
# 如成功,构建所有组件
|
||||
./build-and-push-v2.sh -b
|
||||
```
|
||||
|
||||
### 步骤5: 完整部署
|
||||
|
||||
```bash
|
||||
./build-and-push-v2.sh -p # 推送镜像
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
```
|
||||
|
||||
## 💡 核心特性
|
||||
|
||||
### 1. 统一配置管理
|
||||
|
||||
```bash
|
||||
# .env 文件示例
|
||||
LJWX_VERSION=2.0.3
|
||||
REGISTRY=localhost:15000/ljwx
|
||||
MYSQL_ROOT_PASSWORD=123456
|
||||
MYSQL_DATABASE=test
|
||||
REDIS_PASSWORD=123456
|
||||
|
||||
# Docker Compose 自动使用
|
||||
services:
|
||||
ljwx-mysql:
|
||||
image: ${REGISTRY}/ljwx-mysql:${LJWX_VERSION}
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
```
|
||||
|
||||
### 2. 灵活的构建流程
|
||||
|
||||
```bash
|
||||
# 场景1: 快速迭代单个组件
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
./build-and-push-v2.sh -p -c ljwx-boot
|
||||
docker-compose restart ljwx-boot
|
||||
|
||||
# 场景2: 完整发版
|
||||
./build-and-push-v2.sh -e # 导出DB
|
||||
./build-and-push-v2.sh -b # 构建
|
||||
./build-and-push-v2.sh -p # 推送
|
||||
./build-and-push-v2.sh -d # 部署
|
||||
|
||||
# 场景3: 一键部署
|
||||
./build-and-push-v2.sh -e -a
|
||||
```
|
||||
|
||||
### 3. 数据库版本控制
|
||||
|
||||
```bash
|
||||
# 创建新迁移
|
||||
./db-migrate.sh create 2.0.4 add_features
|
||||
|
||||
# 编辑迁移脚本
|
||||
vim docker/mysql/migrations/V2.0.4__add_features.sql
|
||||
|
||||
# 应用迁移
|
||||
./db-migrate.sh apply 2.0.4
|
||||
|
||||
# 查看历史
|
||||
./db-migrate.sh status
|
||||
|
||||
# 回滚
|
||||
./db-migrate.sh rollback 2.0.3
|
||||
```
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
### 开发环境
|
||||
|
||||
```bash
|
||||
# 1. 修改代码后
|
||||
./build-and-push-v2.sh -b -c ljwx-boot
|
||||
|
||||
# 2. 推送并重启
|
||||
./build-and-push-v2.sh -p -c ljwx-boot
|
||||
docker-compose restart ljwx-boot
|
||||
|
||||
# 3. 查看日志
|
||||
docker-compose logs -f ljwx-boot
|
||||
```
|
||||
|
||||
### 生产环境
|
||||
|
||||
```bash
|
||||
# 1. 备份数据
|
||||
docker exec ljwx-mysql mysqldump -u root -p123456 test > backup.sql
|
||||
|
||||
# 2. 更新版本号
|
||||
vim .env # LJWX_VERSION=2.0.4
|
||||
|
||||
# 3. 导出数据库
|
||||
./db-migrate.sh export 2.0.4
|
||||
|
||||
# 4. 构建新版本
|
||||
./build-and-push-v2.sh -b
|
||||
|
||||
# 5. 推送到Registry
|
||||
./build-and-push-v2.sh -p
|
||||
|
||||
# 6. 部署
|
||||
./build-and-push-v2.sh -d
|
||||
```
|
||||
|
||||
### 数据库升级
|
||||
|
||||
```bash
|
||||
# 1. 创建迁移脚本
|
||||
./db-migrate.sh create 2.0.4 add_user_score_table
|
||||
|
||||
# 2. 编辑SQL(包括幂等性检查)
|
||||
vim docker/mysql/migrations/V2.0.4__add_user_score_table.sql
|
||||
|
||||
# 3. 编辑回滚脚本
|
||||
vim docker/mysql/migrations/rollback/R2.0.4__rollback.sql
|
||||
|
||||
# 4. 测试环境验证
|
||||
./db-migrate.sh apply 2.0.4
|
||||
# 测试功能...
|
||||
./db-migrate.sh rollback 2.0.3 # 测试回滚
|
||||
|
||||
# 5. 重新应用
|
||||
./db-migrate.sh apply 2.0.4
|
||||
|
||||
# 6. 构建新镜像
|
||||
./build-and-push-v2.sh -b -c ljwx-mysql
|
||||
```
|
||||
|
||||
## 📊 改进对比
|
||||
|
||||
| 维度 | v1.x | v2.0 | 改进 |
|
||||
|------|------|------|------|
|
||||
| 配置文件数量 | 3+ | 1 | ⭐⭐⭐⭐⭐ |
|
||||
| 构建灵活性 | 一体化 | 分阶段 | ⭐⭐⭐⭐⭐ |
|
||||
| 数据库管理 | 手动 | 自动化 | ⭐⭐⭐⭐⭐ |
|
||||
| 版本追踪 | ❌ | ✅ | ⭐⭐⭐⭐⭐ |
|
||||
| 回滚支持 | ❌ | ✅ | ⭐⭐⭐⭐⭐ |
|
||||
| 错误恢复 | 困难 | 容易 | ⭐⭐⭐⭐ |
|
||||
| 学习曲线 | 中等 | 低 | ⭐⭐⭐⭐ |
|
||||
| 文档完整性 | 基础 | 详尽 | ⭐⭐⭐⭐⭐ |
|
||||
|
||||
## 🔍 关键改进点
|
||||
|
||||
### 1. 配置管理
|
||||
|
||||
**Before**:
|
||||
```bash
|
||||
# monitoring-versions.env
|
||||
LJWX_VERSION=2.0.3
|
||||
|
||||
# docker-compose.prod.yml (硬编码)
|
||||
image: localhost:15000/ljwx/ljwx-mysql:2.0.3
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=123456
|
||||
|
||||
# build-and-push.sh (硬编码)
|
||||
LJWX_VERSION="1.2.16"
|
||||
REGISTRY="localhost:15000/ljwx"
|
||||
```
|
||||
|
||||
**After**:
|
||||
```bash
|
||||
# .env (唯一配置源)
|
||||
LJWX_VERSION=2.0.3
|
||||
REGISTRY=localhost:15000/ljwx
|
||||
MYSQL_ROOT_PASSWORD=123456
|
||||
|
||||
# docker-compose.prod.v2.yml (使用变量)
|
||||
image: ${REGISTRY}/ljwx-mysql:${LJWX_VERSION}
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
|
||||
# build-and-push-v2.sh (从.env读取)
|
||||
source .env
|
||||
```
|
||||
|
||||
### 2. 数据库管理
|
||||
|
||||
**Before**:
|
||||
```bash
|
||||
# 手动导出
|
||||
mysqldump -h 127.0.0.1 -u root -p123456 test > data.sql
|
||||
cp data.sql docker/mysql/
|
||||
|
||||
# 构建MySQL镜像
|
||||
docker build -t ljwx-mysql .
|
||||
|
||||
# 问题:容易忘记导出,版本不一致
|
||||
```
|
||||
|
||||
**After**:
|
||||
```bash
|
||||
# 导出时自动版本化
|
||||
./db-migrate.sh export 2.0.3
|
||||
# 生成:
|
||||
# - docker/mysql/data.sql (Docker使用)
|
||||
# - docker/mysql/migrations/V2.0.3__baseline.sql (版本化)
|
||||
# - backups/mysql/baseline_2.0.3_*.sql (备份)
|
||||
|
||||
# 增量升级
|
||||
./db-migrate.sh create 2.0.4 add_features
|
||||
./db-migrate.sh apply 2.0.4
|
||||
|
||||
# 自动记录历史
|
||||
SELECT * FROM schema_migrations;
|
||||
```
|
||||
|
||||
### 3. 构建流程
|
||||
|
||||
**Before**:
|
||||
```bash
|
||||
# 只能一次性执行
|
||||
./build-and-push.sh
|
||||
# 失败后难以定位问题
|
||||
```
|
||||
|
||||
**After**:
|
||||
```bash
|
||||
# 分阶段执行,每步可单独调试
|
||||
./build-and-push-v2.sh -b # 构建失败?查看 logs/build/
|
||||
./build-and-push-v2.sh -p # 推送失败?检查Registry
|
||||
./build-and-push-v2.sh -d # 部署失败?查看 logs/deploy/
|
||||
|
||||
# 单组件操作
|
||||
./build-and-push-v2.sh -b -c ljwx-boot # 只构建boot
|
||||
```
|
||||
|
||||
## 📖 快速参考
|
||||
|
||||
### 常用命令速查
|
||||
|
||||
```bash
|
||||
# 配置
|
||||
cp .env.unified .env # 创建配置
|
||||
vim .env # 编辑配置
|
||||
./verify-setup.sh # 验证环境
|
||||
|
||||
# 构建部署
|
||||
./build-and-push-v2.sh -b # 构建所有
|
||||
./build-and-push-v2.sh -p # 推送所有
|
||||
./build-and-push-v2.sh -d # 部署服务
|
||||
./build-and-push-v2.sh -a # 全部执行
|
||||
|
||||
# 单组件
|
||||
./build-and-push-v2.sh -b -c ljwx-boot # 构建单个
|
||||
./build-and-push-v2.sh -p -c ljwx-boot # 推送单个
|
||||
|
||||
# 数据库
|
||||
./db-migrate.sh export 2.0.3 # 导出基线
|
||||
./db-migrate.sh create 2.0.4 desc # 创建迁移
|
||||
./db-migrate.sh apply 2.0.4 # 应用迁移
|
||||
./db-migrate.sh apply-all # 应用所有
|
||||
./db-migrate.sh status # 查看状态
|
||||
./db-migrate.sh rollback 2.0.3 # 回滚
|
||||
|
||||
# Docker Compose
|
||||
docker-compose -f docker-compose.prod.v2.yml up -d
|
||||
docker-compose -f docker-compose.prod.v2.yml ps
|
||||
docker-compose -f docker-compose.prod.v2.yml logs -f
|
||||
docker-compose -f docker-compose.prod.v2.yml restart
|
||||
docker-compose -f docker-compose.prod.v2.yml down
|
||||
```
|
||||
|
||||
## 🎓 学习资源
|
||||
|
||||
- **快速开始**: `QUICK-START-V2.md` (5分钟上手)
|
||||
- **完整指南**: `DEPLOYMENT-GUIDE-V2.md` (详细文档)
|
||||
- **迁移指南**: `docker/mysql/migrations/README.md` (数据库迁移)
|
||||
- **配置说明**: `.env.unified` (所有配置项说明)
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
v2.0重构完美解决了您提出的所有问题:
|
||||
|
||||
1. ✅ **单一配置源** - `.env` 统一管理所有配置
|
||||
2. ✅ **灵活脚本** - 支持 -b/-p/-d/-a 分阶段执行
|
||||
3. ✅ **版本化迁移** - 数据库变更可追踪、可回滚、优雅升级
|
||||
|
||||
核心优势:
|
||||
- 🚀 **提升效率**: 分阶段操作,快速定位问题
|
||||
- 🛡️ **降低风险**: 版本追踪,支持回滚
|
||||
- 📝 **易于维护**: 配置集中,文档完整
|
||||
- 🔧 **灵活扩展**: 易于添加新组件
|
||||
|
||||
下一步建议:
|
||||
1. 阅读 `QUICK-START-V2.md` 快速上手
|
||||
2. 参考 `DEPLOYMENT-GUIDE-V2.md` 了解详细流程
|
||||
3. 使用 `verify-setup.sh` 验证环境
|
||||
4. 执行 `./build-and-push-v2.sh -e -a` 完成首次部署
|
||||
|
||||
**欢迎使用LJWX v2.0!** 🎊
|
||||
@@ -1,610 +0,0 @@
|
||||
#!/bin/bash
|
||||
# ============================================
|
||||
# LJWX 统一构建、推送、部署脚本 v2.0
|
||||
# ============================================
|
||||
# 功能:
|
||||
# - 统一从.env读取配置
|
||||
# - 支持分阶段执行:build, push, deploy
|
||||
# - 自动数据库迁移管理
|
||||
# - 完整的错误处理和日志
|
||||
# ============================================
|
||||
|
||||
set -e
|
||||
|
||||
# ============================================
|
||||
# 配置加载
|
||||
# ============================================
|
||||
|
||||
# 加载.env配置
|
||||
if [ -f .env ]; then
|
||||
echo "📋 加载配置文件: .env"
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
else
|
||||
echo "❌ 错误: .env 文件不存在"
|
||||
echo "💡 请先创建配置文件:"
|
||||
echo " cp .env.unified .env"
|
||||
echo " 然后编辑.env文件设置您的配置"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
MAGENTA='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 默认值
|
||||
COMPOSE_FILE=${COMPOSE_FILE:-docker-compose.prod.v2.yml}
|
||||
BUILD_LOG_DIR="./logs/build"
|
||||
DEPLOY_LOG_DIR="./logs/deploy"
|
||||
|
||||
# 创建日志目录
|
||||
mkdir -p "$BUILD_LOG_DIR" "$DEPLOY_LOG_DIR"
|
||||
|
||||
# ============================================
|
||||
# 工具函数
|
||||
# ============================================
|
||||
|
||||
print_header() {
|
||||
echo -e "\n${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
echo -e "${BLUE}========================================${NC}\n"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
echo -e "${CYAN}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
print_step() {
|
||||
echo -e "${MAGENTA}🔨 $1${NC}"
|
||||
}
|
||||
|
||||
# 检查必需命令
|
||||
check_requirements() {
|
||||
local missing_cmds=()
|
||||
|
||||
for cmd in docker mysql mysqldump; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
missing_cmds+=("$cmd")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_cmds[@]} -gt 0 ]; then
|
||||
print_error "缺少必需命令: ${missing_cmds[*]}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查Docker是否运行
|
||||
check_docker() {
|
||||
if ! docker info &> /dev/null; then
|
||||
print_error "Docker未运行,请先启动Docker"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查Registry是否可用
|
||||
check_registry() {
|
||||
local registry_host=${PRIVATE_REGISTRY_HOST:-localhost:15000}
|
||||
|
||||
if [ "${PRIVATE_REGISTRY_ENABLED}" = "true" ]; then
|
||||
if curl -f -s "http://${registry_host}/v2/_catalog" > /dev/null; then
|
||||
print_success "本地私有 Registry 可用: $registry_host"
|
||||
return 0
|
||||
else
|
||||
print_warning "本地私有 Registry 不可用: $registry_host"
|
||||
print_info "可以手动启动 Registry 或禁用 PRIVATE_REGISTRY_ENABLED"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# 数据库管理
|
||||
# ============================================
|
||||
|
||||
export_database() {
|
||||
print_header "导出数据库基线"
|
||||
|
||||
# 检查宿主MySQL连接
|
||||
if ! mysql -h ${HOST_MYSQL_HOST} -P ${HOST_MYSQL_PORT} \
|
||||
-u${HOST_MYSQL_USER} -p${HOST_MYSQL_PASSWORD} \
|
||||
-e "SELECT 1" &>/dev/null; then
|
||||
print_error "无法连接到宿主数据库 ${HOST_MYSQL_HOST}:${HOST_MYSQL_PORT}"
|
||||
print_info "请检查.env中的 HOST_MYSQL_* 配置"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 使用db-migrate.sh导出
|
||||
if [ -f ./db-migrate.sh ]; then
|
||||
./db-migrate.sh export "${LJWX_VERSION}"
|
||||
else
|
||||
print_warning "db-migrate.sh 不存在,使用简单导出"
|
||||
|
||||
local data_file="./docker/mysql/data.sql"
|
||||
mysqldump -h ${HOST_MYSQL_HOST} -P ${HOST_MYSQL_PORT} \
|
||||
-u${HOST_MYSQL_USER} -p${HOST_MYSQL_PASSWORD} \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--lock-tables=false \
|
||||
--routines \
|
||||
--triggers \
|
||||
--events \
|
||||
--complete-insert \
|
||||
${HOST_MYSQL_DATABASE} > "$data_file" 2>/dev/null
|
||||
|
||||
print_success "数据库已导出: $data_file"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# 构建镜像
|
||||
# ============================================
|
||||
|
||||
build_image() {
|
||||
local component=$1
|
||||
local version=${2:-${LJWX_VERSION}}
|
||||
|
||||
print_step "构建 ${component} 镜像"
|
||||
|
||||
local image_tag="${REGISTRY}/${component}:${version}"
|
||||
local latest_tag="${REGISTRY}/${component}:latest"
|
||||
local log_file="${BUILD_LOG_DIR}/${component}_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# 根据组件选择Dockerfile和构建上下文
|
||||
local dockerfile=""
|
||||
local context="."
|
||||
local build_args=""
|
||||
|
||||
case "$component" in
|
||||
ljwx-mysql)
|
||||
dockerfile="docker/mysql/Dockerfile"
|
||||
# MySQL构建前先导出数据库
|
||||
if [ "${DB_MIGRATION_ENABLED}" = "true" ]; then
|
||||
export_database || print_warning "数据库导出失败,使用现有data.sql"
|
||||
fi
|
||||
;;
|
||||
ljwx-redis)
|
||||
dockerfile="docker/redis/Dockerfile"
|
||||
;;
|
||||
ljwx-boot)
|
||||
dockerfile="ljwx-boot/ljwx-boot-admin/Dockerfile.prod"
|
||||
context="ljwx-boot"
|
||||
;;
|
||||
ljwx-bigscreen)
|
||||
dockerfile="ljwx-bigscreen/bigscreen/Dockerfile.prod"
|
||||
context="ljwx-bigscreen/bigscreen"
|
||||
;;
|
||||
ljwx-admin)
|
||||
dockerfile="ljwx-admin/Dockerfile"
|
||||
context="ljwx-admin"
|
||||
;;
|
||||
*)
|
||||
print_error "未知组件: $component"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# 构建参数
|
||||
build_args="--build-arg BUILD_DATE=${BUILD_DATE:-$(date -u +'%Y-%m-%dT%H:%M:%SZ')}"
|
||||
build_args="$build_args --build-arg GIT_COMMIT=${GIT_COMMIT:-$(git rev-parse --short HEAD 2>/dev/null || echo unknown)}"
|
||||
build_args="$build_args --build-arg VERSION=${version}"
|
||||
|
||||
print_info "镜像标签: $image_tag"
|
||||
print_info "Dockerfile: $dockerfile"
|
||||
print_info "构建上下文: $context"
|
||||
|
||||
# 执行构建
|
||||
if [ "${LOCAL_BUILD}" = "true" ]; then
|
||||
# 本地构建
|
||||
docker build \
|
||||
${build_args} \
|
||||
--platform ${PLATFORMS:-linux/amd64} \
|
||||
-t "$image_tag" \
|
||||
-t "$latest_tag" \
|
||||
-f "$dockerfile" \
|
||||
"$context" 2>&1 | tee "$log_file"
|
||||
else
|
||||
# Buildx多架构构建
|
||||
docker buildx build \
|
||||
${build_args} \
|
||||
--platform ${PLATFORMS:-linux/amd64,linux/arm64} \
|
||||
-t "$image_tag" \
|
||||
-t "$latest_tag" \
|
||||
-f "$dockerfile" \
|
||||
"$context" 2>&1 | tee "$log_file"
|
||||
fi
|
||||
|
||||
if [ ${PIPESTATUS[0]} -eq 0 ]; then
|
||||
print_success "${component} 构建成功"
|
||||
print_info "日志文件: $log_file"
|
||||
return 0
|
||||
else
|
||||
print_error "${component} 构建失败"
|
||||
print_info "查看日志: $log_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
build_all() {
|
||||
print_header "构建所有镜像 - 版本 ${LJWX_VERSION}"
|
||||
|
||||
local components=(
|
||||
"ljwx-mysql"
|
||||
"ljwx-redis"
|
||||
"ljwx-boot"
|
||||
"ljwx-bigscreen"
|
||||
"ljwx-admin"
|
||||
)
|
||||
|
||||
local failed_components=()
|
||||
|
||||
for component in "${components[@]}"; do
|
||||
# 获取组件特定版本
|
||||
local component_version_var="${component//-/_}_VERSION"
|
||||
component_version_var=$(echo "$component_version_var" | tr '[:lower:]' '[:upper:]') # 转大写
|
||||
local version="${!component_version_var:-${LJWX_VERSION}}"
|
||||
|
||||
if ! build_image "$component" "$version"; then
|
||||
failed_components+=("$component")
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
if [ ${#failed_components[@]} -eq 0 ]; then
|
||||
print_success "所有镜像构建成功"
|
||||
return 0
|
||||
else
|
||||
print_error "以下镜像构建失败: ${failed_components[*]}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# 推送镜像
|
||||
# ============================================
|
||||
|
||||
push_image() {
|
||||
local component=$1
|
||||
local version=${2:-${LJWX_VERSION}}
|
||||
|
||||
print_step "推送 ${component} 镜像"
|
||||
|
||||
local image_tag="${REGISTRY}/${component}:${version}"
|
||||
local latest_tag="${REGISTRY}/${component}:latest"
|
||||
|
||||
# 推送版本标签
|
||||
if docker push "$image_tag" 2>&1; then
|
||||
print_success "${component}:${version} 推送成功"
|
||||
else
|
||||
print_error "${component}:${version} 推送失败"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 推送latest标签
|
||||
if docker push "$latest_tag" 2>&1; then
|
||||
print_success "${component}:latest 推送成功"
|
||||
else
|
||||
print_warning "${component}:latest 推送失败"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
push_all() {
|
||||
print_header "推送所有镜像到 ${REGISTRY}"
|
||||
|
||||
check_registry || return 1
|
||||
|
||||
local components=(
|
||||
"ljwx-mysql"
|
||||
"ljwx-redis"
|
||||
"ljwx-boot"
|
||||
"ljwx-bigscreen"
|
||||
"ljwx-admin"
|
||||
)
|
||||
|
||||
local failed_components=()
|
||||
|
||||
for component in "${components[@]}"; do
|
||||
local component_version_var="${component//-/_}_VERSION"
|
||||
component_version_var="${component_version_var^^}"
|
||||
local version="${!component_version_var:-${LJWX_VERSION}}"
|
||||
|
||||
if ! push_image "$component" "$version"; then
|
||||
failed_components+=("$component")
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
if [ ${#failed_components[@]} -eq 0 ]; then
|
||||
print_success "所有镜像推送成功"
|
||||
return 0
|
||||
else
|
||||
print_error "以下镜像推送失败: ${failed_components[*]}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# 部署服务
|
||||
# ============================================
|
||||
|
||||
deploy_services() {
|
||||
print_header "部署服务 - 使用 ${COMPOSE_FILE}"
|
||||
|
||||
# 检查compose文件是否存在
|
||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||
print_error "Compose文件不存在: $COMPOSE_FILE"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查Registry中是否有镜像
|
||||
print_info "检查镜像可用性..."
|
||||
|
||||
local components=("ljwx-mysql" "ljwx-redis" "ljwx-boot" "ljwx-bigscreen" "ljwx-admin")
|
||||
local missing_images=()
|
||||
|
||||
for component in "${components[@]}"; do
|
||||
local component_version_var="${component//-/_}_VERSION"
|
||||
component_version_var="${component_version_var^^}"
|
||||
local version="${!component_version_var:-${LJWX_VERSION}}"
|
||||
local image="${REGISTRY}/${component}:${version}"
|
||||
|
||||
# 尝试拉取镜像
|
||||
if ! docker pull "$image" &>/dev/null; then
|
||||
missing_images+=("$image")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing_images[@]} -gt 0 ]; then
|
||||
print_warning "以下镜像不存在:"
|
||||
for img in "${missing_images[@]}"; do
|
||||
echo " - $img"
|
||||
done
|
||||
print_info "建议先执行: $0 -b -p"
|
||||
read -p "是否继续部署? (yes/no): " confirm
|
||||
if [ "$confirm" != "yes" ]; then
|
||||
print_info "已取消部署"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 停止旧服务
|
||||
print_info "停止现有服务..."
|
||||
docker-compose -f "$COMPOSE_FILE" down 2>&1 | tee "${DEPLOY_LOG_DIR}/down_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# 启动新服务
|
||||
print_info "启动服务..."
|
||||
docker-compose -f "$COMPOSE_FILE" up -d 2>&1 | tee "${DEPLOY_LOG_DIR}/up_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# 等待服务健康
|
||||
print_info "等待服务就绪..."
|
||||
sleep 10
|
||||
|
||||
# 检查服务状态
|
||||
docker-compose -f "$COMPOSE_FILE" ps
|
||||
|
||||
# 应用数据库迁移
|
||||
if [ "${DB_MIGRATION_AUTO_APPLY}" = "true" ] && [ -f ./db-migrate.sh ]; then
|
||||
print_info "应用数据库迁移..."
|
||||
sleep 20 # 等待MySQL完全启动
|
||||
./db-migrate.sh apply-all || print_warning "数据库迁移失败"
|
||||
fi
|
||||
|
||||
print_success "服务部署完成"
|
||||
|
||||
# 显示访问地址
|
||||
print_info "服务访问地址:"
|
||||
echo " - 后端API: http://localhost:${BOOT_PORT:-9998}"
|
||||
echo " - 管理界面: http://localhost:${ADMIN_EXTERNAL_PORT:-8080}"
|
||||
echo " - 大屏服务: http://localhost:${BIGSCREEN_EXTERNAL_PORT:-8000}"
|
||||
echo " - MySQL: localhost:${MYSQL_PORT:-3307} (${MYSQL_USER}/${MYSQL_PASSWORD})"
|
||||
echo " - Redis: localhost:${REDIS_PORT:-6379} (password: ${REDIS_PASSWORD})"
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# 主程序
|
||||
# ============================================
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
${BLUE}LJWX 统一构建、推送、部署脚本 v2.0${NC}
|
||||
|
||||
用法:
|
||||
$0 [选项]
|
||||
|
||||
选项:
|
||||
-b, --build 仅构建镜像
|
||||
-p, --push 仅推送镜像到Registry
|
||||
-d, --deploy 仅部署服务
|
||||
-a, --all 执行所有操作 (build + push + deploy)
|
||||
|
||||
-c <组件>, --component <组件>
|
||||
指定要操作的组件
|
||||
可选: ljwx-mysql, ljwx-redis, ljwx-boot,
|
||||
ljwx-bigscreen, ljwx-admin
|
||||
|
||||
-v <版本>, --version <版本>
|
||||
指定版本号(默认从.env读取)
|
||||
|
||||
-e, --export-db 导出宿主数据库
|
||||
-m, --migrate 仅执行数据库迁移
|
||||
|
||||
-h, --help 显示此帮助信息
|
||||
|
||||
示例:
|
||||
|
||||
1. 一键构建、推送、部署所有组件
|
||||
$ $0 -a
|
||||
|
||||
2. 仅构建所有镜像
|
||||
$ $0 -b
|
||||
|
||||
3. 仅推送所有镜像
|
||||
$ $0 -p
|
||||
|
||||
4. 仅部署服务
|
||||
$ $0 -d
|
||||
|
||||
5. 构建单个组件
|
||||
$ $0 -b -c ljwx-boot
|
||||
|
||||
6. 构建并推送单个组件
|
||||
$ $0 -b -p -c ljwx-mysql
|
||||
|
||||
7. 导出数据库基线
|
||||
$ $0 -e
|
||||
|
||||
8. 分步操作(推荐用于生产)
|
||||
$ $0 -b # 构建镜像
|
||||
$ $0 -p # 推送到Registry
|
||||
$ $0 -e # 导出数据库(如需要)
|
||||
$ $0 -d # 部署服务
|
||||
|
||||
配置:
|
||||
配置文件: .env (从.env.unified复制)
|
||||
版本号: ${LJWX_VERSION}
|
||||
镜像仓库: ${REGISTRY}
|
||||
Compose文件: ${COMPOSE_FILE}
|
||||
|
||||
更多信息:
|
||||
- 数据库迁移: ./db-migrate.sh help
|
||||
- Docker Compose: docker-compose -f ${COMPOSE_FILE} --help
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 解析命令行参数
|
||||
DO_BUILD=false
|
||||
DO_PUSH=false
|
||||
DO_DEPLOY=false
|
||||
DO_EXPORT_DB=false
|
||||
DO_MIGRATE=false
|
||||
COMPONENT=""
|
||||
VERSION="${LJWX_VERSION}"
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
show_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-b|--build)
|
||||
DO_BUILD=true
|
||||
shift
|
||||
;;
|
||||
-p|--push)
|
||||
DO_PUSH=true
|
||||
shift
|
||||
;;
|
||||
-d|--deploy)
|
||||
DO_DEPLOY=true
|
||||
shift
|
||||
;;
|
||||
-a|--all)
|
||||
DO_BUILD=true
|
||||
DO_PUSH=true
|
||||
DO_DEPLOY=true
|
||||
shift
|
||||
;;
|
||||
-c|--component)
|
||||
COMPONENT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-v|--version)
|
||||
VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
-e|--export-db)
|
||||
DO_EXPORT_DB=true
|
||||
shift
|
||||
;;
|
||||
-m|--migrate)
|
||||
DO_MIGRATE=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_error "未知选项: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 执行前检查
|
||||
check_requirements
|
||||
check_docker
|
||||
|
||||
# 显示配置信息
|
||||
print_header "LJWX 构建部署工具 v2.0"
|
||||
echo "版本: ${VERSION}"
|
||||
echo "Registry: ${REGISTRY}"
|
||||
echo "平台: ${PLATFORMS}"
|
||||
echo "Compose: ${COMPOSE_FILE}"
|
||||
echo ""
|
||||
|
||||
# 执行导出数据库
|
||||
if [ "$DO_EXPORT_DB" = true ]; then
|
||||
export_database
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# 执行数据库迁移
|
||||
if [ "$DO_MIGRATE" = true ]; then
|
||||
if [ -f ./db-migrate.sh ]; then
|
||||
./db-migrate.sh apply-all
|
||||
else
|
||||
print_error "db-migrate.sh 不存在"
|
||||
exit 1
|
||||
fi
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# 执行构建
|
||||
if [ "$DO_BUILD" = true ]; then
|
||||
if [ -n "$COMPONENT" ]; then
|
||||
build_image "$COMPONENT" "$VERSION" || exit 1
|
||||
else
|
||||
build_all || exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 执行推送
|
||||
if [ "$DO_PUSH" = true ]; then
|
||||
if [ -n "$COMPONENT" ]; then
|
||||
push_image "$COMPONENT" "$VERSION" || exit 1
|
||||
else
|
||||
push_all || exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 执行部署
|
||||
if [ "$DO_DEPLOY" = true ]; then
|
||||
deploy_services || exit 1
|
||||
fi
|
||||
|
||||
print_success "所有操作完成!"
|
||||
+558
-1542
File diff suppressed because it is too large
Load Diff
-414
@@ -1,414 +0,0 @@
|
||||
#!/bin/bash
|
||||
# 基础服务统一构建脚本
|
||||
# 统一端口配置,有序部署所有服务
|
||||
|
||||
set -e
|
||||
BASE_DIR="/Users/brunogao/work/infra"
|
||||
SCRIPTS_DIR="$BASE_DIR/scripts"
|
||||
|
||||
# 加载配置
|
||||
source "$BASE_DIR/configs/global.env" 2>/dev/null || {
|
||||
echo "⚠️ 配置文件不存在,使用默认配置"
|
||||
}
|
||||
|
||||
# 颜色定义
|
||||
G='\033[0;32m' # 绿色
|
||||
Y='\033[1;33m' # 黄色
|
||||
R='\033[0;31m' # 红色
|
||||
B='\033[0;34m' # 蓝色
|
||||
C='\033[0;36m' # 青色
|
||||
NC='\033[0m' # 无色
|
||||
|
||||
# 日志函数
|
||||
log() { echo -e "${G}[INFO]${NC} $1"; }
|
||||
warn() { echo -e "${Y}[WARN]${NC} $1"; }
|
||||
error() { echo -e "${R}[ERROR]${NC} $1"; }
|
||||
info() { echo -e "${B}[INFO]${NC} $1"; }
|
||||
step() { echo -e "${C}[STEP]${NC} $1"; }
|
||||
|
||||
# 显示Logo
|
||||
show_logo() {
|
||||
echo -e "${B}"
|
||||
cat << 'EOF'
|
||||
╔═══════════════════════════════════════╗
|
||||
║ 基础服务统一构建 ║
|
||||
║ CI/CD Infrastructure ║
|
||||
║ ║
|
||||
║ Port Layout: ║
|
||||
║ • Gitea: 33000 (SSH: 32222) ║
|
||||
║ • Jenkins: 38080 (Agent: 35000) ║
|
||||
║ • Registry: 35001 (UI: 35002) ║
|
||||
╚═══════════════════════════════════════╝
|
||||
EOF
|
||||
echo -e "${NC}"
|
||||
}
|
||||
|
||||
# 检查依赖
|
||||
check_dependencies() {
|
||||
step "检查系统依赖..."
|
||||
|
||||
# 检查Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
error "Docker未安装,请先安装Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info &> /dev/null; then
|
||||
error "Docker未运行,请启动Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查docker-compose
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
error "docker-compose未安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "✅ 系统依赖检查通过"
|
||||
}
|
||||
|
||||
# 检查端口占用
|
||||
check_ports() {
|
||||
step "检查端口占用情况..."
|
||||
|
||||
local ports=(33000 32222 38080 35000 35001 35002)
|
||||
local occupied_ports=()
|
||||
|
||||
for port in "${ports[@]}"; do
|
||||
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null; then
|
||||
occupied_ports+=($port)
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#occupied_ports[@]} -gt 0 ]; then
|
||||
warn "检测到端口占用: ${occupied_ports[*]}"
|
||||
echo "是否继续?占用的端口可能会导致服务启动失败 (y/N)"
|
||||
read -r response
|
||||
if [[ ! $response =~ ^[Yy]$ ]]; then
|
||||
error "用户取消部署"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "✅ 所有端口都可用"
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理现有服务
|
||||
cleanup_existing() {
|
||||
step "清理现有服务..."
|
||||
|
||||
# 停止可能存在的服务
|
||||
docker-compose -f "$BASE_DIR/docker/compose/jenkins-simple.yml" down 2>/dev/null || true
|
||||
docker-compose -f "$BASE_DIR/docker/compose/gitea-compose.yml" down 2>/dev/null || true
|
||||
docker-compose -f "$BASE_DIR/docker/compose/registry.yml" down 2>/dev/null || true
|
||||
|
||||
# 停止单独的容器
|
||||
local containers=("jenkins-simple" "gitea" "registry" "registry-ui")
|
||||
for container in "${containers[@]}"; do
|
||||
docker stop "$container" 2>/dev/null || true
|
||||
docker rm "$container" 2>/dev/null || true
|
||||
done
|
||||
|
||||
log "✅ 现有服务已清理"
|
||||
}
|
||||
|
||||
# 初始化环境
|
||||
init_environment() {
|
||||
step "初始化环境..."
|
||||
|
||||
# 创建必要目录
|
||||
mkdir -p "$BASE_DIR"/{data,backup,configs}
|
||||
mkdir -p "$BASE_DIR/docker/registry/auth"
|
||||
mkdir -p "$BASE_DIR/data"/{gitea,jenkins,registry}
|
||||
|
||||
# 创建网络
|
||||
docker network create $NETWORK_NAME 2>/dev/null || {
|
||||
log "网络 $NETWORK_NAME 已存在"
|
||||
}
|
||||
|
||||
# 创建Registry认证文件
|
||||
if [[ ! -f "$BASE_DIR/docker/registry/auth/htpasswd" ]]; then
|
||||
docker run --rm httpd:2.4-alpine htpasswd -Bbn $REGISTRY_USERNAME $REGISTRY_PASSWORD > \
|
||||
"$BASE_DIR/docker/registry/auth/htpasswd"
|
||||
log "✅ Registry认证文件已创建"
|
||||
fi
|
||||
|
||||
log "✅ 环境初始化完成"
|
||||
}
|
||||
|
||||
# 部署Registry
|
||||
deploy_registry() {
|
||||
step "部署Docker Registry..."
|
||||
|
||||
cd "$BASE_DIR/docker/compose"
|
||||
docker-compose -f registry-simple.yml up -d
|
||||
|
||||
# 等待服务启动
|
||||
local max_wait=30
|
||||
local count=0
|
||||
while [ $count -lt $max_wait ]; do
|
||||
if curl -s http://localhost:35001/v2/ >/dev/null 2>&1; then
|
||||
log "✅ Registry服务启动成功 (http://localhost:35001)"
|
||||
log "✅ Registry UI可用 (http://localhost:35002)"
|
||||
return 0
|
||||
fi
|
||||
sleep 2
|
||||
count=$((count + 1))
|
||||
echo -n "."
|
||||
done
|
||||
|
||||
error "❌ Registry服务启动超时"
|
||||
return 1
|
||||
}
|
||||
|
||||
# 部署Gitea
|
||||
deploy_gitea() {
|
||||
step "部署Gitea服务..."
|
||||
|
||||
cd "$BASE_DIR/docker/compose"
|
||||
docker-compose -f gitea-compose.yml up -d
|
||||
|
||||
# 等待服务启动
|
||||
local max_wait=60
|
||||
local count=0
|
||||
while [ $count -lt $max_wait ]; do
|
||||
if curl -s http://localhost:33000/api/healthz >/dev/null 2>&1; then
|
||||
log "✅ Gitea服务启动成功 (http://localhost:33000)"
|
||||
return 0
|
||||
fi
|
||||
sleep 3
|
||||
count=$((count + 1))
|
||||
echo -n "."
|
||||
done
|
||||
|
||||
error "❌ Gitea服务启动超时"
|
||||
return 1
|
||||
}
|
||||
|
||||
# 部署Jenkins
|
||||
deploy_jenkins() {
|
||||
step "部署Jenkins服务..."
|
||||
|
||||
cd "$BASE_DIR/docker/compose"
|
||||
docker-compose -f jenkins-simple.yml up -d
|
||||
|
||||
# 等待服务启动
|
||||
local max_wait=120
|
||||
local count=0
|
||||
while [ $count -lt $max_wait ]; do
|
||||
if docker logs jenkins-simple 2>&1 | grep -q "Jenkins is fully up and running" || \
|
||||
curl -s http://localhost:38080/login >/dev/null 2>&1; then
|
||||
log "✅ Jenkins服务启动成功 (http://localhost:38080)"
|
||||
log "✅ 管理员账号: admin / admin123"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 每10秒显示启动进度
|
||||
if [ $((count % 5)) -eq 0 ]; then
|
||||
local recent_logs=$(docker logs jenkins-simple 2>&1 | tail -2)
|
||||
info "启动中... $recent_logs"
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
count=$((count + 1))
|
||||
echo -n "."
|
||||
done
|
||||
|
||||
error "❌ Jenkins服务启动超时"
|
||||
return 1
|
||||
}
|
||||
|
||||
# 配置服务集成
|
||||
setup_integration() {
|
||||
step "配置服务集成..."
|
||||
|
||||
# 等待Jenkins完全启动
|
||||
sleep 10
|
||||
|
||||
# 这里可以添加自动配置逻辑
|
||||
# 例如:创建Jenkins凭据,配置Gitea webhook等
|
||||
|
||||
log "✅ 服务集成配置完成"
|
||||
}
|
||||
|
||||
# 运行验证测试
|
||||
run_verification() {
|
||||
step "运行验证测试..."
|
||||
|
||||
local all_ok=true
|
||||
|
||||
# 测试Registry
|
||||
if curl -s -w "%{http_code}" http://localhost:35001/v2/ | grep -q "200"; then
|
||||
log "✅ Registry API正常"
|
||||
else
|
||||
error "❌ Registry API异常"
|
||||
all_ok=false
|
||||
fi
|
||||
|
||||
# 测试Registry UI
|
||||
if curl -s http://localhost:35002 | grep -q "docker-registry-ui"; then
|
||||
log "✅ Registry UI正常"
|
||||
else
|
||||
error "❌ Registry UI异常"
|
||||
all_ok=false
|
||||
fi
|
||||
|
||||
# 测试Gitea
|
||||
if curl -s http://localhost:33000/api/healthz | grep -q "pass"; then
|
||||
log "✅ Gitea API正常"
|
||||
else
|
||||
error "❌ Gitea API异常"
|
||||
all_ok=false
|
||||
fi
|
||||
|
||||
# 测试Jenkins (检查服务是否响应,允许重定向)
|
||||
local jenkins_status=$(curl -s -w "%{http_code}" -o /dev/null http://localhost:38080/login)
|
||||
if [[ "$jenkins_status" == "200" ]]; then
|
||||
log "✅ Jenkins API正常"
|
||||
else
|
||||
error "❌ Jenkins API异常 (状态码: $jenkins_status)"
|
||||
all_ok=false
|
||||
fi
|
||||
|
||||
if $all_ok; then
|
||||
log "🎉 所有服务验证通过!"
|
||||
return 0
|
||||
else
|
||||
error "❌ 部分服务验证失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示部署结果
|
||||
show_result() {
|
||||
echo ""
|
||||
echo "================================================================="
|
||||
echo -e "${G}🎉 基础服务部署完成${NC}"
|
||||
echo "================================================================="
|
||||
echo ""
|
||||
echo -e "${B}服务访问地址:${NC}"
|
||||
echo " • Gitea: http://localhost:33000"
|
||||
echo " • Jenkins: http://localhost:38080 (admin/admin123)"
|
||||
echo " • Docker Registry: http://localhost:35001"
|
||||
echo " • Registry UI: http://localhost:35002"
|
||||
echo ""
|
||||
echo -e "${B}SSH访问:${NC}"
|
||||
echo " • Gitea SSH: ssh://git@localhost:32222"
|
||||
echo ""
|
||||
echo -e "${B}内部服务地址 (容器间通信):${NC}"
|
||||
echo " • Gitea: http://gitea:3000"
|
||||
echo " • Jenkins: http://jenkins:8080"
|
||||
echo " • Registry: http://registry:5000"
|
||||
echo ""
|
||||
echo -e "${Y}后续步骤:${NC}"
|
||||
echo " 1. 在Gitea中创建用户和仓库"
|
||||
echo " 2. 配置Jenkins Pipeline"
|
||||
echo " 3. 测试完整的CI/CD流程"
|
||||
echo ""
|
||||
echo -e "${B}管理命令:${NC}"
|
||||
echo " ./scripts/maintenance/health-check.sh # 健康检查"
|
||||
echo " ./scripts/maintenance/backup-all.sh # 数据备份"
|
||||
echo " ./scripts/utils/show-logs.sh # 查看日志"
|
||||
echo ""
|
||||
echo "================================================================="
|
||||
}
|
||||
|
||||
# 显示帮助
|
||||
show_help() {
|
||||
echo "基础服务统一构建脚本"
|
||||
echo ""
|
||||
echo "用法: $0 [选项]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " --full-auto 完全自动化部署 (推荐)"
|
||||
echo " --step-by-step 分步骤部署,每步确认"
|
||||
echo " --update-ports 仅更新端口配置"
|
||||
echo " --cleanup 清理所有服务"
|
||||
echo " --verify 仅运行验证测试"
|
||||
echo " --help 显示帮助信息"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 --full-auto # 一键部署所有服务"
|
||||
echo " $0 --step-by-step # 逐步部署"
|
||||
echo " $0 --verify # 验证现有服务"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
show_logo
|
||||
|
||||
case "${1:-full-auto}" in
|
||||
"--full-auto")
|
||||
log "开始完全自动化部署..."
|
||||
check_dependencies
|
||||
check_ports
|
||||
cleanup_existing
|
||||
init_environment
|
||||
deploy_registry
|
||||
deploy_gitea
|
||||
deploy_jenkins
|
||||
setup_integration
|
||||
run_verification
|
||||
show_result
|
||||
;;
|
||||
"--step-by-step")
|
||||
log "开始分步骤部署..."
|
||||
check_dependencies
|
||||
|
||||
echo "按回车继续到下一步..."
|
||||
read -r
|
||||
check_ports
|
||||
|
||||
echo "按回车继续清理现有服务..."
|
||||
read -r
|
||||
cleanup_existing
|
||||
|
||||
echo "按回车继续初始化环境..."
|
||||
read -r
|
||||
init_environment
|
||||
|
||||
echo "按回车继续部署Registry..."
|
||||
read -r
|
||||
deploy_registry
|
||||
|
||||
echo "按回车继续部署Gitea..."
|
||||
read -r
|
||||
deploy_gitea
|
||||
|
||||
echo "按回车继续部署Jenkins..."
|
||||
read -r
|
||||
deploy_jenkins
|
||||
|
||||
echo "按回车继续配置集成..."
|
||||
read -r
|
||||
setup_integration
|
||||
|
||||
echo "按回车继续验证测试..."
|
||||
read -r
|
||||
run_verification
|
||||
show_result
|
||||
;;
|
||||
"--cleanup")
|
||||
log "清理所有服务..."
|
||||
cleanup_existing
|
||||
docker network rm $NETWORK_NAME 2>/dev/null || true
|
||||
log "✅ 清理完成"
|
||||
;;
|
||||
"--verify")
|
||||
log "运行验证测试..."
|
||||
run_verification
|
||||
;;
|
||||
"--help")
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
show_help
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 错误处理
|
||||
trap 'error "部署失败,请检查错误信息"; exit 1' ERR
|
||||
|
||||
# 执行主程序
|
||||
main "$@"
|
||||
@@ -1,129 +0,0 @@
|
||||
#!/bin/bash
|
||||
# 多架构分别构建脚本 v1.0
|
||||
|
||||
set -e
|
||||
|
||||
echo "🏗️ 多架构分别构建解决方案"
|
||||
|
||||
# 加载版本配置
|
||||
if [ -f "monitoring-versions.env" ]; then
|
||||
source monitoring-versions.env
|
||||
echo "📋 已加载版本配置文件"
|
||||
else
|
||||
echo "⚠️ 未找到版本配置文件,使用默认配置"
|
||||
LJWX_VERSION="1.2.16"
|
||||
REGISTRY="crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx"
|
||||
fi
|
||||
|
||||
# 登录阿里云
|
||||
echo "🔐 登录阿里云Docker镜像仓库..."
|
||||
echo "admin123" | docker login --username brunogao --password-stdin crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 阿里云登录成功"
|
||||
else
|
||||
echo "❌ 阿里云登录失败,请检查凭据"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 构建函数
|
||||
build_single_arch() {
|
||||
local arch=$1
|
||||
local tag_suffix=$2
|
||||
local image_name="ljwx-boot"
|
||||
local tag="$REGISTRY/$image_name:$LJWX_VERSION-$tag_suffix"
|
||||
|
||||
echo "🔨 构建 $arch 架构镜像..."
|
||||
|
||||
# 设置平台
|
||||
export DOCKER_DEFAULT_PLATFORM="linux/$arch"
|
||||
|
||||
# 构建单架构镜像
|
||||
docker build \
|
||||
--platform linux/$arch \
|
||||
--progress=plain \
|
||||
-t $tag \
|
||||
. -f ljwx-boot/ljwx-boot-admin/Dockerfile.prod
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ $arch 架构构建成功: $tag"
|
||||
# 推送到镜像仓库
|
||||
docker push $tag
|
||||
echo "✅ $arch 架构推送成功"
|
||||
return 0
|
||||
else
|
||||
echo "❌ $arch 架构构建失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建多架构manifest
|
||||
create_multiarch_manifest() {
|
||||
local image_name="ljwx-boot"
|
||||
local manifest_tag="$REGISTRY/$image_name:$LJWX_VERSION"
|
||||
local amd64_tag="$REGISTRY/$image_name:$LJWX_VERSION-amd64"
|
||||
local arm64_tag="$REGISTRY/$image_name:$LJWX_VERSION-arm64"
|
||||
|
||||
echo "📦 创建多架构 manifest..."
|
||||
|
||||
# 创建 manifest
|
||||
docker manifest create $manifest_tag $amd64_tag $arm64_tag
|
||||
|
||||
# 设置架构信息
|
||||
docker manifest annotate $manifest_tag $amd64_tag --arch amd64
|
||||
docker manifest annotate $manifest_tag $arm64_tag --arch arm64
|
||||
|
||||
# 推送 manifest
|
||||
docker manifest push $manifest_tag
|
||||
|
||||
# 创建 latest 标签的 manifest
|
||||
local latest_tag="$REGISTRY/$image_name:latest"
|
||||
docker manifest create $latest_tag $amd64_tag $arm64_tag
|
||||
docker manifest annotate $latest_tag $amd64_tag --arch amd64
|
||||
docker manifest annotate $latest_tag $arm64_tag --arch arm64
|
||||
docker manifest push $latest_tag
|
||||
|
||||
echo "✅ 多架构 manifest 创建完成"
|
||||
echo "🏷️ 镜像标签: $manifest_tag, $latest_tag"
|
||||
}
|
||||
|
||||
# 主程序
|
||||
main() {
|
||||
echo "🚀 开始分别构建多架构镜像..."
|
||||
|
||||
# 构建 AMD64 架构
|
||||
echo ""
|
||||
echo "=== 构建 AMD64 架构 ==="
|
||||
if ! build_single_arch "amd64" "amd64"; then
|
||||
echo "❌ AMD64 架构构建失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 构建 ARM64 架构
|
||||
echo ""
|
||||
echo "=== 构建 ARM64 架构 ==="
|
||||
if ! build_single_arch "arm64" "arm64"; then
|
||||
echo "❌ ARM64 架构构建失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建多架构 manifest
|
||||
echo ""
|
||||
echo "=== 创建多架构 Manifest ==="
|
||||
create_multiarch_manifest
|
||||
|
||||
echo ""
|
||||
echo "🎉 多架构构建完成!"
|
||||
echo ""
|
||||
echo "📊 构建摘要:"
|
||||
echo " AMD64: $REGISTRY/ljwx-boot:$LJWX_VERSION-amd64"
|
||||
echo " ARM64: $REGISTRY/ljwx-boot:$LJWX_VERSION-arm64"
|
||||
echo " 多架构: $REGISTRY/ljwx-boot:$LJWX_VERSION"
|
||||
echo " 多架构: $REGISTRY/ljwx-boot:latest"
|
||||
echo ""
|
||||
echo "💡 使用方式:"
|
||||
echo " docker pull $REGISTRY/ljwx-boot:$LJWX_VERSION"
|
||||
echo " Docker会自动选择适合当前架构的镜像"
|
||||
}
|
||||
|
||||
# 执行主程序
|
||||
main "$@"
|
||||
@@ -1,51 +0,0 @@
|
||||
# Jenkins CI/CD 测试报告
|
||||
|
||||
## 测试时间
|
||||
2025-07-12 20:25:14
|
||||
|
||||
## 服务状态
|
||||
- ✅ Jenkins: http://localhost:8081/jenkins
|
||||
- ✅ Gitea: http://localhost:3000
|
||||
- ✅ Registry: localhost:5001
|
||||
|
||||
## 测试结果
|
||||
|
||||
### 1. 基础功能测试
|
||||
- [x] Jenkins服务启动
|
||||
- [x] Gitea服务启动
|
||||
- [x] Registry服务启动
|
||||
- [x] 服务间网络连通
|
||||
|
||||
### 2. Docker构建测试
|
||||
- [x] Dockerfile构建
|
||||
- [x] 镜像运行测试
|
||||
- [x] 健康检查
|
||||
|
||||
### 3. Registry集成测试
|
||||
- [x] 镜像推送
|
||||
- [x] 镜像拉取
|
||||
- [x] 标签管理
|
||||
|
||||
### 4. Pipeline配置
|
||||
- [x] 共享库创建
|
||||
- [x] Pipeline模板
|
||||
- [x] 作业配置生成
|
||||
- [x] Webhook配置
|
||||
|
||||
## 配置文件位置
|
||||
- Jenkins配置: `docker/compose/jenkins/`
|
||||
- Pipeline模板: `docker/compose/jenkins/templates/`
|
||||
- 共享库: `docker/compose/jenkins/shared-library/`
|
||||
- 测试项目: `/tmp/jenkins-cicd-test/`
|
||||
|
||||
## 下一步操作
|
||||
1. 在Gitea中创建测试仓库
|
||||
2. 在Jenkins中创建Pipeline作业
|
||||
3. 配置Webhook触发
|
||||
4. 执行完整CI/CD流程测试
|
||||
|
||||
## 相关文档
|
||||
- [Jenkins配置指南](docker/compose/jenkins/CONFIG_GUIDE.md)
|
||||
- [Webhook配置指南](docker/compose/jenkins/WEBHOOK_GUIDE.md)
|
||||
- [Docker最佳实践](docker/compose/jenkins/DOCKER_BEST_PRACTICES.md)
|
||||
- [Pipeline最佳实践](docker/compose/jenkins/PIPELINE_BEST_PRACTICES.md)
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
# LJWX系统环境变量配置
|
||||
# 由generate-config.sh自动生成,请勿手动修改
|
||||
|
||||
# 镜像仓库和版本
|
||||
REGISTRY=crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx
|
||||
MYSQL_VERSION=2.0.1
|
||||
REDIS_VERSION=2.0.1
|
||||
BOOT_VERSION=2.0.1
|
||||
BIGSCREEN_VERSION=2.0.1
|
||||
ADMIN_VERSION=2.0.1
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_HOST=ljwx-mysql
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_DATABASE=test
|
||||
MYSQL_USERNAME=ljwx
|
||||
MYSQL_PASSWORD=123456
|
||||
|
||||
REDIS_HOST=ljwx-redis
|
||||
REDIS_PORT=6379
|
||||
|
||||
# 服务端口
|
||||
ADMIN_PORT=8080
|
||||
BIGSCREEN_PORT=8001
|
||||
BOOT_PORT=8082
|
||||
|
||||
# 生成时间
|
||||
GENERATED_AT=2025-09-06T08:12:09Z
|
||||
@@ -1,153 +0,0 @@
|
||||
# LJWX 灵境万象健康管理系统 - 客户端部署
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 前置要求
|
||||
- Docker 20.0+
|
||||
- Docker Compose 2.0+
|
||||
- Linux/macOS 系统
|
||||
- 2GB+ 可用内存
|
||||
- 10GB+ 可用磁盘空间
|
||||
|
||||
### 一键启动
|
||||
```bash
|
||||
# 下载并解压部署包到服务器
|
||||
wget [部署包下载地址] -O ljwx-client.tar.gz
|
||||
tar -xzf ljwx-client.tar.gz
|
||||
cd ljwx-client
|
||||
|
||||
# 启动系统
|
||||
./start.sh
|
||||
```
|
||||
|
||||
### 系统访问
|
||||
启动完成后,通过以下地址访问:
|
||||
|
||||
- **管理后台**: http://服务器IP
|
||||
- **大屏系统**: http://服务器IP:5000
|
||||
- **后端API**: http://服务器IP:9998
|
||||
|
||||
默认账户:
|
||||
- 用户名: `admin`
|
||||
- 密码: `admin123`
|
||||
|
||||
## 📋 管理命令
|
||||
|
||||
```bash
|
||||
# 查看服务状态
|
||||
./start.sh status
|
||||
|
||||
# 停止服务
|
||||
./start.sh stop
|
||||
|
||||
# 重启服务
|
||||
./start.sh restart
|
||||
|
||||
# 查看所有日志
|
||||
./start.sh logs
|
||||
|
||||
# 查看指定服务日志
|
||||
./start.sh logs ljwx-boot
|
||||
|
||||
# 清理系统(慎用)
|
||||
./start.sh clean
|
||||
|
||||
# 显示帮助
|
||||
./start.sh help
|
||||
```
|
||||
|
||||
## 🔧 配置说明
|
||||
|
||||
### 端口配置
|
||||
编辑 `.env` 文件修改端口:
|
||||
```bash
|
||||
LJWX_ADMIN_PORT=80 # 前端管理系统
|
||||
LJWX_BIGSCREEN_PORT=5000 # 大屏系统
|
||||
LJWX_BOOT_PORT=9998 # 后端API
|
||||
MYSQL_PORT=3306 # 数据库
|
||||
REDIS_PORT=6379 # 缓存
|
||||
```
|
||||
|
||||
### 数据库配置
|
||||
编辑 `.env` 文件修改数据库设置:
|
||||
```bash
|
||||
MYSQL_ROOT_PASSWORD=123456
|
||||
MYSQL_DATABASE=test
|
||||
MYSQL_USER=ljwx
|
||||
MYSQL_PASSWORD=123456
|
||||
```
|
||||
|
||||
## 📂 目录结构
|
||||
|
||||
```
|
||||
ljwx-client/
|
||||
├── start.sh # 一键启动脚本
|
||||
├── docker-compose.yml # Docker编排文件
|
||||
├── .env # 环境变量配置
|
||||
├── README.md # 说明文档
|
||||
├── data/ # 数据持久化
|
||||
│ ├── mysql/ # 数据库数据
|
||||
│ └── redis/ # 缓存数据
|
||||
├── config/ # 配置文件
|
||||
│ ├── mysql/ # 数据库配置
|
||||
│ └── redis/ # 缓存配置
|
||||
├── logs/ # 日志文件
|
||||
│ ├── ljwx-boot/ # 后端日志
|
||||
│ ├── ljwx-bigscreen/ # 大屏日志
|
||||
│ └── nginx/ # 前端日志
|
||||
└── backups/ # 备份文件
|
||||
```
|
||||
|
||||
## 🔍 故障排除
|
||||
|
||||
### 端口占用
|
||||
```bash
|
||||
# 检查端口占用
|
||||
sudo netstat -tlnp | grep :80
|
||||
sudo netstat -tlnp | grep :5000
|
||||
|
||||
# 修改 .env 文件中的端口配置
|
||||
```
|
||||
|
||||
### 服务无法启动
|
||||
```bash
|
||||
# 查看服务状态
|
||||
./start.sh status
|
||||
|
||||
# 查看详细日志
|
||||
./start.sh logs
|
||||
|
||||
# 重启服务
|
||||
./start.sh restart
|
||||
```
|
||||
|
||||
### 数据库连接失败
|
||||
```bash
|
||||
# 检查数据库服务
|
||||
docker logs ljwx-mysql
|
||||
|
||||
# 进入数据库容器
|
||||
docker exec -it ljwx-mysql mysql -u root -p
|
||||
```
|
||||
|
||||
### 清理重新开始
|
||||
```bash
|
||||
# 停止并清理所有数据
|
||||
./start.sh clean
|
||||
|
||||
# 重新启动
|
||||
./start.sh start
|
||||
```
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如遇问题,请联系技术支持:
|
||||
- 📧 邮箱: support@ljwx.com
|
||||
- 📱 电话: 400-XXX-XXXX
|
||||
- 🔧 在线文档: https://docs.ljwx.com
|
||||
|
||||
## 📄 版本信息
|
||||
|
||||
- 系统版本: 2.0.1
|
||||
- 更新日期: 2025-09-06
|
||||
- 兼容性: Docker 20.0+, Linux/macOS
|
||||
@@ -1,63 +0,0 @@
|
||||
# LJWX系统简单配置
|
||||
|
||||
## 📁 文件说明
|
||||
|
||||
- `ljwx.env` - 所有配置都在这里
|
||||
- `docker-compose.yml` - Docker服务编排
|
||||
- `start-ljwx.sh` - 一键启动脚本
|
||||
|
||||
## 🔧 修改配置
|
||||
|
||||
编辑 `ljwx.env` 文件:
|
||||
|
||||
```bash
|
||||
# 数据库配置
|
||||
MYSQL_HOST=ljwx-mysql
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_DATABASE=test
|
||||
MYSQL_USERNAME=ljwx
|
||||
MYSQL_PASSWORD=123456
|
||||
|
||||
# 服务端口
|
||||
ADMIN_PORT=8080
|
||||
BIGSCREEN_PORT=8001
|
||||
BOOT_PORT=8082
|
||||
|
||||
# 镜像版本
|
||||
MYSQL_VERSION=2.0.1
|
||||
BIGSCREEN_VERSION=2.0.1
|
||||
BOOT_VERSION=2.0.1
|
||||
```
|
||||
|
||||
## 🚀 启动系统
|
||||
|
||||
```bash
|
||||
./start-ljwx.sh
|
||||
```
|
||||
|
||||
## 🛠️ 常用命令
|
||||
|
||||
```bash
|
||||
# 启动所有服务
|
||||
docker-compose --env-file ljwx.env up -d
|
||||
|
||||
# 停止所有服务
|
||||
docker-compose down
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f ljwx-bigscreen
|
||||
|
||||
# 重启单个服务
|
||||
docker-compose restart ljwx-bigscreen
|
||||
```
|
||||
|
||||
## 📊 服务地址
|
||||
|
||||
- 管理后台: http://localhost:8080
|
||||
- 大屏系统: http://localhost:8001
|
||||
- 后端API: http://localhost:8082
|
||||
|
||||
就这么简单!所有配置都在 `ljwx.env` 文件里。
|
||||
@@ -1,246 +0,0 @@
|
||||
package com.ljwx.common.config;
|
||||
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* LJWX系统配置加载器 - Java版本
|
||||
* 统一配置管理,支持YAML配置文件和环境变量覆盖
|
||||
*
|
||||
* @author LJWX Team
|
||||
* @version 2.0.1
|
||||
*/
|
||||
@Component
|
||||
@Configuration
|
||||
public class LJWXConfigLoader {
|
||||
|
||||
private Map<String, Object> config;
|
||||
|
||||
@Value("${ljwx.config.path:/app/config/ljwx-config.yaml}")
|
||||
private String configPath;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载配置文件
|
||||
*/
|
||||
private void loadConfig() {
|
||||
String[] possiblePaths = {
|
||||
"/app/config/ljwx-config.yaml", // 容器内路径
|
||||
"/client/config/ljwx-config.yaml", // 挂载路径
|
||||
"client/config/ljwx-config.yaml", // 相对路径
|
||||
"config/ljwx-config.yaml", // 简化路径
|
||||
configPath // 配置的路径
|
||||
};
|
||||
|
||||
for (String path : possiblePaths) {
|
||||
File file = new File(path);
|
||||
if (file.exists()) {
|
||||
try (InputStream input = new FileInputStream(file)) {
|
||||
Yaml yaml = new Yaml();
|
||||
config = yaml.load(input);
|
||||
|
||||
// 应用环境变量覆盖
|
||||
applyEnvOverrides();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
// 继续尝试下一个路径
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("配置文件未找到,请确保ljwx-config.yaml存在");
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用环境变量覆盖
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void applyEnvOverrides() {
|
||||
// 数据库配置覆盖
|
||||
Map<String, Object> database = (Map<String, Object>) config.get("database");
|
||||
if (database != null) {
|
||||
Map<String, Object> mysql = (Map<String, Object>) database.get("mysql");
|
||||
if (mysql != null) {
|
||||
overrideFromEnv("MYSQL_HOST", mysql, "host");
|
||||
overrideFromEnv("MYSQL_PORT", mysql, "port", Integer.class);
|
||||
overrideFromEnv("MYSQL_DATABASE", mysql, "database");
|
||||
overrideFromEnv("MYSQL_USERNAME", mysql, "username");
|
||||
overrideFromEnv("MYSQL_PASSWORD", mysql, "password");
|
||||
}
|
||||
|
||||
Map<String, Object> redis = (Map<String, Object>) database.get("redis");
|
||||
if (redis != null) {
|
||||
overrideFromEnv("REDIS_HOST", redis, "host");
|
||||
overrideFromEnv("REDIS_PORT", redis, "port", Integer.class);
|
||||
overrideFromEnv("REDIS_PASSWORD", redis, "password");
|
||||
}
|
||||
}
|
||||
|
||||
// 服务端口覆盖
|
||||
String serverPort = System.getenv("SERVER_PORT");
|
||||
String serviceName = System.getenv("SERVICE_NAME");
|
||||
if (serverPort != null && serviceName != null) {
|
||||
Map<String, Object> services = (Map<String, Object>) config.get("services");
|
||||
if (services != null && services.containsKey(serviceName)) {
|
||||
Map<String, Object> service = (Map<String, Object>) services.get(serviceName);
|
||||
service.put("port", Integer.valueOf(serverPort));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从环境变量覆盖配置
|
||||
*/
|
||||
private void overrideFromEnv(String envKey, Map<String, Object> configMap, String configKey) {
|
||||
overrideFromEnv(envKey, configMap, configKey, String.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void overrideFromEnv(String envKey, Map<String, Object> configMap, String configKey, Class<T> type) {
|
||||
String envValue = System.getenv(envKey);
|
||||
if (envValue != null) {
|
||||
Object value = envValue;
|
||||
if (type == Integer.class) {
|
||||
value = Integer.valueOf(envValue);
|
||||
} else if (type == Boolean.class) {
|
||||
value = Boolean.valueOf(envValue);
|
||||
}
|
||||
configMap.put(configKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置值,支持点号分隔的嵌套键
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object get(String key, Object defaultValue) {
|
||||
String[] keys = key.split("\\.");
|
||||
Object value = config;
|
||||
|
||||
for (String k : keys) {
|
||||
if (value instanceof Map) {
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
if (map.containsKey(k)) {
|
||||
value = map.get(k);
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置值
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return get(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字符串配置
|
||||
*/
|
||||
public String getString(String key, String defaultValue) {
|
||||
Object value = get(key, defaultValue);
|
||||
return value != null ? value.toString() : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取整数配置
|
||||
*/
|
||||
public Integer getInt(String key, Integer defaultValue) {
|
||||
Object value = get(key, defaultValue);
|
||||
if (value instanceof Integer) {
|
||||
return (Integer) value;
|
||||
} else if (value instanceof String) {
|
||||
try {
|
||||
return Integer.valueOf((String) value);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库配置
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getDatabaseConfig(String dbType) {
|
||||
return (Map<String, Object>) get("database." + dbType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务配置
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getServiceConfig(String serviceName) {
|
||||
return (Map<String, Object>) get("services." + serviceName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取镜像配置
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getImageConfig() {
|
||||
return (Map<String, Object>) get("images", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库连接URL
|
||||
*/
|
||||
public String getDatabaseUrl(String dbType) {
|
||||
Map<String, Object> dbConfig = getDatabaseConfig(dbType);
|
||||
if (dbConfig == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if ("mysql".equals(dbType)) {
|
||||
String host = (String) dbConfig.get("host");
|
||||
Integer port = (Integer) dbConfig.get("port");
|
||||
String database = (String) dbConfig.get("database");
|
||||
String username = (String) dbConfig.get("username");
|
||||
String password = (String) dbConfig.get("password");
|
||||
String charset = (String) dbConfig.getOrDefault("charset", "utf8mb4");
|
||||
|
||||
return String.format("jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=%s&useSSL=false&serverTimezone=Asia/Shanghai",
|
||||
host, port, database, charset);
|
||||
} else if ("redis".equals(dbType)) {
|
||||
String host = (String) dbConfig.get("host");
|
||||
Integer port = (Integer) dbConfig.get("port");
|
||||
String password = (String) dbConfig.get("password");
|
||||
Integer db = (Integer) dbConfig.getOrDefault("db", 0);
|
||||
|
||||
if (password != null && !password.isEmpty()) {
|
||||
return String.format("redis://:%s@%s:%d/%d", password, host, port, db);
|
||||
} else {
|
||||
return String.format("redis://%s:%d/%d", host, port, db);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新加载配置
|
||||
*/
|
||||
public void reload() {
|
||||
loadConfig();
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
# LJWX系统统一配置管理
|
||||
|
||||
本目录包含LJWX系统的统一配置管理工具,支持所有服务统一读取配置信息。
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
client/config/
|
||||
├── ljwx-config.yaml # 主配置文件(YAML格式)
|
||||
├── config_loader.py # Python配置加载器
|
||||
├── config-loader.js # JavaScript配置加载器
|
||||
├── LJWXConfigLoader.java # Java配置加载器
|
||||
├── package.json # JavaScript依赖配置
|
||||
└── README.md # 本文档
|
||||
```
|
||||
|
||||
## 主配置文件
|
||||
|
||||
`ljwx-config.yaml` 是系统的核心配置文件,包含:
|
||||
|
||||
- **系统信息**: 系统名称、版本、环境
|
||||
- **数据库配置**: MySQL、Redis连接信息
|
||||
- **服务端口**: 各服务的端口配置
|
||||
- **镜像版本**: Docker镜像版本信息
|
||||
- **网络配置**: Docker网络设置
|
||||
- **日志配置**: 日志级别和格式
|
||||
- **安全配置**: JWT密钥、CORS设置
|
||||
- **业务配置**: 业务相关的参数
|
||||
|
||||
## 各语言配置加载器
|
||||
|
||||
### Python (ljwx-bigscreen)
|
||||
|
||||
```python
|
||||
# 导入配置加载器
|
||||
from config_loader import get_config, get_database_config, get_service_config
|
||||
|
||||
# 获取配置
|
||||
config = get_config()
|
||||
mysql_config = get_database_config('mysql')
|
||||
service_config = get_service_config('ljwx-bigscreen')
|
||||
|
||||
# 获取具体配置值
|
||||
db_host = config.get('database.mysql.host')
|
||||
service_port = config.get('services.ljwx-bigscreen.port')
|
||||
```
|
||||
|
||||
### JavaScript (ljwx-admin)
|
||||
|
||||
```javascript
|
||||
// 导入配置加载器
|
||||
const { getConfig, getDatabaseConfig, getServiceConfig } = require('./config-loader');
|
||||
|
||||
// 获取配置
|
||||
const config = getConfig();
|
||||
const mysqlConfig = getDatabaseConfig('mysql');
|
||||
const serviceConfig = getServiceConfig('ljwx-admin');
|
||||
|
||||
// 获取具体配置值
|
||||
const dbHost = config.get('database.mysql.host');
|
||||
const servicePort = config.get('services.ljwx-admin.port');
|
||||
```
|
||||
|
||||
### Java (ljwx-boot)
|
||||
|
||||
```java
|
||||
// Spring Boot中使用
|
||||
@Autowired
|
||||
private LJWXConfigLoader configLoader;
|
||||
|
||||
// 获取配置
|
||||
Map<String, Object> mysqlConfig = configLoader.getDatabaseConfig("mysql");
|
||||
Map<String, Object> serviceConfig = configLoader.getServiceConfig("ljwx-boot");
|
||||
|
||||
// 获取具体配置值
|
||||
String dbHost = configLoader.getString("database.mysql.host", "localhost");
|
||||
Integer servicePort = configLoader.getInt("services.ljwx-boot.port", 8082);
|
||||
```
|
||||
|
||||
## 环境变量覆盖
|
||||
|
||||
配置支持环境变量覆盖,优先级:**环境变量 > 配置文件**
|
||||
|
||||
### 数据库配置覆盖
|
||||
|
||||
- `MYSQL_HOST` - MySQL主机地址
|
||||
- `MYSQL_PORT` - MySQL端口
|
||||
- `MYSQL_DATABASE` - 数据库名
|
||||
- `MYSQL_USERNAME` - 数据库用户名
|
||||
- `MYSQL_PASSWORD` - 数据库密码
|
||||
- `REDIS_HOST` - Redis主机地址
|
||||
- `REDIS_PORT` - Redis端口
|
||||
- `REDIS_PASSWORD` - Redis密码
|
||||
|
||||
### 服务端口覆盖
|
||||
|
||||
- `SERVER_PORT` + `SERVICE_NAME` - 特定服务的端口
|
||||
|
||||
## 配置文件路径查找顺序
|
||||
|
||||
各配置加载器会按以下顺序查找配置文件:
|
||||
|
||||
1. `/app/config/ljwx-config.yaml` (容器内路径)
|
||||
2. `/client/config/ljwx-config.yaml` (挂载路径)
|
||||
3. `client/config/ljwx-config.yaml` (相对路径)
|
||||
4. `config/ljwx-config.yaml` (简化路径)
|
||||
5. 指定的自定义路径
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 安装依赖
|
||||
|
||||
**Python依赖:**
|
||||
```bash
|
||||
pip install PyYAML
|
||||
```
|
||||
|
||||
**JavaScript依赖:**
|
||||
```bash
|
||||
cd client/config
|
||||
npm install
|
||||
```
|
||||
|
||||
**Java依赖:**
|
||||
在`pom.xml`或`build.gradle`中添加SnakeYAML依赖。
|
||||
|
||||
### 2. 配置文件挂载
|
||||
|
||||
在Docker容器中挂载配置文件:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
volumes:
|
||||
- ./client/config/ljwx-config.yaml:/app/config/ljwx-config.yaml:ro
|
||||
```
|
||||
|
||||
### 3. 在应用中使用
|
||||
|
||||
各服务在启动时自动加载配置,无需额外配置。
|
||||
|
||||
## 配置生成工具
|
||||
|
||||
使用 `generate-config.sh` 可以从统一配置生成各服务的运行时配置:
|
||||
|
||||
```bash
|
||||
cd client
|
||||
./generate-config.sh
|
||||
```
|
||||
|
||||
生成的文件:
|
||||
- `docker-compose.yml` - Docker Compose配置
|
||||
- `.env` - 环境变量文件
|
||||
- `config/bigscreen/config.py` - Bigscreen配置
|
||||
- `config/boot/application-prod.yml` - Boot配置
|
||||
|
||||
## 配置更新
|
||||
|
||||
1. 修改 `ljwx-config.yaml` 文件
|
||||
2. 重新生成配置: `./generate-config.sh`
|
||||
3. 重启相关服务: `docker-compose restart`
|
||||
|
||||
## 安全注意事项
|
||||
|
||||
- 配置文件包含敏感信息(数据库密码等),请妥善保管
|
||||
- 生产环境建议使用环境变量覆盖敏感配置
|
||||
- 配置文件应使用只读挂载到容器中
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 配置文件未找到
|
||||
|
||||
确保配置文件路径正确,检查容器内挂载是否成功:
|
||||
|
||||
```bash
|
||||
docker exec -it ljwx-bigscreen ls -la /app/config/
|
||||
```
|
||||
|
||||
### 配置加载失败
|
||||
|
||||
检查YAML文件格式是否正确:
|
||||
|
||||
```bash
|
||||
python3 -c "import yaml; yaml.safe_load(open('client/config/ljwx-config.yaml'))"
|
||||
```
|
||||
|
||||
### 环境变量不生效
|
||||
|
||||
确认环境变量名称正确,并在容器启动时传入:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- MYSQL_HOST=new-mysql-host
|
||||
- MYSQL_PORT=3307
|
||||
```
|
||||
@@ -1,137 +0,0 @@
|
||||
# LJWX系统统一配置管理 - 完成总结
|
||||
|
||||
## 🎉 已完成的工作
|
||||
|
||||
### ✅ 1. 核心配置文件
|
||||
- **ljwx-config.yaml** - 主配置文件(YAML格式)
|
||||
- **ljwx-config.json** - 兼容配置文件(JSON格式,无需外部依赖)
|
||||
|
||||
### ✅ 2. 多语言配置加载器
|
||||
- **config_loader.py** - Python版配置加载器(ljwx-bigscreen)
|
||||
- **config-loader.js** - JavaScript版配置加载器(ljwx-admin)
|
||||
- **LJWXConfigLoader.java** - Java版配置加载器(ljwx-boot)
|
||||
|
||||
### ✅ 3. 自动化工具
|
||||
- **generate-config.sh** - 配置生成脚本
|
||||
- **docker-compose.template.yml** - Docker Compose模板
|
||||
- **package.json** - JavaScript依赖管理
|
||||
|
||||
### ✅ 4. 生成的运行时配置
|
||||
- **docker-compose.yml** - 完整的Docker Compose配置
|
||||
- **.env** - 环境变量配置文件
|
||||
- **config/bigscreen/config.py** - Bigscreen专用配置
|
||||
- **config/boot/application-prod.yml** - Spring Boot生产配置
|
||||
|
||||
### ✅ 5. 文档和示例
|
||||
- **README.md** - 详细使用文档
|
||||
- **integration-examples.md** - 各服务集成示例
|
||||
- **SUMMARY.md** - 本总结文档
|
||||
|
||||
## 📋 配置涵盖内容
|
||||
|
||||
### 🗄️ 数据库配置
|
||||
```yaml
|
||||
database:
|
||||
mysql:
|
||||
host: "ljwx-mysql"
|
||||
port: 3306
|
||||
database: "test"
|
||||
username: "ljwx"
|
||||
password: "123456"
|
||||
redis:
|
||||
host: "ljwx-redis"
|
||||
port: 6379
|
||||
```
|
||||
|
||||
### 🚀 服务端口配置
|
||||
```yaml
|
||||
services:
|
||||
ljwx-admin: 8080
|
||||
ljwx-bigscreen: 8001
|
||||
ljwx-boot: 8082
|
||||
```
|
||||
|
||||
### 🐳 镜像版本配置
|
||||
```yaml
|
||||
images:
|
||||
registry: "crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx"
|
||||
ljwx-mysql: "2.0.1"
|
||||
ljwx-redis: "2.0.1"
|
||||
ljwx-admin: "2.0.1"
|
||||
ljwx-bigscreen: "2.0.1"
|
||||
ljwx-boot: "2.0.1"
|
||||
```
|
||||
|
||||
## 🔧 使用方法
|
||||
|
||||
### 1. 生成配置
|
||||
```bash
|
||||
cd client
|
||||
./generate-config.sh
|
||||
```
|
||||
|
||||
### 2. 启动服务
|
||||
```bash
|
||||
cd client
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 3. 各服务自动读取统一配置
|
||||
- **ljwx-bigscreen**: 通过Python配置加载器
|
||||
- **ljwx-boot**: 通过Java配置加载器
|
||||
- **ljwx-admin**: 通过JavaScript配置加载器
|
||||
|
||||
## 🌟 核心特性
|
||||
|
||||
### ✨ 统一管理
|
||||
- 所有配置集中在一个文件中
|
||||
- 避免配置分散和不一致问题
|
||||
|
||||
### 🔄 环境变量覆盖
|
||||
- 支持通过环境变量覆盖配置
|
||||
- 便于不同环境部署
|
||||
|
||||
### 🎯 多语言支持
|
||||
- Python、JavaScript、Java三种语言的加载器
|
||||
- 统一的API接口设计
|
||||
|
||||
### 🚢 容器化友好
|
||||
- 配置文件可直接挂载到容器
|
||||
- 支持Docker Compose自动化部署
|
||||
|
||||
### 📝 自动生成
|
||||
- 一键生成所有运行时配置
|
||||
- 减少手动配置错误
|
||||
|
||||
## 🔍 配置验证
|
||||
|
||||
所有配置加载器都包含:
|
||||
- ✅ 配置文件存在性检查
|
||||
- ✅ 必要配置项完整性验证
|
||||
- ✅ 环境变量优先级处理
|
||||
- ✅ 默认值和备用配置
|
||||
|
||||
## 🚨 注意事项
|
||||
|
||||
1. **安全**: 配置文件包含敏感信息,请妥善保管
|
||||
2. **权限**: 配置文件应以只读方式挂载到容器
|
||||
3. **更新**: 修改配置后需重启相关服务生效
|
||||
4. **备份**: 重要配置文件应纳入版本控制和备份
|
||||
|
||||
## 🎯 下一步建议
|
||||
|
||||
1. **集成现有服务**: 根据integration-examples.md更新各服务代码
|
||||
2. **测试配置**: 在开发环境测试配置加载和服务启动
|
||||
3. **生产部署**: 在生产环境使用环境变量覆盖敏感配置
|
||||
4. **监控告警**: 添加配置相关的监控和告警
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如需帮助,请参考:
|
||||
- `README.md` - 详细使用指南
|
||||
- `integration-examples.md` - 集成示例
|
||||
- 测试各配置加载器:运行对应语言的测试代码
|
||||
|
||||
---
|
||||
|
||||
✅ **LJWX系统统一配置管理已完成,所有服务现在可以使用统一的配置文件!** 🚀
|
||||
@@ -1,50 +0,0 @@
|
||||
# ljwx-bigscreen配置文件
|
||||
# 由generate-config.sh自动生成
|
||||
|
||||
# 从统一配置加载
|
||||
import sys
|
||||
import os
|
||||
sys.path.append('/app/config')
|
||||
sys.path.append('/client/config')
|
||||
|
||||
try:
|
||||
from config_loader import get_database_config, get_service_config, get_config
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_CONFIG = get_database_config('mysql')
|
||||
REDIS_CONFIG = get_database_config('redis')
|
||||
|
||||
# 服务配置
|
||||
SERVICE_CONFIG = get_service_config('ljwx-bigscreen')
|
||||
|
||||
# 应用配置
|
||||
APP_CONFIG = {
|
||||
'HOST': '0.0.0.0',
|
||||
'PORT': SERVICE_CONFIG.get('port', 8001),
|
||||
'DEBUG': False,
|
||||
'SECRET_KEY': get_config().get('security.jwt_secret', 'ljwx-secret'),
|
||||
}
|
||||
|
||||
except ImportError:
|
||||
# 备用静态配置
|
||||
MYSQL_CONFIG = {
|
||||
'host': 'ljwx-mysql',
|
||||
'port': 3306,
|
||||
'database': 'test',
|
||||
'username': 'ljwx',
|
||||
'password': '123456'
|
||||
}
|
||||
|
||||
REDIS_CONFIG = {
|
||||
'host': 'ljwx-redis',
|
||||
'port': 6379,
|
||||
'password': '',
|
||||
'db': 0
|
||||
}
|
||||
|
||||
APP_CONFIG = {
|
||||
'HOST': '0.0.0.0',
|
||||
'PORT': 8001,
|
||||
'DEBUG': False,
|
||||
'SECRET_KEY': 'ljwx-secret',
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
# ljwx-boot生产环境配置文件
|
||||
# 由generate-config.sh自动生成
|
||||
|
||||
server:
|
||||
port: 8082
|
||||
servlet:
|
||||
context-path: /api
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: prod
|
||||
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://ljwx-mysql:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: ljwx
|
||||
password: 123456
|
||||
|
||||
hikari:
|
||||
pool-name: ljwx-boot-pool
|
||||
minimum-idle: 5
|
||||
maximum-pool-size: 20
|
||||
connection-timeout: 30000
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
|
||||
redis:
|
||||
host: ljwx-redis
|
||||
port: 6379
|
||||
database: 0
|
||||
timeout: 5000
|
||||
jedis:
|
||||
pool:
|
||||
max-active: 50
|
||||
max-wait: 3000
|
||||
max-idle: 20
|
||||
min-idle: 2
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
show-sql: false
|
||||
database-platform: org.hibernate.dialect.MySQL8Dialect
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
com.ljwx: INFO
|
||||
file:
|
||||
name: /app/logs/ljwx-boot.log
|
||||
pattern:
|
||||
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||
|
||||
# 管理端点
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info,metrics
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
@@ -1,265 +0,0 @@
|
||||
/**
|
||||
* LJWX系统配置加载器 - JavaScript版本
|
||||
* 统一配置管理,支持YAML配置文件和环境变量覆盖
|
||||
*
|
||||
* @author LJWX Team
|
||||
* @version 2.0.1
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
class LJWXConfigLoader {
|
||||
constructor(configPath = null) {
|
||||
this.configPath = configPath;
|
||||
this.config = null;
|
||||
this.loadConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载配置文件
|
||||
*/
|
||||
loadConfig() {
|
||||
const possiblePaths = [
|
||||
'/app/config/ljwx-config.yaml', // 容器内路径
|
||||
'/client/config/ljwx-config.yaml', // 挂载路径
|
||||
path.join(__dirname, 'ljwx-config.yaml'), // 同级目录
|
||||
'client/config/ljwx-config.yaml', // 相对路径
|
||||
'config/ljwx-config.yaml', // 简化路径
|
||||
this.configPath // 指定路径
|
||||
].filter(p => p);
|
||||
|
||||
for (const configPath of possiblePaths) {
|
||||
if (fs.existsSync(configPath)) {
|
||||
try {
|
||||
const fileContents = fs.readFileSync(configPath, 'utf8');
|
||||
this.config = yaml.load(fileContents);
|
||||
|
||||
// 应用环境变量覆盖
|
||||
this.applyEnvOverrides();
|
||||
return;
|
||||
} catch (error) {
|
||||
// 继续尝试下一个路径
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('配置文件未找到,请确保ljwx-config.yaml存在');
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用环境变量覆盖
|
||||
*/
|
||||
applyEnvOverrides() {
|
||||
// 数据库配置覆盖
|
||||
if (process.env.MYSQL_HOST) {
|
||||
this.config.database.mysql.host = process.env.MYSQL_HOST;
|
||||
}
|
||||
if (process.env.MYSQL_PORT) {
|
||||
this.config.database.mysql.port = parseInt(process.env.MYSQL_PORT);
|
||||
}
|
||||
if (process.env.MYSQL_DATABASE) {
|
||||
this.config.database.mysql.database = process.env.MYSQL_DATABASE;
|
||||
}
|
||||
if (process.env.MYSQL_USERNAME) {
|
||||
this.config.database.mysql.username = process.env.MYSQL_USERNAME;
|
||||
}
|
||||
if (process.env.MYSQL_PASSWORD) {
|
||||
this.config.database.mysql.password = process.env.MYSQL_PASSWORD;
|
||||
}
|
||||
|
||||
if (process.env.REDIS_HOST) {
|
||||
this.config.database.redis.host = process.env.REDIS_HOST;
|
||||
}
|
||||
if (process.env.REDIS_PORT) {
|
||||
this.config.database.redis.port = parseInt(process.env.REDIS_PORT);
|
||||
}
|
||||
if (process.env.REDIS_PASSWORD) {
|
||||
this.config.database.redis.password = process.env.REDIS_PASSWORD;
|
||||
}
|
||||
|
||||
// 服务端口覆盖
|
||||
if (process.env.SERVER_PORT && process.env.SERVICE_NAME) {
|
||||
const serviceName = process.env.SERVICE_NAME;
|
||||
if (this.config.services[serviceName]) {
|
||||
this.config.services[serviceName].port = parseInt(process.env.SERVER_PORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置值,支持点号分隔的嵌套键
|
||||
*
|
||||
* @param {string} key - 配置键,如 'database.mysql.host'
|
||||
* @param {any} defaultValue - 默认值
|
||||
* @returns {any} 配置值
|
||||
*/
|
||||
get(key, defaultValue = null) {
|
||||
const keys = key.split('.');
|
||||
let value = this.config;
|
||||
|
||||
for (const k of keys) {
|
||||
if (value && typeof value === 'object' && k in value) {
|
||||
value = value[k];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库配置
|
||||
*
|
||||
* @param {string} dbType - 数据库类型,如 'mysql', 'redis'
|
||||
* @returns {object} 数据库配置对象
|
||||
*/
|
||||
getDatabaseConfig(dbType = 'mysql') {
|
||||
return this.get(`database.${dbType}`, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务配置
|
||||
*
|
||||
* @param {string} serviceName - 服务名称
|
||||
* @returns {object} 服务配置对象
|
||||
*/
|
||||
getServiceConfig(serviceName) {
|
||||
return this.get(`services.${serviceName}`, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取镜像配置
|
||||
*
|
||||
* @returns {object} 镜像配置对象
|
||||
*/
|
||||
getImageConfig() {
|
||||
return this.get('images', {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库连接URL
|
||||
*
|
||||
* @param {string} dbType - 数据库类型
|
||||
* @returns {string} 数据库连接URL
|
||||
*/
|
||||
getDatabaseUrl(dbType = 'mysql') {
|
||||
const dbConfig = this.getDatabaseConfig(dbType);
|
||||
|
||||
if (dbType === 'mysql') {
|
||||
const { host, port, database, username, password, charset = 'utf8mb4' } = dbConfig;
|
||||
return `mysql://${username}:${password}@${host}:${port}/${database}?charset=${charset}`;
|
||||
} else if (dbType === 'redis') {
|
||||
const { host, port, password = '', db = 0 } = dbConfig;
|
||||
const passwordPart = password ? `:${password}@` : '';
|
||||
return `redis://${passwordPart}${host}:${port}/${db}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新加载配置
|
||||
*/
|
||||
reload() {
|
||||
this.loadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
// 全局配置实例
|
||||
let _configLoader = null;
|
||||
|
||||
/**
|
||||
* 获取全局配置实例
|
||||
*
|
||||
* @returns {LJWXConfigLoader} 配置加载器实例
|
||||
*/
|
||||
function getConfig() {
|
||||
if (_configLoader === null) {
|
||||
_configLoader = new LJWXConfigLoader();
|
||||
}
|
||||
return _configLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新加载全局配置
|
||||
*/
|
||||
function reloadConfig() {
|
||||
if (_configLoader !== null) {
|
||||
_configLoader.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// 便捷函数
|
||||
/**
|
||||
* 获取数据库配置
|
||||
*/
|
||||
function getDatabaseConfig(dbType = 'mysql') {
|
||||
return getConfig().getDatabaseConfig(dbType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务配置
|
||||
*/
|
||||
function getServiceConfig(serviceName) {
|
||||
return getConfig().getServiceConfig(serviceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库连接URL
|
||||
*/
|
||||
function getDatabaseUrl(dbType = 'mysql') {
|
||||
return getConfig().getDatabaseUrl(dbType);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
LJWXConfigLoader,
|
||||
getConfig,
|
||||
reloadConfig,
|
||||
getDatabaseConfig,
|
||||
getServiceConfig,
|
||||
getDatabaseUrl
|
||||
};
|
||||
|
||||
// 如果是直接运行此文件,进行测试
|
||||
if (require.main === module) {
|
||||
try {
|
||||
const config = getConfig();
|
||||
|
||||
console.log('=== LJWX配置测试 ===');
|
||||
console.log(`系统名称: ${config.get('system.name')}`);
|
||||
console.log(`系统版本: ${config.get('system.version')}`);
|
||||
console.log('');
|
||||
|
||||
console.log('=== 数据库配置 ===');
|
||||
const mysqlConfig = getDatabaseConfig('mysql');
|
||||
console.log(`MySQL:`, mysqlConfig);
|
||||
console.log(`MySQL URL: ${getDatabaseUrl('mysql')}`);
|
||||
console.log('');
|
||||
|
||||
const redisConfig = getDatabaseConfig('redis');
|
||||
console.log(`Redis:`, redisConfig);
|
||||
console.log(`Redis URL: ${getDatabaseUrl('redis')}`);
|
||||
console.log('');
|
||||
|
||||
console.log('=== 服务配置 ===');
|
||||
['ljwx-admin', 'ljwx-bigscreen', 'ljwx-boot'].forEach(service => {
|
||||
const serviceConfig = getServiceConfig(service);
|
||||
console.log(`${service}:`, serviceConfig);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
console.log('=== 镜像配置 ===');
|
||||
const imageConfig = config.getImageConfig();
|
||||
console.log(`镜像仓库: ${imageConfig.registry}`);
|
||||
console.log(`Admin镜像: ${imageConfig['ljwx-admin']}`);
|
||||
console.log(`Bigscreen镜像: ${imageConfig['ljwx-bigscreen']}`);
|
||||
console.log(`Boot镜像: ${imageConfig['ljwx-boot']}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('配置加载测试失败:', error.message);
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
LJWX系统配置加载器
|
||||
统一配置管理,支持YAML配置文件和环境变量覆盖
|
||||
"""
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from typing import Dict, Any, Optional
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class LJWXConfigLoader:
|
||||
"""LJWX配置加载器"""
|
||||
|
||||
def __init__(self, config_path: Optional[str] = None):
|
||||
"""
|
||||
初始化配置加载器
|
||||
|
||||
Args:
|
||||
config_path: 配置文件路径,默认为当前目录下的ljwx-config.yaml
|
||||
"""
|
||||
if config_path is None:
|
||||
# 尝试多个可能的配置文件位置
|
||||
possible_paths = [
|
||||
"/app/config/ljwx-config.yaml", # 容器内路径
|
||||
"/client/config/ljwx-config.yaml", # 挂载路径
|
||||
os.path.join(os.path.dirname(__file__), "ljwx-config.yaml"), # 同级目录
|
||||
"client/config/ljwx-config.yaml", # 相对路径
|
||||
"config/ljwx-config.yaml" # 简化路径
|
||||
]
|
||||
|
||||
config_path = None
|
||||
for path in possible_paths:
|
||||
if os.path.exists(path):
|
||||
config_path = path
|
||||
break
|
||||
|
||||
if config_path is None:
|
||||
raise FileNotFoundError("配置文件未找到,请确保ljwx-config.yaml存在")
|
||||
|
||||
self.config_path = config_path
|
||||
self.config = self._load_config()
|
||||
|
||||
def _load_config(self) -> Dict[str, Any]:
|
||||
"""加载配置文件"""
|
||||
try:
|
||||
with open(self.config_path, 'r', encoding='utf-8') as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
# 环境变量覆盖
|
||||
config = self._apply_env_overrides(config)
|
||||
|
||||
return config
|
||||
except Exception as e:
|
||||
raise Exception(f"加载配置文件失败: {e}")
|
||||
|
||||
def _apply_env_overrides(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""应用环境变量覆盖"""
|
||||
# 数据库配置覆盖
|
||||
if 'MYSQL_HOST' in os.environ:
|
||||
config['database']['mysql']['host'] = os.environ['MYSQL_HOST']
|
||||
if 'MYSQL_PORT' in os.environ:
|
||||
config['database']['mysql']['port'] = int(os.environ['MYSQL_PORT'])
|
||||
if 'MYSQL_DATABASE' in os.environ:
|
||||
config['database']['mysql']['database'] = os.environ['MYSQL_DATABASE']
|
||||
if 'MYSQL_USERNAME' in os.environ:
|
||||
config['database']['mysql']['username'] = os.environ['MYSQL_USERNAME']
|
||||
if 'MYSQL_PASSWORD' in os.environ:
|
||||
config['database']['mysql']['password'] = os.environ['MYSQL_PASSWORD']
|
||||
|
||||
if 'REDIS_HOST' in os.environ:
|
||||
config['database']['redis']['host'] = os.environ['REDIS_HOST']
|
||||
if 'REDIS_PORT' in os.environ:
|
||||
config['database']['redis']['port'] = int(os.environ['REDIS_PORT'])
|
||||
if 'REDIS_PASSWORD' in os.environ:
|
||||
config['database']['redis']['password'] = os.environ['REDIS_PASSWORD']
|
||||
|
||||
# 服务端口覆盖
|
||||
if 'SERVER_PORT' in os.environ:
|
||||
service_name = os.environ.get('SERVICE_NAME', 'ljwx-boot')
|
||||
if service_name in config['services']:
|
||||
config['services'][service_name]['port'] = int(os.environ['SERVER_PORT'])
|
||||
|
||||
return config
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""
|
||||
获取配置值,支持点号分隔的嵌套键
|
||||
|
||||
Args:
|
||||
key: 配置键,如 'database.mysql.host'
|
||||
default: 默认值
|
||||
|
||||
Returns:
|
||||
配置值
|
||||
"""
|
||||
keys = key.split('.')
|
||||
value = self.config
|
||||
|
||||
for k in keys:
|
||||
if isinstance(value, dict) and k in value:
|
||||
value = value[k]
|
||||
else:
|
||||
return default
|
||||
|
||||
return value
|
||||
|
||||
def get_database_config(self, db_type: str = 'mysql') -> Dict[str, Any]:
|
||||
"""获取数据库配置"""
|
||||
return self.get(f'database.{db_type}', {})
|
||||
|
||||
def get_service_config(self, service_name: str) -> Dict[str, Any]:
|
||||
"""获取服务配置"""
|
||||
return self.get(f'services.{service_name}', {})
|
||||
|
||||
def get_image_config(self) -> Dict[str, str]:
|
||||
"""获取镜像配置"""
|
||||
return self.get('images', {})
|
||||
|
||||
def get_database_url(self, db_type: str = 'mysql') -> str:
|
||||
"""获取数据库连接URL"""
|
||||
db_config = self.get_database_config(db_type)
|
||||
|
||||
if db_type == 'mysql':
|
||||
return f"mysql+pymysql://{db_config['username']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}?charset={db_config.get('charset', 'utf8mb4')}"
|
||||
elif db_type == 'redis':
|
||||
password_part = f":{db_config['password']}@" if db_config.get('password') else ""
|
||||
return f"redis://{password_part}{db_config['host']}:{db_config['port']}/{db_config.get('db', 0)}"
|
||||
|
||||
return ""
|
||||
|
||||
def reload(self):
|
||||
"""重新加载配置"""
|
||||
self.config = self._load_config()
|
||||
|
||||
|
||||
# 全局配置实例
|
||||
_config_loader = None
|
||||
|
||||
def get_config() -> LJWXConfigLoader:
|
||||
"""获取全局配置实例"""
|
||||
global _config_loader
|
||||
if _config_loader is None:
|
||||
_config_loader = LJWXConfigLoader()
|
||||
return _config_loader
|
||||
|
||||
def reload_config():
|
||||
"""重新加载全局配置"""
|
||||
global _config_loader
|
||||
if _config_loader is not None:
|
||||
_config_loader.reload()
|
||||
|
||||
# 便捷函数
|
||||
def get_database_config(db_type: str = 'mysql') -> Dict[str, Any]:
|
||||
"""获取数据库配置"""
|
||||
return get_config().get_database_config(db_type)
|
||||
|
||||
def get_service_config(service_name: str) -> Dict[str, Any]:
|
||||
"""获取服务配置"""
|
||||
return get_config().get_service_config(service_name)
|
||||
|
||||
def get_database_url(db_type: str = 'mysql') -> str:
|
||||
"""获取数据库连接URL"""
|
||||
return get_config().get_database_url(db_type)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 测试配置加载
|
||||
config = get_config()
|
||||
|
||||
print("=== LJWX配置测试 ===")
|
||||
print(f"系统名称: {config.get('system.name')}")
|
||||
print(f"系统版本: {config.get('system.version')}")
|
||||
print()
|
||||
|
||||
print("=== 数据库配置 ===")
|
||||
mysql_config = get_database_config('mysql')
|
||||
print(f"MySQL: {mysql_config}")
|
||||
print(f"MySQL URL: {get_database_url('mysql')}")
|
||||
print()
|
||||
|
||||
redis_config = get_database_config('redis')
|
||||
print(f"Redis: {redis_config}")
|
||||
print(f"Redis URL: {get_database_url('redis')}")
|
||||
print()
|
||||
|
||||
print("=== 服务配置 ===")
|
||||
for service in ['ljwx-admin', 'ljwx-bigscreen', 'ljwx-boot']:
|
||||
service_config = get_service_config(service)
|
||||
print(f"{service}: {service_config}")
|
||||
print()
|
||||
|
||||
print("=== 镜像配置 ===")
|
||||
image_config = config.get_image_config()
|
||||
print(f"镜像仓库: {image_config.get('registry')}")
|
||||
print(f"Admin镜像: {image_config.get('ljwx-admin')}")
|
||||
print(f"Bigscreen镜像: {image_config.get('ljwx-bigscreen')}")
|
||||
print(f"Boot镜像: {image_config.get('ljwx-boot')}")
|
||||
@@ -1,394 +0,0 @@
|
||||
# LJWX系统统一配置集成示例
|
||||
|
||||
## ljwx-bigscreen (Python Flask) 集成示例
|
||||
|
||||
### 1. 修改主应用文件
|
||||
|
||||
在 `ljwx-bigscreen/bigscreen/app.py` 或 `run.py` 中:
|
||||
|
||||
```python
|
||||
# 原有代码
|
||||
import os
|
||||
from flask import Flask
|
||||
# ... 其他导入
|
||||
|
||||
# 新增:导入统一配置
|
||||
import sys
|
||||
sys.path.append('/client/config')
|
||||
sys.path.append('/app/config')
|
||||
|
||||
try:
|
||||
from config_loader import get_database_config, get_service_config, get_config
|
||||
|
||||
# 从统一配置加载
|
||||
mysql_config = get_database_config('mysql')
|
||||
redis_config = get_database_config('redis')
|
||||
service_config = get_service_config('ljwx-bigscreen')
|
||||
|
||||
# 数据库连接配置
|
||||
DATABASE_CONFIG = {
|
||||
'host': mysql_config['host'],
|
||||
'port': mysql_config['port'],
|
||||
'database': mysql_config['database'],
|
||||
'username': mysql_config['username'],
|
||||
'password': mysql_config['password'],
|
||||
'charset': mysql_config.get('charset', 'utf8mb4')
|
||||
}
|
||||
|
||||
# Redis配置
|
||||
REDIS_CONFIG = {
|
||||
'host': redis_config['host'],
|
||||
'port': redis_config['port'],
|
||||
'password': redis_config.get('password', ''),
|
||||
'db': redis_config.get('db', 0)
|
||||
}
|
||||
|
||||
# 应用配置
|
||||
APP_PORT = service_config['port']
|
||||
|
||||
except ImportError:
|
||||
# 备用配置(兼容现有部署)
|
||||
DATABASE_CONFIG = {
|
||||
'host': os.getenv('MYSQL_HOST', 'ljwx-mysql'),
|
||||
'port': int(os.getenv('MYSQL_PORT', 3306)),
|
||||
'database': os.getenv('MYSQL_DATABASE', 'test'),
|
||||
'username': os.getenv('MYSQL_USERNAME', 'ljwx'),
|
||||
'password': os.getenv('MYSQL_PASSWORD', '123456'),
|
||||
'charset': 'utf8mb4'
|
||||
}
|
||||
|
||||
REDIS_CONFIG = {
|
||||
'host': os.getenv('REDIS_HOST', 'ljwx-redis'),
|
||||
'port': int(os.getenv('REDIS_PORT', 6379)),
|
||||
'password': os.getenv('REDIS_PASSWORD', ''),
|
||||
'db': int(os.getenv('REDIS_DB', 0))
|
||||
}
|
||||
|
||||
APP_PORT = int(os.getenv('SERVER_PORT', 8001))
|
||||
|
||||
# Flask应用初始化
|
||||
app = Flask(__name__)
|
||||
|
||||
# 使用统一配置
|
||||
app.config.update({
|
||||
'MYSQL_HOST': DATABASE_CONFIG['host'],
|
||||
'MYSQL_PORT': DATABASE_CONFIG['port'],
|
||||
'MYSQL_DATABASE': DATABASE_CONFIG['database'],
|
||||
'MYSQL_USER': DATABASE_CONFIG['username'],
|
||||
'MYSQL_PASSWORD': DATABASE_CONFIG['password'],
|
||||
'REDIS_HOST': REDIS_CONFIG['host'],
|
||||
'REDIS_PORT': REDIS_CONFIG['port'],
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=APP_PORT, debug=False)
|
||||
```
|
||||
|
||||
### 2. 修改数据库连接模块
|
||||
|
||||
在数据库连接文件中:
|
||||
|
||||
```python
|
||||
# 原有代码中的数据库连接部分
|
||||
import pymysql
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
# 使用统一配置
|
||||
from app import DATABASE_CONFIG
|
||||
|
||||
# SQLAlchemy连接
|
||||
def get_database_engine():
|
||||
connection_url = f"mysql+pymysql://{DATABASE_CONFIG['username']}:{DATABASE_CONFIG['password']}@{DATABASE_CONFIG['host']}:{DATABASE_CONFIG['port']}/{DATABASE_CONFIG['database']}?charset={DATABASE_CONFIG['charset']}"
|
||||
return create_engine(connection_url, pool_pre_ping=True, pool_recycle=3600)
|
||||
|
||||
# PyMySQL直接连接
|
||||
def get_mysql_connection():
|
||||
return pymysql.connect(
|
||||
host=DATABASE_CONFIG['host'],
|
||||
port=DATABASE_CONFIG['port'],
|
||||
user=DATABASE_CONFIG['username'],
|
||||
password=DATABASE_CONFIG['password'],
|
||||
database=DATABASE_CONFIG['database'],
|
||||
charset=DATABASE_CONFIG['charset'],
|
||||
cursorclass=pymysql.cursors.DictCursor
|
||||
)
|
||||
```
|
||||
|
||||
## ljwx-boot (Spring Boot) 集成示例
|
||||
|
||||
### 1. 添加配置类
|
||||
|
||||
创建 `src/main/java/com/ljwx/common/config/LJWXConfiguration.java`:
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class LJWXConfiguration {
|
||||
|
||||
@Autowired
|
||||
private LJWXConfigLoader configLoader;
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.datasource")
|
||||
public DataSourceProperties dataSourceProperties() {
|
||||
DataSourceProperties properties = new DataSourceProperties();
|
||||
|
||||
Map<String, Object> mysqlConfig = configLoader.getDatabaseConfig("mysql");
|
||||
if (mysqlConfig != null) {
|
||||
String host = (String) mysqlConfig.get("host");
|
||||
Integer port = (Integer) mysqlConfig.get("port");
|
||||
String database = (String) mysqlConfig.get("database");
|
||||
String username = (String) mysqlConfig.get("username");
|
||||
String password = (String) mysqlConfig.get("password");
|
||||
|
||||
String url = String.format("jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai",
|
||||
host, port, database);
|
||||
|
||||
properties.setUrl(url);
|
||||
properties.setUsername(username);
|
||||
properties.setPassword(password);
|
||||
properties.setDriverClassName("com.mysql.cj.jdbc.Driver");
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "spring.redis")
|
||||
public LettuceConnectionFactory redisConnectionFactory() {
|
||||
Map<String, Object> redisConfig = configLoader.getDatabaseConfig("redis");
|
||||
if (redisConfig != null) {
|
||||
String host = (String) redisConfig.get("host");
|
||||
Integer port = (Integer) redisConfig.get("port");
|
||||
String password = (String) redisConfig.get("password");
|
||||
|
||||
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
|
||||
config.setHostName(host);
|
||||
config.setPort(port);
|
||||
if (password != null && !password.isEmpty()) {
|
||||
config.setPassword(password);
|
||||
}
|
||||
|
||||
return new LettuceConnectionFactory(config);
|
||||
}
|
||||
|
||||
return new LettuceConnectionFactory();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 修改应用启动类
|
||||
|
||||
在 `Application.java` 中:
|
||||
|
||||
```java
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = {"com.ljwx"})
|
||||
public class LJWXBootApplication {
|
||||
|
||||
@Autowired
|
||||
private LJWXConfigLoader configLoader;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LJWXBootApplication.class, args);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// 打印配置信息用于调试
|
||||
Map<String, Object> serviceConfig = configLoader.getServiceConfig("ljwx-boot");
|
||||
log.info("LJWX Boot服务配置: {}", serviceConfig);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ljwx-admin (Vue.js + Node.js) 集成示例
|
||||
|
||||
### 1. 在构建配置中使用
|
||||
|
||||
在 `vite.config.js` 或 `webpack.config.js` 中:
|
||||
|
||||
```javascript
|
||||
const { getConfig, getDatabaseConfig } = require('../client/config/config-loader');
|
||||
|
||||
// 加载统一配置
|
||||
const config = getConfig();
|
||||
const serviceConfig = config.getServiceConfig('ljwx-admin');
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
port: serviceConfig.port,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: `http://ljwx-boot:${config.getServiceConfig('ljwx-boot').port}`,
|
||||
changeOrigin: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
define: {
|
||||
// 将配置注入到环境变量
|
||||
__LJWX_CONFIG__: JSON.stringify({
|
||||
apiUrl: `/api`,
|
||||
version: config.get('system.version'),
|
||||
})
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 在前端代码中使用
|
||||
|
||||
创建 `src/config/index.js`:
|
||||
|
||||
```javascript
|
||||
// 前端配置
|
||||
export const config = {
|
||||
apiUrl: import.meta.env.VITE_API_URL || '/api',
|
||||
version: import.meta.env.VITE_VERSION || '2.0.1',
|
||||
|
||||
// 从后端获取的配置
|
||||
async loadRuntimeConfig() {
|
||||
try {
|
||||
const response = await fetch('/api/system/config');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.warn('无法加载运行时配置:', error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Docker配置挂载示例
|
||||
|
||||
### 1. 在 Dockerfile 中添加配置支持
|
||||
|
||||
```dockerfile
|
||||
# ljwx-bigscreen Dockerfile
|
||||
FROM python:3.12-slim
|
||||
|
||||
# 创建配置目录
|
||||
RUN mkdir -p /app/config
|
||||
|
||||
# 复制应用代码
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
|
||||
# 安装依赖
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# 复制配置加载器
|
||||
COPY client/config/config_loader.py /app/config/
|
||||
|
||||
# 启动应用
|
||||
CMD ["python", "run.py"]
|
||||
```
|
||||
|
||||
### 2. 在 docker-compose.yml 中挂载配置
|
||||
|
||||
```yaml
|
||||
services:
|
||||
ljwx-bigscreen:
|
||||
image: ljwx-bigscreen:2.0.1
|
||||
volumes:
|
||||
- ./client/config/ljwx-config.json:/app/config/ljwx-config.json:ro
|
||||
- ./client/config/config_loader.py:/app/config/config_loader.py:ro
|
||||
environment:
|
||||
- SERVICE_NAME=ljwx-bigscreen
|
||||
- PYTHONPATH=/app:/app/config
|
||||
```
|
||||
|
||||
## 配置热更新支持
|
||||
|
||||
### 1. Python中的配置热更新
|
||||
|
||||
```python
|
||||
import threading
|
||||
import time
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
|
||||
class ConfigReloadHandler(FileSystemEventHandler):
|
||||
def __init__(self, config_loader):
|
||||
self.config_loader = config_loader
|
||||
|
||||
def on_modified(self, event):
|
||||
if event.src_path.endswith('ljwx-config.json'):
|
||||
print("配置文件已更新,重新加载...")
|
||||
self.config_loader.reload()
|
||||
|
||||
# 在应用启动时启用配置监控
|
||||
def start_config_watcher(config_loader):
|
||||
event_handler = ConfigReloadHandler(config_loader)
|
||||
observer = Observer()
|
||||
observer.schedule(event_handler, '/app/config', recursive=False)
|
||||
observer.start()
|
||||
return observer
|
||||
```
|
||||
|
||||
### 2. Java中的配置热更新
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class ConfigReloadService {
|
||||
|
||||
@Autowired
|
||||
private LJWXConfigLoader configLoader;
|
||||
|
||||
@EventListener
|
||||
@Async
|
||||
public void handleConfigReload(ConfigReloadEvent event) {
|
||||
log.info("重新加载配置...");
|
||||
configLoader.reload();
|
||||
// 触发相关服务重新初始化
|
||||
}
|
||||
|
||||
// 定期检查配置文件修改时间
|
||||
@Scheduled(fixedDelay = 30000)
|
||||
public void checkConfigFile() {
|
||||
// 检查配置文件是否修改
|
||||
// 如果修改,发布ConfigReloadEvent
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 配置验证
|
||||
|
||||
### 1. Python配置验证
|
||||
|
||||
```python
|
||||
def validate_config(config):
|
||||
"""验证配置的完整性和正确性"""
|
||||
required_keys = [
|
||||
'database.mysql.host',
|
||||
'database.mysql.port',
|
||||
'database.mysql.username',
|
||||
'database.mysql.password',
|
||||
'services.ljwx-bigscreen.port'
|
||||
]
|
||||
|
||||
for key in required_keys:
|
||||
if config.get(key) is None:
|
||||
raise ValueError(f"配置项 {key} 不能为空")
|
||||
|
||||
# 端口范围验证
|
||||
port = config.get('services.ljwx-bigscreen.port')
|
||||
if not (1 <= port <= 65535):
|
||||
raise ValueError(f"端口 {port} 超出有效范围")
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
### 2. 启动时配置检查
|
||||
|
||||
```python
|
||||
# 在应用启动时验证配置
|
||||
try:
|
||||
config = get_config()
|
||||
validate_config(config)
|
||||
print("✅ 配置验证通过")
|
||||
except Exception as e:
|
||||
print(f"❌ 配置验证失败: {e}")
|
||||
sys.exit(1)
|
||||
```
|
||||
|
||||
通过以上集成示例,各服务可以无缝使用统一配置系统,同时保持向后兼容性。
|
||||
@@ -1,105 +0,0 @@
|
||||
{
|
||||
"system": {
|
||||
"name": "ljwx-system",
|
||||
"version": "2.0.1",
|
||||
"environment": "production"
|
||||
},
|
||||
"database": {
|
||||
"mysql": {
|
||||
"host": "ljwx-mysql",
|
||||
"port": 3306,
|
||||
"database": "test",
|
||||
"username": "ljwx",
|
||||
"password": "123456",
|
||||
"charset": "utf8mb4",
|
||||
"pool_size": 10,
|
||||
"max_overflow": 20,
|
||||
"pool_timeout": 30,
|
||||
"pool_recycle": 3600
|
||||
},
|
||||
"redis": {
|
||||
"host": "ljwx-redis",
|
||||
"port": 6379,
|
||||
"password": "",
|
||||
"db": 0,
|
||||
"max_connections": 50
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"ljwx-admin": {
|
||||
"port": 8080,
|
||||
"api_prefix": "/api"
|
||||
},
|
||||
"ljwx-bigscreen": {
|
||||
"port": 8001,
|
||||
"api_prefix": "/api"
|
||||
},
|
||||
"ljwx-boot": {
|
||||
"port": 8082,
|
||||
"api_prefix": "/api"
|
||||
},
|
||||
"ljwx-mysql": {
|
||||
"port": 3306
|
||||
},
|
||||
"ljwx-redis": {
|
||||
"port": 6379
|
||||
}
|
||||
},
|
||||
"images": {
|
||||
"registry": "crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx",
|
||||
"ljwx-mysql": "2.0.1",
|
||||
"ljwx-redis": "2.0.1",
|
||||
"ljwx-admin": "2.0.1",
|
||||
"ljwx-bigscreen": "2.0.1",
|
||||
"ljwx-boot": "2.0.1",
|
||||
"grafana": "1.2.6",
|
||||
"prometheus": "1.2.6",
|
||||
"loki": "1.2.6",
|
||||
"promtail": "1.2.6",
|
||||
"alertmanager": "1.2.6"
|
||||
},
|
||||
"network": {
|
||||
"name": "client_ljwx-network",
|
||||
"driver": "bridge",
|
||||
"subnet": "172.20.0.0/16"
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
"max_file_size": "100MB",
|
||||
"backup_count": 10,
|
||||
"log_path": "/app/logs"
|
||||
},
|
||||
"security": {
|
||||
"jwt_secret": "ljwx-jwt-secret-key-2024",
|
||||
"jwt_expiration": 86400,
|
||||
"cors_origins": [
|
||||
"http://localhost:3000",
|
||||
"http://localhost:8080",
|
||||
"http://192.168.1.83:8080"
|
||||
]
|
||||
},
|
||||
"monitoring": {
|
||||
"enable_metrics": true,
|
||||
"metrics_port": 9090,
|
||||
"health_check_interval": 30
|
||||
},
|
||||
"alert": {
|
||||
"enabled": true,
|
||||
"webhook_url": "http://ljwx-bigscreen:8001/alert/webhook",
|
||||
"retry_count": 3,
|
||||
"retry_interval": 60
|
||||
},
|
||||
"business": {
|
||||
"health_data": {
|
||||
"batch_size": 1000,
|
||||
"process_interval": 300,
|
||||
"anomaly_threshold": 0.8
|
||||
},
|
||||
"device_message": {
|
||||
"queue_size": 10000,
|
||||
"process_workers": 4,
|
||||
"retention_days": 90
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
# LJWX 系统统一配置文件
|
||||
# 所有服务都从此文件读取配置信息
|
||||
|
||||
# 系统基础信息
|
||||
system:
|
||||
name: "ljwx-system"
|
||||
version: "2.0.1"
|
||||
environment: "production"
|
||||
|
||||
# 数据库配置
|
||||
database:
|
||||
mysql:
|
||||
host: "ljwx-mysql"
|
||||
port: 3306
|
||||
database: "test"
|
||||
username: "ljwx"
|
||||
password: "123456"
|
||||
charset: "utf8mb4"
|
||||
pool_size: 10
|
||||
max_overflow: 20
|
||||
pool_timeout: 30
|
||||
pool_recycle: 3600
|
||||
|
||||
redis:
|
||||
host: "ljwx-redis"
|
||||
port: 6379
|
||||
password: ""
|
||||
db: 0
|
||||
max_connections: 50
|
||||
|
||||
# 服务端口配置
|
||||
services:
|
||||
ljwx-admin:
|
||||
port: 8080
|
||||
api_prefix: "/api"
|
||||
|
||||
ljwx-bigscreen:
|
||||
port: 8001
|
||||
api_prefix: "/api"
|
||||
|
||||
ljwx-boot:
|
||||
port: 8082
|
||||
api_prefix: "/api"
|
||||
|
||||
ljwx-mysql:
|
||||
port: 3306
|
||||
|
||||
ljwx-redis:
|
||||
port: 6379
|
||||
|
||||
# Docker镜像版本配置
|
||||
images:
|
||||
registry: "crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx"
|
||||
ljwx-mysql: "2.0.1"
|
||||
ljwx-redis: "2.0.1"
|
||||
ljwx-admin: "2.0.1"
|
||||
ljwx-bigscreen: "2.0.1"
|
||||
ljwx-boot: "2.0.1"
|
||||
grafana: "1.2.6"
|
||||
prometheus: "1.2.6"
|
||||
loki: "1.2.6"
|
||||
promtail: "1.2.6"
|
||||
alertmanager: "1.2.6"
|
||||
|
||||
# 网络配置
|
||||
network:
|
||||
name: "client_ljwx-network"
|
||||
driver: "bridge"
|
||||
subnet: "172.20.0.0/16"
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level: "INFO"
|
||||
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
max_file_size: "100MB"
|
||||
backup_count: 10
|
||||
log_path: "/app/logs"
|
||||
|
||||
# 安全配置
|
||||
security:
|
||||
jwt_secret: "ljwx-jwt-secret-key-2024"
|
||||
jwt_expiration: 86400 # 24 hours
|
||||
cors_origins:
|
||||
- "http://localhost:3000"
|
||||
- "http://localhost:8080"
|
||||
- "http://192.168.1.83:8080"
|
||||
|
||||
# 监控配置
|
||||
monitoring:
|
||||
enable_metrics: true
|
||||
metrics_port: 9090
|
||||
health_check_interval: 30
|
||||
|
||||
# 告警配置
|
||||
alert:
|
||||
enabled: true
|
||||
webhook_url: "http://ljwx-bigscreen:8001/alert/webhook"
|
||||
retry_count: 3
|
||||
retry_interval: 60
|
||||
|
||||
# 业务配置
|
||||
business:
|
||||
# 健康数据处理配置
|
||||
health_data:
|
||||
batch_size: 1000
|
||||
process_interval: 300 # 5 minutes
|
||||
anomaly_threshold: 0.8
|
||||
|
||||
# 设备消息配置
|
||||
device_message:
|
||||
queue_size: 10000
|
||||
process_workers: 4
|
||||
retention_days: 90
|
||||
@@ -1,7 +0,0 @@
|
||||
[mysqld]
|
||||
# MySQL 9 compatible - removed default_authentication_plugin
|
||||
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO
|
||||
character-set-server=utf8mb4
|
||||
collation-server=utf8mb4_unicode_ci
|
||||
max_connections=200
|
||||
innodb_buffer_pool_size=256M
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "ljwx-config",
|
||||
"version": "2.0.1",
|
||||
"description": "LJWX系统统一配置管理工具",
|
||||
"main": "config-loader.js",
|
||||
"scripts": {
|
||||
"test": "node config-loader.js"
|
||||
},
|
||||
"keywords": [
|
||||
"ljwx",
|
||||
"config",
|
||||
"yaml",
|
||||
"configuration"
|
||||
],
|
||||
"author": "LJWX Team",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
# Redis定制化配置文件模板
|
||||
|
||||
# 网络配置
|
||||
bind 0.0.0.0
|
||||
port 6379
|
||||
protected-mode no
|
||||
|
||||
# 认证配置
|
||||
requirepass 123456
|
||||
|
||||
# 内存配置
|
||||
maxmemory 512mb
|
||||
maxmemory-policy allkeys-lru
|
||||
|
||||
# 持久化配置
|
||||
save 900 1
|
||||
save 300 10
|
||||
save 60 10000
|
||||
rdbcompression yes
|
||||
rdbchecksum yes
|
||||
dbfilename dump.rdb
|
||||
dir /data
|
||||
|
||||
# AOF配置
|
||||
appendonly yes
|
||||
appendfilename "appendonly.aof"
|
||||
appendfsync everysec
|
||||
no-appendfsync-on-rewrite no
|
||||
auto-aof-rewrite-percentage 100
|
||||
auto-aof-rewrite-min-size 64mb
|
||||
|
||||
# 日志配置
|
||||
loglevel notice
|
||||
logfile /var/log/redis/redis.log
|
||||
|
||||
# 性能优化
|
||||
tcp-keepalive 300
|
||||
timeout 0
|
||||
tcp-backlog 511
|
||||
databases 16
|
||||
|
||||
# 客户端配置
|
||||
maxclients 10000
|
||||
|
||||
# 慢查询日志
|
||||
slowlog-log-slower-than 10000
|
||||
slowlog-max-len 128
|
||||
|
||||
# 键空间通知
|
||||
notify-keyspace-events ""
|
||||
|
||||
# 安全配置
|
||||
rename-command FLUSHDB ""
|
||||
rename-command FLUSHALL ""
|
||||
rename-command KEYS ""
|
||||
rename-command CONFIG "CONFIG_9f2a8b3c4d5e6f7a"
|
||||
@@ -1,232 +0,0 @@
|
||||
#!/bin/bash
|
||||
# LJWX 快速配置脚本
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${BLUE}🔧 LJWX 系统配置向导${NC}"
|
||||
echo ""
|
||||
|
||||
# 获取服务器IP
|
||||
get_server_ip() {
|
||||
local ip
|
||||
ip=$(hostname -I | awk '{print $1}')
|
||||
if [ -z "$ip" ]; then
|
||||
ip=$(curl -s ipinfo.io/ip 2>/dev/null || echo "localhost")
|
||||
fi
|
||||
echo "$ip"
|
||||
}
|
||||
|
||||
# 检查端口是否被占用
|
||||
check_port() {
|
||||
local port=$1
|
||||
if netstat -tlnp 2>/dev/null | grep -q ":${port} "; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# 配置端口
|
||||
configure_ports() {
|
||||
echo -e "${YELLOW}📡 配置服务端口${NC}"
|
||||
|
||||
# 管理后台端口
|
||||
while true; do
|
||||
read -p "请输入管理后台端口 [默认: 80]: " admin_port
|
||||
admin_port=${admin_port:-80}
|
||||
|
||||
if check_port "$admin_port"; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}端口 ${admin_port} 已被占用,请选择其他端口${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# 大屏系统端口
|
||||
while true; do
|
||||
read -p "请输入大屏系统端口 [默认: 5000]: " bigscreen_port
|
||||
bigscreen_port=${bigscreen_port:-5000}
|
||||
|
||||
if check_port "$bigscreen_port"; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}端口 ${bigscreen_port} 已被占用,请选择其他端口${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# 后端API端口
|
||||
while true; do
|
||||
read -p "请输入后端API端口 [默认: 9998]: " boot_port
|
||||
boot_port=${boot_port:-9998}
|
||||
|
||||
if check_port "$boot_port"; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}端口 ${boot_port} 已被占用,请选择其他端口${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# MySQL端口
|
||||
while true; do
|
||||
read -p "请输入MySQL端口 [默认: 3306]: " mysql_port
|
||||
mysql_port=${mysql_port:-3306}
|
||||
|
||||
if check_port "$mysql_port"; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}端口 ${mysql_port} 已被占用,请选择其他端口${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Redis端口
|
||||
while true; do
|
||||
read -p "请输入Redis端口 [默认: 6379]: " redis_port
|
||||
redis_port=${redis_port:-6379}
|
||||
|
||||
if check_port "$redis_port"; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}端口 ${redis_port} 已被占用,请选择其他端口${NC}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 配置数据库
|
||||
configure_database() {
|
||||
echo ""
|
||||
echo -e "${YELLOW}🗄️ 配置数据库${NC}"
|
||||
|
||||
read -p "请输入MySQL root密码 [默认: 123456]: " mysql_root_password
|
||||
mysql_root_password=${mysql_root_password:-123456}
|
||||
|
||||
read -p "请输入数据库名称 [默认: test]: " mysql_database
|
||||
mysql_database=${mysql_database:-test}
|
||||
|
||||
read -p "请输入应用数据库用户名 [默认: ljwx]: " mysql_user
|
||||
mysql_user=${mysql_user:-ljwx}
|
||||
|
||||
read -p "请输入应用数据库密码 [默认: 123456]: " mysql_password
|
||||
mysql_password=${mysql_password:-123456}
|
||||
}
|
||||
|
||||
# 配置镜像源
|
||||
configure_registry() {
|
||||
echo ""
|
||||
echo -e "${YELLOW}🐳 配置镜像源${NC}"
|
||||
echo "1) 阿里云镜像仓库 (默认)"
|
||||
echo "2) Docker Hub"
|
||||
echo "3) 自定义镜像仓库"
|
||||
|
||||
read -p "请选择镜像源 [1]: " registry_choice
|
||||
registry_choice=${registry_choice:-1}
|
||||
|
||||
case $registry_choice in
|
||||
1)
|
||||
registry="crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx"
|
||||
;;
|
||||
2)
|
||||
registry="ljwx"
|
||||
;;
|
||||
3)
|
||||
read -p "请输入自定义镜像仓库地址: " registry
|
||||
;;
|
||||
*)
|
||||
registry="crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 生成配置文件
|
||||
generate_env() {
|
||||
echo ""
|
||||
echo -e "${YELLOW}📝 生成配置文件${NC}"
|
||||
|
||||
cat > .env << EOF
|
||||
# LJWX 系统配置
|
||||
LJWX_VERSION=2.0.1
|
||||
REGISTRY=${registry}
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_PASSWORD=${mysql_root_password}
|
||||
MYSQL_DATABASE=${mysql_database}
|
||||
MYSQL_USER=${mysql_user}
|
||||
MYSQL_PASSWORD=${mysql_password}
|
||||
|
||||
# 服务端口配置
|
||||
LJWX_BOOT_PORT=${boot_port}
|
||||
LJWX_BIGSCREEN_PORT=${bigscreen_port}
|
||||
LJWX_ADMIN_PORT=${admin_port}
|
||||
MYSQL_PORT=${mysql_port}
|
||||
REDIS_PORT=${redis_port}
|
||||
|
||||
# 时区配置
|
||||
TZ=Asia/Shanghai
|
||||
|
||||
# 日志配置
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# 配置生成时间
|
||||
GENERATED_AT=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
CONFIGURED_BY=configure.sh
|
||||
EOF
|
||||
}
|
||||
|
||||
# 显示配置摘要
|
||||
show_summary() {
|
||||
local server_ip
|
||||
server_ip=$(get_server_ip)
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ 配置完成!${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}📋 配置摘要:${NC}"
|
||||
echo -e " 服务器IP: ${GREEN}${server_ip}${NC}"
|
||||
echo -e " 管理后台: ${GREEN}http://${server_ip}:${admin_port}${NC}"
|
||||
echo -e " 大屏系统: ${GREEN}http://${server_ip}:${bigscreen_port}${NC}"
|
||||
echo -e " 后端API: ${GREEN}http://${server_ip}:${boot_port}${NC}"
|
||||
echo -e " MySQL: ${GREEN}${server_ip}:${mysql_port}${NC}"
|
||||
echo -e " Redis: ${GREEN}${server_ip}:${redis_port}${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}🗄️ 数据库配置:${NC}"
|
||||
echo -e " 数据库名: ${GREEN}${mysql_database}${NC}"
|
||||
echo -e " 用户名: ${GREEN}${mysql_user}${NC}"
|
||||
echo -e " 密码: ${GREEN}${mysql_password}${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}🐳 镜像源:${NC}"
|
||||
echo -e " ${GREEN}${registry}${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}📝 配置已保存到 .env 文件${NC}"
|
||||
echo -e "${YELLOW}🚀 现在可以运行 './start.sh' 启动系统${NC}"
|
||||
}
|
||||
|
||||
# 交互式确认
|
||||
confirm_config() {
|
||||
echo ""
|
||||
echo -e "${YELLOW}确认以上配置?${NC}"
|
||||
read -p "(yes/no) [yes]: " confirm
|
||||
confirm=${confirm:-yes}
|
||||
|
||||
if [ "$confirm" != "yes" ] && [ "$confirm" != "y" ]; then
|
||||
echo -e "${BLUE}配置已取消${NC}"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# 主程序
|
||||
main() {
|
||||
configure_ports
|
||||
configure_database
|
||||
configure_registry
|
||||
confirm_config
|
||||
generate_env
|
||||
show_summary
|
||||
}
|
||||
|
||||
# 执行主程序
|
||||
main "$@"
|
||||
@@ -1,164 +0,0 @@
|
||||
#!/bin/bash
|
||||
# 创建客户端部署包
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
PACKAGE_NAME="ljwx-client-v2.0.1"
|
||||
PACKAGE_DIR="${PACKAGE_NAME}"
|
||||
|
||||
echo -e "${BLUE}📦 创建 LJWX 客户端部署包${NC}"
|
||||
echo ""
|
||||
|
||||
# 创建打包目录
|
||||
echo -e "${YELLOW}📁 创建打包目录...${NC}"
|
||||
rm -rf "$PACKAGE_DIR"
|
||||
mkdir -p "$PACKAGE_DIR"
|
||||
|
||||
# 复制文件
|
||||
echo -e "${YELLOW}📋 复制文件...${NC}"
|
||||
cp start.sh "$PACKAGE_DIR/"
|
||||
cp configure.sh "$PACKAGE_DIR/"
|
||||
cp monitor.sh "$PACKAGE_DIR/"
|
||||
cp README.md "$PACKAGE_DIR/"
|
||||
|
||||
# 创建示例配置文件
|
||||
echo -e "${YELLOW}⚙️ 创建示例配置...${NC}"
|
||||
cat > "$PACKAGE_DIR/.env.example" << 'EOF'
|
||||
# LJWX 系统配置示例
|
||||
LJWX_VERSION=2.0.1
|
||||
REGISTRY=crpi-yilnm6upy4pmbp67.cn-shenzhen.personal.cr.aliyuncs.com/ljwx
|
||||
|
||||
# 数据库配置
|
||||
MYSQL_ROOT_PASSWORD=123456
|
||||
MYSQL_DATABASE=test
|
||||
MYSQL_USER=ljwx
|
||||
MYSQL_PASSWORD=123456
|
||||
|
||||
# 服务端口配置
|
||||
LJWX_BOOT_PORT=9998
|
||||
LJWX_BIGSCREEN_PORT=5000
|
||||
LJWX_ADMIN_PORT=80
|
||||
MYSQL_PORT=3306
|
||||
REDIS_PORT=6379
|
||||
|
||||
# 时区配置
|
||||
TZ=Asia/Shanghai
|
||||
|
||||
# 日志配置
|
||||
LOG_LEVEL=INFO
|
||||
EOF
|
||||
|
||||
# 创建快速开始脚本
|
||||
cat > "$PACKAGE_DIR/quick-start.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
# LJWX 快速开始脚本
|
||||
|
||||
echo "🚀 LJWX 灵境万象健康管理系统 - 快速开始"
|
||||
echo ""
|
||||
|
||||
# 检查Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "❌ Docker 未安装,请先安装 Docker"
|
||||
echo " 安装指南: https://docs.docker.com/get-docker/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 运行配置向导
|
||||
if [ ! -f .env ]; then
|
||||
echo "📝 运行配置向导..."
|
||||
./configure.sh
|
||||
fi
|
||||
|
||||
# 启动系统
|
||||
echo "🚀 启动系统..."
|
||||
./start.sh
|
||||
|
||||
echo ""
|
||||
echo "✅ 快速开始完成!"
|
||||
EOF
|
||||
|
||||
chmod +x "$PACKAGE_DIR/quick-start.sh"
|
||||
|
||||
# 创建卸载脚本
|
||||
cat > "$PACKAGE_DIR/uninstall.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
# LJWX 卸载脚本
|
||||
|
||||
echo "🗑️ LJWX 系统卸载"
|
||||
echo ""
|
||||
|
||||
read -p "⚠️ 这将完全删除LJWX系统和所有数据,确认继续?(yes/no): " confirm
|
||||
|
||||
if [ "$confirm" = "yes" ]; then
|
||||
echo "🛑 停止服务..."
|
||||
./start.sh stop 2>/dev/null || true
|
||||
|
||||
echo "🧹 清理系统..."
|
||||
./start.sh clean 2>/dev/null || true
|
||||
|
||||
echo "📁 删除配置和数据..."
|
||||
rm -rf data/ logs/ config/ backups/
|
||||
rm -f .env docker-compose.yml
|
||||
|
||||
echo "✅ 卸载完成"
|
||||
else
|
||||
echo "❌ 卸载已取消"
|
||||
fi
|
||||
EOF
|
||||
|
||||
chmod +x "$PACKAGE_DIR/uninstall.sh"
|
||||
|
||||
# 创建版本信息文件
|
||||
cat > "$PACKAGE_DIR/VERSION" << EOF
|
||||
LJWX 灵境万象健康管理系统
|
||||
版本: 2.0.1
|
||||
构建日期: $(date '+%Y-%m-%d')
|
||||
打包时间: $(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
组件版本:
|
||||
- ljwx-mysql: 2.0.1
|
||||
- ljwx-redis: 2.0.1
|
||||
- ljwx-boot: 2.0.1
|
||||
- ljwx-bigscreen: 2.0.1
|
||||
- ljwx-admin: 2.0.1
|
||||
|
||||
系统要求:
|
||||
- Docker 20.0+
|
||||
- Docker Compose 2.0+
|
||||
- 2GB+ 内存
|
||||
- 10GB+ 磁盘空间
|
||||
EOF
|
||||
|
||||
# 创建压缩包
|
||||
echo -e "${YELLOW}📦 创建压缩包...${NC}"
|
||||
tar -czf "${PACKAGE_NAME}.tar.gz" "$PACKAGE_DIR"
|
||||
|
||||
# 计算文件大小和校验和
|
||||
PACKAGE_SIZE=$(du -h "${PACKAGE_NAME}.tar.gz" | cut -f1)
|
||||
PACKAGE_MD5=$(md5sum "${PACKAGE_NAME}.tar.gz" | cut -d' ' -f1)
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ 部署包创建完成!${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}📦 包信息:${NC}"
|
||||
echo -e " 文件名: ${GREEN}${PACKAGE_NAME}.tar.gz${NC}"
|
||||
echo -e " 大小: ${GREEN}${PACKAGE_SIZE}${NC}"
|
||||
echo -e " MD5: ${GREEN}${PACKAGE_MD5}${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}📋 客户部署步骤:${NC}"
|
||||
echo -e " 1. 上传 ${YELLOW}${PACKAGE_NAME}.tar.gz${NC} 到客户服务器"
|
||||
echo -e " 2. 解压: ${YELLOW}tar -xzf ${PACKAGE_NAME}.tar.gz${NC}"
|
||||
echo -e " 3. 进入目录: ${YELLOW}cd ${PACKAGE_NAME}${NC}"
|
||||
echo -e " 4. 快速开始: ${YELLOW}./quick-start.sh${NC}"
|
||||
echo ""
|
||||
echo -e "${BLUE}📖 详细说明请查看包内的 README.md${NC}"
|
||||
|
||||
# 清理临时目录
|
||||
rm -rf "$PACKAGE_DIR"
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
[auto]
|
||||
server-uuid=7e7f87ae-8ae5-11f0-a9cb-0242ac140002
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user