'docker'
This commit is contained in:
parent
09842a2611
commit
3793cc3252
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# 强制 shell 脚本、配置文件等使用 LF
|
||||
*.sh text eol=lf
|
||||
*.env text eol=lf
|
||||
.env.* text eol=lf
|
||||
|
||||
# 可选:所有文本文件统一用 LF(更严格)
|
||||
# * text=auto eol=lf
|
||||
309
.kiro/specs/docker-deployment/design.md
Normal file
309
.kiro/specs/docker-deployment/design.md
Normal file
@ -0,0 +1,309 @@
|
||||
# Design Document: Docker Deployment
|
||||
|
||||
## Overview
|
||||
|
||||
本设计文档描述了若依框架项目的前后端分离Docker部署方案。该方案将Vue3前端应用、Spring Boot后端应用和MySQL数据库分别容器化,通过Docker Compose进行统一编排和管理。
|
||||
|
||||
系统采用微服务架构,前端通过Nginx提供静态文件服务并代理API请求到后端服务,后端连接到独立的数据库容器,实现完全的容器化部署。
|
||||
|
||||
## Architecture
|
||||
|
||||
### 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Docker Host"
|
||||
subgraph "Frontend Container"
|
||||
A[Nginx + Vue3 Static Files]
|
||||
end
|
||||
|
||||
subgraph "Backend Container"
|
||||
B[Spring Boot Application]
|
||||
end
|
||||
|
||||
subgraph "Database Container"
|
||||
C[MySQL Database]
|
||||
end
|
||||
|
||||
subgraph "Volumes"
|
||||
D[Database Data Volume]
|
||||
E[Log Volume]
|
||||
F[Config Volume]
|
||||
end
|
||||
end
|
||||
|
||||
G[External Users] --> A
|
||||
A --> B
|
||||
B --> C
|
||||
C --> D
|
||||
B --> E
|
||||
A --> F
|
||||
B --> F
|
||||
```
|
||||
|
||||
### 网络架构
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "External Network"
|
||||
U[Users]
|
||||
end
|
||||
|
||||
subgraph "Docker Network: anxin-network"
|
||||
F[Frontend:80]
|
||||
B[Backend:8080]
|
||||
D[Database:3306]
|
||||
end
|
||||
|
||||
U -->|HTTP:80| F
|
||||
F -->|API Proxy| B
|
||||
B -->|MySQL Connection| D
|
||||
```
|
||||
|
||||
## Components and Interfaces
|
||||
|
||||
### 1. Frontend Container (anxin-frontend)
|
||||
|
||||
**基础镜像**: nginx:alpine
|
||||
**构建方式**: 多阶段构建
|
||||
|
||||
**第一阶段 - 构建阶段**:
|
||||
- 基础镜像: node:18-alpine
|
||||
- 工作目录: /app
|
||||
- 复制源码并执行npm构建
|
||||
- 输出: dist目录包含构建后的静态文件
|
||||
|
||||
**第二阶段 - 运行阶段**:
|
||||
- 基础镜像: nginx:alpine
|
||||
- 复制构建产物到nginx默认目录
|
||||
- 配置nginx.conf用于静态文件服务和API代理
|
||||
- 暴露端口: 80
|
||||
|
||||
**Nginx配置要点**:
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
# 静态文件服务
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# API代理
|
||||
location /prod-api/ {
|
||||
proxy_pass http://anxin-backend:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Backend Container (anxin-backend)
|
||||
|
||||
**基础镜像**: openjdk:8-jre-alpine
|
||||
**构建方式**: 多阶段构建
|
||||
|
||||
**第一阶段 - 构建阶段**:
|
||||
- 基础镜像: maven:3.8-openjdk-8
|
||||
- 工作目录: /app
|
||||
- 复制pom.xml和源码
|
||||
- 执行Maven构建: mvn clean package -DskipTests
|
||||
- 输出: target目录包含JAR文件
|
||||
|
||||
**第二阶段 - 运行阶段**:
|
||||
- 基础镜像: openjdk:8-jre-alpine
|
||||
- 复制JAR文件到容器
|
||||
- 设置启动命令
|
||||
- 暴露端口: 8080
|
||||
|
||||
**环境变量配置**:
|
||||
- `SPRING_PROFILES_ACTIVE`: 激活的配置文件
|
||||
- `SPRING_DATASOURCE_URL`: 数据库连接URL
|
||||
- `SPRING_DATASOURCE_USERNAME`: 数据库用户名
|
||||
- `SPRING_DATASOURCE_PASSWORD`: 数据库密码
|
||||
|
||||
### 3. Database Container (anxin-mysql)
|
||||
|
||||
**基础镜像**: mysql:8.0
|
||||
**配置要点**:
|
||||
- 数据持久化: 挂载数据卷到/var/lib/mysql
|
||||
- 初始化脚本: 挂载SQL文件到/docker-entrypoint-initdb.d/
|
||||
- 字符集配置: utf8mb4
|
||||
- 暴露端口: 3306
|
||||
|
||||
**环境变量**:
|
||||
- `MYSQL_ROOT_PASSWORD`: root用户密码
|
||||
- `MYSQL_DATABASE`: 默认数据库名
|
||||
- `MYSQL_USER`: 应用用户名
|
||||
- `MYSQL_PASSWORD`: 应用用户密码
|
||||
|
||||
### 4. Docker Compose编排
|
||||
|
||||
**服务依赖关系**:
|
||||
```yaml
|
||||
services:
|
||||
anxin-mysql:
|
||||
# 数据库服务,最先启动
|
||||
|
||||
anxin-backend:
|
||||
depends_on:
|
||||
- anxin-mysql
|
||||
# 后端服务,依赖数据库
|
||||
|
||||
anxin-frontend:
|
||||
depends_on:
|
||||
- anxin-backend
|
||||
# 前端服务,依赖后端
|
||||
```
|
||||
|
||||
**网络配置**:
|
||||
- 创建自定义网络: anxin-network
|
||||
- 所有服务连接到同一网络
|
||||
- 服务间通过服务名进行通信
|
||||
|
||||
**卷挂载**:
|
||||
- 数据库数据卷: mysql-data
|
||||
- 日志卷: logs
|
||||
- 配置文件卷: configs
|
||||
|
||||
## Data Models
|
||||
|
||||
### 容器配置模型
|
||||
|
||||
```yaml
|
||||
# Docker Compose配置结构
|
||||
version: '3.8'
|
||||
services:
|
||||
service_name:
|
||||
build:
|
||||
context: string
|
||||
dockerfile: string
|
||||
image: string
|
||||
container_name: string
|
||||
ports:
|
||||
- "host_port:container_port"
|
||||
environment:
|
||||
- KEY=VALUE
|
||||
volumes:
|
||||
- volume_name:container_path
|
||||
networks:
|
||||
- network_name
|
||||
depends_on:
|
||||
- dependency_service
|
||||
```
|
||||
|
||||
### 构建脚本配置模型
|
||||
|
||||
```bash
|
||||
# 环境配置结构
|
||||
ENVIRONMENT=production|staging|development
|
||||
DB_HOST=string
|
||||
DB_PORT=number
|
||||
DB_NAME=string
|
||||
DB_USER=string
|
||||
DB_PASSWORD=string
|
||||
BACKEND_PORT=number
|
||||
FRONTEND_PORT=number
|
||||
```
|
||||
|
||||
## Correctness Properties
|
||||
|
||||
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
|
||||
|
||||
### Property 1: Container Build Verification
|
||||
*For any* Docker container build process, the resulting container should contain all required application artifacts (static files for frontend, JAR files for backend)
|
||||
**Validates: Requirements 1.1, 2.1**
|
||||
|
||||
### Property 2: Service Connectivity
|
||||
*For any* multi-container deployment, when all containers are started, each service should be able to communicate with its dependencies (frontend to backend, backend to database)
|
||||
**Validates: Requirements 1.2, 1.3, 2.2**
|
||||
|
||||
### Property 3: Port Configuration
|
||||
*For any* container configuration, the specified ports should be correctly exposed and accessible from the host system
|
||||
**Validates: Requirements 1.5, 2.3, 3.4**
|
||||
|
||||
### Property 4: Build Process Execution
|
||||
*For any* build script execution, the script should successfully complete all build steps (npm build for frontend, Maven build for backend) without errors
|
||||
**Validates: Requirements 1.4, 2.4**
|
||||
|
||||
### Property 5: Database Initialization
|
||||
*For any* database container startup, the container should successfully initialize the database schema and execute all provided SQL scripts
|
||||
**Validates: Requirements 3.2, 3.5**
|
||||
|
||||
### Property 6: Data Persistence
|
||||
*For any* database container restart, previously stored data should remain intact through volume mounting
|
||||
**Validates: Requirements 3.3**
|
||||
|
||||
### Property 7: Service Orchestration
|
||||
*For any* Docker Compose deployment, services should start in the correct dependency order and establish proper network communication
|
||||
**Validates: Requirements 4.1, 4.2, 4.3, 4.5**
|
||||
|
||||
### Property 8: Volume Configuration
|
||||
*For any* Docker Compose configuration, all specified volumes should be correctly mounted and accessible to their respective containers
|
||||
**Validates: Requirements 4.4**
|
||||
|
||||
### Property 9: Build Script Functionality
|
||||
*For any* deployment script execution, the script should successfully build all images, pull latest code, and verify service availability
|
||||
**Validates: Requirements 5.1, 5.2, 5.5**
|
||||
|
||||
### Property 10: Environment Configuration Management
|
||||
*For any* environment parameter change, the build script should correctly apply the new configuration and load the appropriate configuration files
|
||||
**Validates: Requirements 5.3, 6.1, 6.2, 6.3, 6.4, 6.5**
|
||||
|
||||
### Property 11: Logging and Monitoring
|
||||
*For any* script execution, sufficient logging information should be provided to enable troubleshooting and monitoring
|
||||
**Validates: Requirements 5.4**
|
||||
|
||||
## Error Handling
|
||||
|
||||
### 容器启动失败处理
|
||||
- **数据库连接失败**: 后端容器应实现重试机制,等待数据库容器完全启动
|
||||
- **端口冲突**: 提供清晰的错误信息并建议解决方案
|
||||
- **镜像构建失败**: 详细记录构建日志,便于问题定位
|
||||
|
||||
### 网络连接问题
|
||||
- **服务间通信失败**: 验证网络配置和服务发现机制
|
||||
- **外部访问问题**: 检查端口映射和防火墙配置
|
||||
- **DNS解析问题**: 确保容器间能够通过服务名正确解析
|
||||
|
||||
### 数据持久化问题
|
||||
- **卷挂载失败**: 验证宿主机目录权限和路径存在性
|
||||
- **数据丢失**: 实现数据备份和恢复机制
|
||||
- **存储空间不足**: 监控磁盘使用情况并提供告警
|
||||
|
||||
### 构建脚本错误处理
|
||||
- **依赖下载失败**: 配置镜像源和重试机制
|
||||
- **权限问题**: 提供明确的权限要求说明
|
||||
- **环境变量缺失**: 验证必需的环境变量并提供默认值
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### 单元测试方法
|
||||
- **Dockerfile语法验证**: 使用hadolint等工具验证Dockerfile语法
|
||||
- **配置文件验证**: 验证nginx.conf、docker-compose.yml等配置文件的正确性
|
||||
- **脚本语法检查**: 使用shellcheck验证shell脚本语法
|
||||
|
||||
### 集成测试方法
|
||||
- **容器构建测试**: 验证每个容器能够成功构建
|
||||
- **服务启动测试**: 验证所有服务能够正确启动并建立连接
|
||||
- **端到端测试**: 从外部访问验证整个系统的功能完整性
|
||||
|
||||
### 属性测试配置
|
||||
使用Docker和shell脚本进行属性测试,每个属性测试运行最少100次迭代:
|
||||
|
||||
- **测试框架**: 使用Bash测试框架(如bats-core)
|
||||
- **测试环境**: 在隔离的Docker环境中运行测试
|
||||
- **测试数据**: 使用不同的环境配置和数据集进行测试
|
||||
- **测试标签格式**: **Feature: docker-deployment, Property {number}: {property_text}**
|
||||
|
||||
### 性能测试
|
||||
- **容器启动时间**: 测量各容器的启动时间
|
||||
- **资源使用情况**: 监控CPU、内存、磁盘使用情况
|
||||
- **并发访问测试**: 测试系统在高并发情况下的表现
|
||||
|
||||
### 安全测试
|
||||
- **镜像安全扫描**: 使用工具扫描镜像中的安全漏洞
|
||||
- **网络安全**: 验证容器间网络隔离和访问控制
|
||||
- **敏感信息保护**: 确保密码等敏感信息不会暴露在镜像中
|
||||
88
.kiro/specs/docker-deployment/requirements.md
Normal file
88
.kiro/specs/docker-deployment/requirements.md
Normal file
@ -0,0 +1,88 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
为若依框架项目创建前后端分离的Docker部署方案,包括前端Vue3应用和后端Spring Boot应用的独立容器化部署脚本。
|
||||
|
||||
## Glossary
|
||||
|
||||
- **Frontend_Container**: Vue3前端应用的Docker容器
|
||||
- **Backend_Container**: Spring Boot后端应用的Docker容器
|
||||
- **Docker_Compose**: 用于编排多容器应用的工具
|
||||
- **Nginx_Proxy**: 用于前端静态文件服务和API代理的反向代理服务器
|
||||
- **Database_Container**: MySQL数据库容器
|
||||
- **Build_Script**: 构建和部署脚本
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: 前端容器化部署
|
||||
|
||||
**User Story:** 作为运维人员,我希望将Vue3前端应用容器化部署,以便实现环境一致性和快速部署。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Frontend_Container SHALL 包含构建好的Vue3静态文件
|
||||
2. WHEN 前端容器启动时,THE Nginx_Proxy SHALL 提供静态文件服务
|
||||
3. THE Frontend_Container SHALL 配置API代理到后端服务
|
||||
4. WHEN 构建前端镜像时,THE Build_Script SHALL 执行npm构建流程
|
||||
5. THE Frontend_Container SHALL 暴露80端口用于HTTP访问
|
||||
|
||||
### Requirement 2: 后端容器化部署
|
||||
|
||||
**User Story:** 作为运维人员,我希望将Spring Boot后端应用容器化部署,以便实现独立的服务部署和扩展。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Backend_Container SHALL 包含编译好的Spring Boot JAR文件
|
||||
2. WHEN 后端容器启动时,THE Backend_Container SHALL 连接到数据库
|
||||
3. THE Backend_Container SHALL 暴露8080端口用于API访问
|
||||
4. WHEN 构建后端镜像时,THE Build_Script SHALL 执行Maven构建流程
|
||||
5. THE Backend_Container SHALL 配置环境变量用于数据库连接
|
||||
|
||||
### Requirement 3: 数据库容器化部署
|
||||
|
||||
**User Story:** 作为运维人员,我希望数据库也能容器化部署,以便实现完整的容器化环境。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Database_Container SHALL 使用MySQL镜像
|
||||
2. WHEN 数据库容器启动时,THE Database_Container SHALL 初始化数据库结构
|
||||
3. THE Database_Container SHALL 持久化数据到宿主机卷
|
||||
4. THE Database_Container SHALL 暴露3306端口
|
||||
5. WHEN 初始化时,THE Database_Container SHALL 执行SQL初始化脚本
|
||||
|
||||
### Requirement 4: 容器编排和网络配置
|
||||
|
||||
**User Story:** 作为运维人员,我希望通过Docker Compose统一管理所有容器,以便简化部署和维护。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Docker_Compose SHALL 定义所有服务的依赖关系
|
||||
2. WHEN 启动服务时,THE Docker_Compose SHALL 按正确顺序启动容器
|
||||
3. THE Docker_Compose SHALL 创建内部网络用于容器间通信
|
||||
4. THE Docker_Compose SHALL 配置卷挂载用于数据持久化
|
||||
5. WHEN 服务启动时,THE Docker_Compose SHALL 等待依赖服务就绪
|
||||
|
||||
### Requirement 5: 构建和部署脚本
|
||||
|
||||
**User Story:** 作为开发人员,我希望有自动化的构建和部署脚本,以便快速部署应用到不同环境。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Build_Script SHALL 提供一键构建所有镜像的功能
|
||||
2. WHEN 执行部署脚本时,THE Build_Script SHALL 自动拉取最新代码
|
||||
3. THE Build_Script SHALL 支持不同环境的配置切换
|
||||
4. THE Build_Script SHALL 提供日志输出用于问题排查
|
||||
5. WHEN 部署完成时,THE Build_Script SHALL 验证服务可用性
|
||||
|
||||
### Requirement 6: 环境配置管理
|
||||
|
||||
**User Story:** 作为运维人员,我希望能够灵活配置不同环境的参数,以便在开发、测试、生产环境中使用。
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Build_Script SHALL 支持通过环境变量配置数据库连接
|
||||
2. THE Build_Script SHALL 支持配置前端API基础URL
|
||||
3. THE Build_Script SHALL 支持配置容器资源限制
|
||||
4. THE Build_Script SHALL 支持配置日志级别和输出路径
|
||||
5. WHEN 切换环境时,THE Build_Script SHALL 加载对应的配置文件
|
||||
176
.kiro/specs/docker-deployment/tasks.md
Normal file
176
.kiro/specs/docker-deployment/tasks.md
Normal file
@ -0,0 +1,176 @@
|
||||
# Implementation Plan: Docker Deployment
|
||||
|
||||
## Overview
|
||||
|
||||
本实现计划将若依框架项目转换为前后端分离的Docker部署方案。使用Bash脚本实现自动化构建和部署,通过Docker Compose编排多容器应用,实现完整的容器化部署流程。
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] 1. 创建项目Docker化基础结构
|
||||
- 创建docker目录结构
|
||||
- 设置基础配置文件模板
|
||||
- 创建环境变量配置文件
|
||||
- _Requirements: 6.1, 6.5_
|
||||
|
||||
- [ ] 2. 实现前端容器化
|
||||
- [x] 2.1 创建前端Dockerfile
|
||||
- 编写多阶段构建的Dockerfile
|
||||
- 配置Node.js构建环境
|
||||
- 配置Nginx运行环境
|
||||
- _Requirements: 1.1, 1.4_
|
||||
|
||||
- [ ]* 2.2 编写前端容器构建属性测试
|
||||
- **Property 1: Container Build Verification (Frontend)**
|
||||
- **Validates: Requirements 1.1**
|
||||
|
||||
- [x] 2.3 创建Nginx配置文件
|
||||
- 配置静态文件服务
|
||||
- 配置API代理规则
|
||||
- 设置端口和路径映射
|
||||
- _Requirements: 1.2, 1.3, 1.5_
|
||||
|
||||
- [ ]* 2.4 编写前端服务连接属性测试
|
||||
- **Property 2: Service Connectivity (Frontend)**
|
||||
- **Validates: Requirements 1.2, 1.3**
|
||||
|
||||
- [ ] 3. 实现后端容器化
|
||||
- [x] 3.1 创建后端Dockerfile
|
||||
- 编写多阶段构建的Dockerfile
|
||||
- 配置Maven构建环境
|
||||
- 配置JRE运行环境
|
||||
- _Requirements: 2.1, 2.4_
|
||||
|
||||
- [ ]* 3.2 编写后端容器构建属性测试
|
||||
- **Property 1: Container Build Verification (Backend)**
|
||||
- **Validates: Requirements 2.1**
|
||||
|
||||
- [x] 3.3 配置后端环境变量和连接
|
||||
- 设置数据库连接环境变量
|
||||
- 配置应用端口和网络
|
||||
- 设置日志和监控配置
|
||||
- _Requirements: 2.2, 2.3, 2.5_
|
||||
|
||||
- [ ]* 3.4 编写后端数据库连接属性测试
|
||||
- **Property 2: Service Connectivity (Backend)**
|
||||
- **Validates: Requirements 2.2**
|
||||
|
||||
- [ ] 4. 实现数据库容器化
|
||||
- [x] 4.1 创建数据库Docker配置
|
||||
- 配置MySQL容器参数
|
||||
- 设置数据卷挂载
|
||||
- 配置初始化脚本路径
|
||||
- _Requirements: 3.1, 3.3, 3.4_
|
||||
|
||||
- [x] 4.2 准备数据库初始化脚本
|
||||
- 复制现有SQL文件到初始化目录
|
||||
- 配置数据库用户和权限
|
||||
- 设置字符集和时区
|
||||
- _Requirements: 3.2, 3.5_
|
||||
|
||||
- [ ]* 4.3 编写数据库初始化属性测试
|
||||
- **Property 5: Database Initialization**
|
||||
- **Validates: Requirements 3.2, 3.5**
|
||||
|
||||
- [ ]* 4.4 编写数据持久化属性测试
|
||||
- **Property 6: Data Persistence**
|
||||
- **Validates: Requirements 3.3**
|
||||
|
||||
- [ ] 5. 创建Docker Compose编排配置
|
||||
- [x] 5.1 编写docker-compose.yml
|
||||
- 定义所有服务配置
|
||||
- 设置服务依赖关系
|
||||
- 配置网络和卷
|
||||
- _Requirements: 4.1, 4.2, 4.3, 4.4_
|
||||
|
||||
- [x] 5.2 配置环境特定的compose文件
|
||||
- 创建开发环境配置
|
||||
- 创建生产环境配置
|
||||
- 创建测试环境配置
|
||||
- _Requirements: 5.3, 6.5_
|
||||
|
||||
- [ ]* 5.3 编写服务编排属性测试
|
||||
- **Property 7: Service Orchestration**
|
||||
- **Validates: Requirements 4.1, 4.2, 4.3, 4.5**
|
||||
|
||||
- [ ]* 5.4 编写卷配置属性测试
|
||||
- **Property 8: Volume Configuration**
|
||||
- **Validates: Requirements 4.4**
|
||||
|
||||
- [x] 6. 检查点 - 验证容器配置
|
||||
- 确保所有Dockerfile和配置文件语法正确,如有问题请询问用户
|
||||
|
||||
- [ ] 7. 实现构建和部署脚本
|
||||
- [x] 7.1 创建主构建脚本 (build.sh)
|
||||
- 实现一键构建所有镜像功能
|
||||
- 添加代码拉取和更新功能
|
||||
- 实现环境配置切换
|
||||
- _Requirements: 5.1, 5.2, 5.3_
|
||||
|
||||
- [ ]* 7.2 编写构建脚本功能属性测试
|
||||
- **Property 9: Build Script Functionality**
|
||||
- **Validates: Requirements 5.1, 5.2, 5.5**
|
||||
|
||||
- [x] 7.3 创建部署脚本 (deploy.sh)
|
||||
- 实现服务启动和停止功能
|
||||
- 添加服务健康检查
|
||||
- 实现日志查看功能
|
||||
- _Requirements: 5.4, 5.5_
|
||||
|
||||
- [ ]* 7.4 编写日志和监控属性测试
|
||||
- **Property 11: Logging and Monitoring**
|
||||
- **Validates: Requirements 5.4**
|
||||
|
||||
- [x] 7.5 创建环境管理脚本 (env-config.sh)
|
||||
- 实现环境变量配置管理
|
||||
- 支持不同环境的参数切换
|
||||
- 添加配置验证功能
|
||||
- _Requirements: 6.1, 6.2, 6.3, 6.4_
|
||||
|
||||
- [ ]* 7.6 编写环境配置管理属性测试
|
||||
- **Property 10: Environment Configuration Management**
|
||||
- **Validates: Requirements 6.1, 6.2, 6.3, 6.4, 6.5**
|
||||
|
||||
- [ ] 8. 实现端口配置和网络测试
|
||||
- [ ] 8.1 添加端口配置验证
|
||||
- 验证所有容器端口正确暴露
|
||||
- 检查端口冲突
|
||||
- 测试外部访问连通性
|
||||
- _Requirements: 1.5, 2.3, 3.4_
|
||||
|
||||
- [ ]* 8.2 编写端口配置属性测试
|
||||
- **Property 3: Port Configuration**
|
||||
- **Validates: Requirements 1.5, 2.3, 3.4**
|
||||
|
||||
- [ ] 8.3 实现构建流程验证
|
||||
- 验证npm构建流程
|
||||
- 验证Maven构建流程
|
||||
- 添加构建错误处理
|
||||
- _Requirements: 1.4, 2.4_
|
||||
|
||||
- [ ]* 8.4 编写构建流程属性测试
|
||||
- **Property 4: Build Process Execution**
|
||||
- **Validates: Requirements 1.4, 2.4**
|
||||
|
||||
- [ ] 9. 创建文档和使用说明
|
||||
- [x] 9.1 编写部署文档 (README.md)
|
||||
- 创建快速开始指南
|
||||
- 添加环境要求说明
|
||||
- 提供故障排除指南
|
||||
- _Requirements: 5.4_
|
||||
|
||||
- [x] 9.2 创建配置示例文件
|
||||
- 提供各环境的配置模板
|
||||
- 添加配置参数说明
|
||||
- 创建环境变量示例
|
||||
- _Requirements: 6.1, 6.2, 6.3, 6.4_
|
||||
|
||||
- [ ] 10. 最终检查点 - 完整系统测试
|
||||
- 确保所有测试通过,完整的端到端部署流程正常工作,如有问题请询问用户
|
||||
|
||||
## Notes
|
||||
|
||||
- 标记有 `*` 的任务是可选的,可以跳过以实现更快的MVP
|
||||
- 每个任务都引用了具体的需求以确保可追溯性
|
||||
- 检查点确保增量验证
|
||||
- 属性测试验证通用正确性属性
|
||||
- 单元测试验证具体示例和边界情况
|
||||
26
docker/.gitignore
vendored
Normal file
26
docker/.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
# Docker部署相关忽略文件
|
||||
|
||||
# 环境配置文件 (除了示例文件)
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# 数据目录
|
||||
data/
|
||||
logs/
|
||||
|
||||
# 生成的配置文件
|
||||
docker-compose.yml
|
||||
configs/nginx.conf
|
||||
configs/application-docker.yml
|
||||
configs/my.cnf
|
||||
|
||||
# Docker相关
|
||||
.docker/
|
||||
|
||||
# 临时文件
|
||||
*.tmp
|
||||
*.log
|
||||
|
||||
# 备份文件
|
||||
*.bak
|
||||
*.backup
|
||||
929
docker/README.md
Normal file
929
docker/README.md
Normal file
@ -0,0 +1,929 @@
|
||||
# 若依框架 Docker 部署文档
|
||||
|
||||
本文档提供若依框架项目的完整Docker化部署方案,包括前后端分离架构的容器化部署、环境配置管理和故障排除指南。
|
||||
|
||||
## 📋 目录
|
||||
|
||||
- [项目概述](#项目概述)
|
||||
- [快速开始](#快速开始)
|
||||
- [环境要求](#环境要求)
|
||||
- [目录结构](#目录结构)
|
||||
- [详细部署步骤](#详细部署步骤)
|
||||
- [环境配置](#环境配置)
|
||||
- [服务管理](#服务管理)
|
||||
- [监控和日志](#监控和日志)
|
||||
- [故障排除](#故障排除)
|
||||
- [性能优化](#性能优化)
|
||||
- [安全配置](#安全配置)
|
||||
- [常见问题](#常见问题)
|
||||
|
||||
## 🚀 项目概述
|
||||
|
||||
本部署方案将若依框架项目容器化,实现:
|
||||
- **前后端分离**:Vue3前端 + Spring Boot后端独立部署
|
||||
- **数据库容器化**:MySQL 8.0容器化部署
|
||||
- **环境隔离**:支持开发、测试、生产环境配置
|
||||
- **自动化部署**:一键构建、部署和管理脚本
|
||||
- **服务监控**:健康检查和日志管理
|
||||
|
||||
### 架构图
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Frontend │ │ Backend │ │ Database │
|
||||
│ (Vue3+Nginx) │───▶│ (Spring Boot) │───▶│ (MySQL) │
|
||||
│ Port: 80 │ │ Port: 8080 │ │ Port: 3306 │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## ⚡ 快速开始
|
||||
|
||||
### 1. 环境准备
|
||||
|
||||
确保系统已安装必要的软件:
|
||||
|
||||
```bash
|
||||
# 检查Docker版本
|
||||
docker --version
|
||||
docker-compose --version
|
||||
|
||||
# 检查系统资源
|
||||
free -h
|
||||
df -h
|
||||
```
|
||||
|
||||
### 2. 配置环境
|
||||
|
||||
```bash
|
||||
# 1. 进入Docker目录
|
||||
cd docker
|
||||
|
||||
# 2. 复制环境配置文件
|
||||
cp environments/.env.example environments/.env.development
|
||||
|
||||
# 3. 编辑配置文件(根据需要修改)
|
||||
vim environments/.env.development
|
||||
```
|
||||
|
||||
### 3. 一键部署
|
||||
|
||||
```bash
|
||||
# 开发环境部署
|
||||
./build.sh deploy -e development
|
||||
|
||||
# 或者分步执行
|
||||
./build.sh build-all -e development # 构建镜像
|
||||
./deploy.sh start -e development # 启动服务
|
||||
```
|
||||
|
||||
### 4. 验证部署
|
||||
|
||||
```bash
|
||||
# 检查服务状态
|
||||
./deploy.sh status -e development
|
||||
|
||||
# 执行健康检查
|
||||
./deploy.sh health -e development --wait
|
||||
|
||||
# 访问应用
|
||||
# 前端: http://localhost:80
|
||||
# 后端API: http://localhost:8080
|
||||
```
|
||||
|
||||
## 🔧 环境要求
|
||||
|
||||
### 系统要求
|
||||
|
||||
| 组件 | 最低要求 | 推荐配置 |
|
||||
|------|----------|----------|
|
||||
| **操作系统** | Linux/macOS/Windows | Ubuntu 20.04+ / CentOS 8+ |
|
||||
| **CPU** | 2核心 | 4核心+ |
|
||||
| **内存** | 4GB | 8GB+ |
|
||||
| **磁盘空间** | 10GB | 20GB+ |
|
||||
| **网络** | 100Mbps | 1Gbps+ |
|
||||
|
||||
### 软件依赖
|
||||
|
||||
| 软件 | 版本要求 | 安装命令 |
|
||||
|------|----------|----------|
|
||||
| **Docker** | 20.10+ | `curl -fsSL https://get.docker.com \| sh` |
|
||||
| **Docker Compose** | 2.0+ | 随Docker Desktop安装 |
|
||||
| **Git** | 2.0+ | `apt install git` / `yum install git` |
|
||||
| **Bash** | 4.0+ | 系统自带 |
|
||||
|
||||
### 端口要求
|
||||
|
||||
确保以下端口未被占用:
|
||||
|
||||
| 服务 | 默认端口 | 可配置 | 说明 |
|
||||
|------|----------|--------|------|
|
||||
| 前端服务 | 80 | ✅ | HTTP访问端口 |
|
||||
| 后端服务 | 8080 | ✅ | API服务端口 |
|
||||
| 数据库 | 3306 | ✅ | MySQL连接端口 |
|
||||
|
||||
## 📁 目录结构
|
||||
|
||||
```
|
||||
docker/
|
||||
├── README.md # 本文档
|
||||
├── build.sh # 主构建脚本
|
||||
├── deploy.sh # 部署管理脚本
|
||||
├── docker-compose.yml # 基础编排文件
|
||||
├── docker-compose.*.yml # 环境特定编排文件
|
||||
├── validation-report.md # 验证报告
|
||||
│
|
||||
├── frontend/ # 前端容器配置
|
||||
│ ├── Dockerfile # 前端镜像构建文件
|
||||
│ └── nginx.conf.* # Nginx配置文件
|
||||
│
|
||||
├── backend/ # 后端容器配置
|
||||
│ ├── Dockerfile # 后端镜像构建文件
|
||||
│ └── startup.sh # 启动脚本
|
||||
│
|
||||
├── database/ # 数据库配置
|
||||
│ ├── docker-compose.database.yml
|
||||
│ ├── init/ # 初始化脚本
|
||||
│ └── README.md
|
||||
│
|
||||
├── environments/ # 环境配置
|
||||
│ ├── .env.example # 配置模板
|
||||
│ ├── .env.development # 开发环境
|
||||
│ ├── .env.staging # 测试环境
|
||||
│ └── .env.production # 生产环境
|
||||
│
|
||||
├── configs/ # 配置文件模板
|
||||
│ ├── nginx.conf.* # Nginx配置模板
|
||||
│ ├── application-docker.yml # Spring Boot配置
|
||||
│ └── my.cnf.* # MySQL配置
|
||||
│
|
||||
├── scripts/ # 辅助脚本
|
||||
│ ├── env-config.sh # 环境配置管理
|
||||
│ ├── validate-*.sh # 配置验证脚本
|
||||
│ ├── backup.sh # 数据备份脚本
|
||||
│ └── setup-env.sh # 环境初始化
|
||||
│
|
||||
└── data/ # 数据目录(运行时创建)
|
||||
├── mysql/ # 数据库数据
|
||||
├── logs/ # 日志文件
|
||||
└── uploads/ # 上传文件
|
||||
```
|
||||
|
||||
## 📖 详细部署步骤
|
||||
|
||||
### 步骤1:环境配置
|
||||
|
||||
#### 1.1 创建环境配置文件
|
||||
|
||||
```bash
|
||||
# 复制配置模板
|
||||
cp environments/.env.example environments/.env.development
|
||||
|
||||
# 编辑配置文件
|
||||
vim environments/.env.development
|
||||
```
|
||||
|
||||
#### 1.2 关键配置项说明
|
||||
|
||||
```bash
|
||||
# 基础环境配置
|
||||
ENVIRONMENT=development # 环境标识
|
||||
COMPOSE_PROJECT_NAME=anxin # Docker Compose项目名
|
||||
|
||||
# 数据库配置
|
||||
DB_HOST=anxin-mysql # 数据库主机
|
||||
DB_PORT=3306 # 数据库端口
|
||||
DB_NAME=anxin # 数据库名
|
||||
DB_USER=anxin_user # 数据库用户
|
||||
DB_PASSWORD=your_secure_password # 数据库密码
|
||||
|
||||
# 服务端口配置
|
||||
FRONTEND_PORT=80 # 前端服务端口
|
||||
BACKEND_PORT=8080 # 后端服务端口
|
||||
|
||||
# 资源限制配置
|
||||
BACKEND_MEMORY_LIMIT=1024 # 后端内存限制(MB)
|
||||
DATABASE_MEMORY_LIMIT=512 # 数据库内存限制(MB)
|
||||
```
|
||||
|
||||
### 步骤2:构建镜像
|
||||
|
||||
#### 2.1 构建所有镜像
|
||||
|
||||
```bash
|
||||
# 构建所有镜像(开发环境)
|
||||
./build.sh build-all -e development
|
||||
|
||||
# 构建特定组件
|
||||
./build.sh build -c frontend -e development
|
||||
./build.sh build -c backend -e development
|
||||
|
||||
# 强制重新构建(不使用缓存)
|
||||
./build.sh build-all -e development --no-cache
|
||||
```
|
||||
|
||||
#### 2.2 构建选项说明
|
||||
|
||||
| 选项 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| `-e, --env` | 指定环境 | `-e production` |
|
||||
| `-c, --component` | 指定组件 | `-c frontend` |
|
||||
| `--pull` | 构建前拉取代码 | `--pull` |
|
||||
| `--no-cache` | 不使用构建缓存 | `--no-cache` |
|
||||
| `--clean` | 清理构建缓存 | `--clean` |
|
||||
| `--verbose` | 显示详细日志 | `--verbose` |
|
||||
|
||||
### 步骤3:启动服务
|
||||
|
||||
#### 3.1 启动所有服务
|
||||
|
||||
```bash
|
||||
# 启动所有服务
|
||||
./deploy.sh start -e development
|
||||
|
||||
# 启动特定服务
|
||||
./deploy.sh start mysql -e development
|
||||
./deploy.sh start backend frontend -e development
|
||||
```
|
||||
|
||||
#### 3.2 服务管理命令
|
||||
|
||||
```bash
|
||||
# 查看服务状态
|
||||
./deploy.sh status -e development
|
||||
|
||||
# 重启服务
|
||||
./deploy.sh restart -e development
|
||||
|
||||
# 停止服务
|
||||
./deploy.sh stop -e development
|
||||
|
||||
# 完全清理(删除容器和网络)
|
||||
./deploy.sh down -e development
|
||||
```
|
||||
|
||||
### 步骤4:验证部署
|
||||
|
||||
#### 4.1 健康检查
|
||||
|
||||
```bash
|
||||
# 执行健康检查
|
||||
./deploy.sh health -e development
|
||||
|
||||
# 等待所有服务健康
|
||||
./deploy.sh health -e development --wait --retry 10
|
||||
```
|
||||
|
||||
#### 4.2 访问测试
|
||||
|
||||
```bash
|
||||
# 测试前端访问
|
||||
curl -I http://localhost:80
|
||||
|
||||
# 测试后端API
|
||||
curl -I http://localhost:8080/actuator/health
|
||||
|
||||
# 测试数据库连接
|
||||
mysql -h localhost -P 3306 -u anxin_user -p
|
||||
```
|
||||
|
||||
## ⚙️ 环境配置
|
||||
|
||||
### 开发环境 (Development)
|
||||
|
||||
```bash
|
||||
# 特点:启用调试模式,详细日志,热重载
|
||||
ENVIRONMENT=development
|
||||
LOG_LEVEL=DEBUG
|
||||
SPRING_PROFILES_ACTIVE=docker,dev
|
||||
```
|
||||
|
||||
### 测试环境 (Staging)
|
||||
|
||||
```bash
|
||||
# 特点:接近生产配置,性能测试
|
||||
ENVIRONMENT=staging
|
||||
LOG_LEVEL=INFO
|
||||
SPRING_PROFILES_ACTIVE=docker,staging
|
||||
```
|
||||
|
||||
### 生产环境 (Production)
|
||||
|
||||
```bash
|
||||
# 特点:优化性能,安全配置,监控
|
||||
ENVIRONMENT=production
|
||||
LOG_LEVEL=WARN
|
||||
SPRING_PROFILES_ACTIVE=docker,prod
|
||||
```
|
||||
|
||||
### 环境切换
|
||||
|
||||
```bash
|
||||
# 切换到生产环境
|
||||
./build.sh deploy -e production --pull
|
||||
|
||||
# 切换到开发环境
|
||||
./deploy.sh restart -e development
|
||||
```
|
||||
|
||||
## 🔄 服务管理
|
||||
|
||||
### 启动服务
|
||||
|
||||
```bash
|
||||
# 启动所有服务
|
||||
./deploy.sh start
|
||||
|
||||
# 启动特定服务
|
||||
./deploy.sh start mysql
|
||||
./deploy.sh start backend frontend
|
||||
|
||||
# 强制重新创建容器
|
||||
./deploy.sh start --force
|
||||
```
|
||||
|
||||
### 停止服务
|
||||
|
||||
```bash
|
||||
# 停止所有服务
|
||||
./deploy.sh stop
|
||||
|
||||
# 停止特定服务
|
||||
./deploy.sh stop backend
|
||||
|
||||
# 设置停止超时时间
|
||||
./deploy.sh stop -t 60
|
||||
```
|
||||
|
||||
### 重启服务
|
||||
|
||||
```bash
|
||||
# 重启所有服务
|
||||
./deploy.sh restart
|
||||
|
||||
# 重启特定服务
|
||||
./deploy.sh restart backend
|
||||
```
|
||||
|
||||
### 服务状态
|
||||
|
||||
```bash
|
||||
# 查看详细状态
|
||||
./deploy.sh status
|
||||
|
||||
# 查看容器列表
|
||||
./deploy.sh ps
|
||||
|
||||
# 查看网络和卷信息
|
||||
docker network ls | grep anxin
|
||||
docker volume ls | grep anxin
|
||||
```
|
||||
|
||||
## 📊 监控和日志
|
||||
|
||||
### 日志查看
|
||||
|
||||
```bash
|
||||
# 查看所有服务日志
|
||||
./deploy.sh logs
|
||||
|
||||
# 查看特定服务日志
|
||||
./deploy.sh logs backend
|
||||
|
||||
# 实时跟踪日志
|
||||
./deploy.sh logs -f
|
||||
|
||||
# 查看最近100行日志
|
||||
./deploy.sh logs --tail 100
|
||||
|
||||
# 查看最近1小时日志
|
||||
./deploy.sh logs --since 1h
|
||||
```
|
||||
|
||||
### 健康监控
|
||||
|
||||
```bash
|
||||
# 执行健康检查
|
||||
./deploy.sh health
|
||||
|
||||
# 持续监控(等待所有服务健康)
|
||||
./deploy.sh health --wait --retry 20 --interval 30
|
||||
|
||||
# 查看服务详细信息
|
||||
docker inspect anxin-backend-development
|
||||
```
|
||||
|
||||
### 性能监控
|
||||
|
||||
```bash
|
||||
# 查看容器资源使用
|
||||
docker stats
|
||||
|
||||
# 查看特定容器资源使用
|
||||
docker stats anxin-backend-development
|
||||
|
||||
# 查看系统资源
|
||||
free -h
|
||||
df -h
|
||||
```
|
||||
|
||||
## 🔧 故障排除
|
||||
|
||||
### 常见问题诊断
|
||||
|
||||
#### 1. 服务启动失败
|
||||
|
||||
**症状**:容器无法启动或立即退出
|
||||
|
||||
**诊断步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 查看容器状态
|
||||
./deploy.sh status
|
||||
|
||||
# 2. 查看容器日志
|
||||
./deploy.sh logs [service_name]
|
||||
|
||||
# 3. 检查配置文件
|
||||
cat environments/.env.development
|
||||
|
||||
# 4. 验证端口占用
|
||||
netstat -tlnp | grep :80
|
||||
netstat -tlnp | grep :8080
|
||||
netstat -tlnp | grep :3306
|
||||
```
|
||||
|
||||
**常见原因及解决方案**:
|
||||
|
||||
| 问题 | 原因 | 解决方案 |
|
||||
|------|------|----------|
|
||||
| 端口被占用 | 其他服务占用端口 | `sudo lsof -i :80` 查找并停止占用进程 |
|
||||
| 内存不足 | 系统内存不够 | 增加系统内存或调整容器内存限制 |
|
||||
| 配置错误 | 环境变量配置错误 | 检查并修正 `.env` 文件 |
|
||||
| 镜像构建失败 | 依赖下载失败 | 检查网络连接,使用 `--no-cache` 重新构建 |
|
||||
|
||||
#### 2. 数据库连接失败
|
||||
|
||||
**症状**:后端无法连接数据库
|
||||
|
||||
**诊断步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 检查数据库容器状态
|
||||
docker ps | grep mysql
|
||||
|
||||
# 2. 检查数据库日志
|
||||
./deploy.sh logs mysql
|
||||
|
||||
# 3. 测试数据库连接
|
||||
docker exec -it anxin-mysql-development mysql -u root -p
|
||||
|
||||
# 4. 检查网络连接
|
||||
docker network inspect anxin-development_default
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 重启数据库服务
|
||||
./deploy.sh restart mysql
|
||||
|
||||
# 检查数据库初始化
|
||||
docker exec anxin-mysql-development mysql -u root -p -e "SHOW DATABASES;"
|
||||
|
||||
# 重新初始化数据库
|
||||
./deploy.sh down
|
||||
rm -rf data/development/mysql
|
||||
./deploy.sh start
|
||||
```
|
||||
|
||||
#### 3. 前端无法访问后端API
|
||||
|
||||
**症状**:前端页面加载但API调用失败
|
||||
|
||||
**诊断步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 检查后端服务状态
|
||||
curl -I http://localhost:8080/actuator/health
|
||||
|
||||
# 2. 检查Nginx配置
|
||||
docker exec anxin-frontend-development cat /etc/nginx/nginx.conf
|
||||
|
||||
# 3. 查看Nginx日志
|
||||
./deploy.sh logs frontend
|
||||
|
||||
# 4. 检查网络连通性
|
||||
docker exec anxin-frontend-development ping anxin-backend
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 重启前端服务
|
||||
./deploy.sh restart frontend
|
||||
|
||||
# 检查API代理配置
|
||||
# 编辑 configs/nginx.conf.development
|
||||
# 确保 proxy_pass 指向正确的后端服务
|
||||
```
|
||||
|
||||
#### 4. 镜像构建失败
|
||||
|
||||
**症状**:Docker镜像构建过程中出错
|
||||
|
||||
**诊断步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 查看构建日志
|
||||
./build.sh build-all --verbose
|
||||
|
||||
# 2. 检查Dockerfile语法
|
||||
docker run --rm -i hadolint/hadolint < frontend/Dockerfile
|
||||
|
||||
# 3. 手动构建测试
|
||||
cd frontend
|
||||
docker build -t test-frontend .
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 清理构建缓存
|
||||
./build.sh clean
|
||||
|
||||
# 强制重新构建
|
||||
./build.sh build-all --no-cache
|
||||
|
||||
# 检查网络连接
|
||||
ping registry-1.docker.io
|
||||
```
|
||||
|
||||
#### 5. 性能问题
|
||||
|
||||
**症状**:服务响应缓慢或资源使用过高
|
||||
|
||||
**诊断步骤**:
|
||||
|
||||
```bash
|
||||
# 1. 查看资源使用情况
|
||||
docker stats
|
||||
|
||||
# 2. 检查系统负载
|
||||
top
|
||||
htop
|
||||
iostat -x 1
|
||||
|
||||
# 3. 分析日志
|
||||
./deploy.sh logs --since 1h | grep -i error
|
||||
./deploy.sh logs --since 1h | grep -i slow
|
||||
```
|
||||
|
||||
**解决方案**:
|
||||
|
||||
```bash
|
||||
# 调整资源限制
|
||||
# 编辑 environments/.env.development
|
||||
BACKEND_MEMORY_LIMIT=2048
|
||||
DATABASE_MEMORY_LIMIT=1024
|
||||
|
||||
# 重启服务应用新配置
|
||||
./deploy.sh restart
|
||||
```
|
||||
|
||||
### 日志分析
|
||||
|
||||
#### 关键日志位置
|
||||
|
||||
```bash
|
||||
# 容器日志
|
||||
docker logs anxin-backend-development
|
||||
|
||||
# 应用日志(挂载到宿主机)
|
||||
tail -f data/development/backend-logs/application.log
|
||||
tail -f data/development/mysql-logs/error.log
|
||||
tail -f data/development/nginx-logs/access.log
|
||||
```
|
||||
|
||||
#### 日志级别说明
|
||||
|
||||
| 级别 | 说明 | 使用场景 |
|
||||
|------|------|----------|
|
||||
| ERROR | 错误信息 | 生产环境问题排查 |
|
||||
| WARN | 警告信息 | 潜在问题识别 |
|
||||
| INFO | 一般信息 | 正常运行监控 |
|
||||
| DEBUG | 调试信息 | 开发环境调试 |
|
||||
|
||||
### 数据备份与恢复
|
||||
|
||||
#### 数据备份
|
||||
|
||||
```bash
|
||||
# 使用内置备份脚本
|
||||
./scripts/backup.sh -e development
|
||||
|
||||
# 手动备份数据库
|
||||
docker exec anxin-mysql-development mysqldump -u root -p anxin > backup.sql
|
||||
|
||||
# 备份数据卷
|
||||
docker run --rm -v anxin-development_mysql-data:/data -v $(pwd):/backup alpine tar czf /backup/mysql-data-backup.tar.gz /data
|
||||
```
|
||||
|
||||
#### 数据恢复
|
||||
|
||||
```bash
|
||||
# 恢复数据库
|
||||
docker exec -i anxin-mysql-development mysql -u root -p anxin < backup.sql
|
||||
|
||||
# 恢复数据卷
|
||||
docker run --rm -v anxin-development_mysql-data:/data -v $(pwd):/backup alpine tar xzf /backup/mysql-data-backup.tar.gz -C /
|
||||
```
|
||||
|
||||
### 网络问题排查
|
||||
|
||||
#### 检查网络配置
|
||||
|
||||
```bash
|
||||
# 查看Docker网络
|
||||
docker network ls
|
||||
docker network inspect anxin-development_default
|
||||
|
||||
# 检查容器网络连接
|
||||
docker exec anxin-frontend-development ping anxin-backend
|
||||
docker exec anxin-backend-development ping anxin-mysql
|
||||
|
||||
# 检查端口映射
|
||||
docker port anxin-frontend-development
|
||||
docker port anxin-backend-development
|
||||
```
|
||||
|
||||
#### 解决网络问题
|
||||
|
||||
```bash
|
||||
# 重新创建网络
|
||||
./deploy.sh down
|
||||
./deploy.sh start
|
||||
|
||||
# 检查防火墙设置
|
||||
sudo ufw status
|
||||
sudo iptables -L
|
||||
```
|
||||
|
||||
## 🚀 性能优化
|
||||
|
||||
### 容器资源优化
|
||||
|
||||
#### 内存优化
|
||||
|
||||
```bash
|
||||
# 调整JVM内存设置
|
||||
JAVA_OPTS=-Xms512m -Xmx1024m -XX:+UseG1GC
|
||||
|
||||
# 调整MySQL内存设置
|
||||
# 编辑 configs/my.cnf.production
|
||||
innodb_buffer_pool_size = 256M
|
||||
key_buffer_size = 64M
|
||||
```
|
||||
|
||||
#### CPU优化
|
||||
|
||||
```bash
|
||||
# 设置CPU限制
|
||||
# 在 docker-compose.yml 中
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1024M
|
||||
```
|
||||
|
||||
### 镜像优化
|
||||
|
||||
#### 减小镜像大小
|
||||
|
||||
```bash
|
||||
# 使用多阶段构建
|
||||
# 使用Alpine Linux基础镜像
|
||||
# 清理不必要的文件和缓存
|
||||
|
||||
# 查看镜像大小
|
||||
docker images | grep anxin
|
||||
```
|
||||
|
||||
#### 构建缓存优化
|
||||
|
||||
```bash
|
||||
# 合理安排Dockerfile层级
|
||||
# 将变化频率低的操作放在前面
|
||||
# 使用.dockerignore排除不必要文件
|
||||
```
|
||||
|
||||
### 数据库优化
|
||||
|
||||
#### MySQL配置优化
|
||||
|
||||
```bash
|
||||
# 编辑 configs/my.cnf.production
|
||||
[mysqld]
|
||||
innodb_buffer_pool_size = 512M
|
||||
innodb_log_file_size = 128M
|
||||
max_connections = 200
|
||||
query_cache_size = 64M
|
||||
```
|
||||
|
||||
#### 索引优化
|
||||
|
||||
```sql
|
||||
-- 分析慢查询
|
||||
SHOW PROCESSLIST;
|
||||
SHOW FULL PROCESSLIST;
|
||||
|
||||
-- 查看索引使用情况
|
||||
EXPLAIN SELECT * FROM your_table WHERE condition;
|
||||
```
|
||||
|
||||
## 🔒 安全配置
|
||||
|
||||
### 容器安全
|
||||
|
||||
#### 用户权限
|
||||
|
||||
```bash
|
||||
# 使用非root用户运行容器
|
||||
# 在Dockerfile中添加
|
||||
RUN addgroup -g 1001 appuser && adduser -u 1001 -G appuser -s /bin/sh -D appuser
|
||||
USER appuser
|
||||
```
|
||||
|
||||
#### 网络安全
|
||||
|
||||
```bash
|
||||
# 限制容器网络访问
|
||||
# 使用自定义网络
|
||||
# 关闭不必要的端口映射
|
||||
```
|
||||
|
||||
### 数据安全
|
||||
|
||||
#### 密码管理
|
||||
|
||||
```bash
|
||||
# 使用强密码
|
||||
# 定期更换密码
|
||||
# 使用Docker secrets管理敏感信息
|
||||
|
||||
# 创建密码文件
|
||||
echo "your_secure_password" | docker secret create db_password -
|
||||
```
|
||||
|
||||
#### 数据加密
|
||||
|
||||
```bash
|
||||
# 启用MySQL SSL
|
||||
# 配置应用程序使用SSL连接
|
||||
# 加密敏感数据字段
|
||||
```
|
||||
|
||||
### 访问控制
|
||||
|
||||
#### 防火墙配置
|
||||
|
||||
```bash
|
||||
# 配置iptables规则
|
||||
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
||||
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
|
||||
sudo iptables -A INPUT -p tcp --dport 3306 -s 172.20.0.0/16 -j ACCEPT
|
||||
```
|
||||
|
||||
#### 反向代理
|
||||
|
||||
```bash
|
||||
# 使用Nginx作为反向代理
|
||||
# 配置SSL终止
|
||||
# 实现负载均衡
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q1: 如何更新应用版本?
|
||||
|
||||
**A**:
|
||||
|
||||
```bash
|
||||
# 1. 拉取最新代码
|
||||
./build.sh pull
|
||||
|
||||
# 2. 重新构建镜像
|
||||
./build.sh build-all --no-cache
|
||||
|
||||
# 3. 重启服务
|
||||
./deploy.sh restart
|
||||
```
|
||||
|
||||
### Q2: 如何扩展服务实例?
|
||||
|
||||
**A**:
|
||||
|
||||
```bash
|
||||
# 编辑 docker-compose.yml
|
||||
services:
|
||||
anxin-backend:
|
||||
deploy:
|
||||
replicas: 3
|
||||
|
||||
# 重新部署
|
||||
./deploy.sh restart
|
||||
```
|
||||
|
||||
### Q3: 如何迁移到其他服务器?
|
||||
|
||||
**A**:
|
||||
|
||||
```bash
|
||||
# 1. 备份数据
|
||||
./scripts/backup.sh
|
||||
|
||||
# 2. 复制项目文件和备份到新服务器
|
||||
rsync -av . user@newserver:/path/to/project
|
||||
|
||||
# 3. 在新服务器上恢复
|
||||
./deploy.sh start
|
||||
# 恢复数据库备份
|
||||
```
|
||||
|
||||
### Q4: 如何配置SSL证书?
|
||||
|
||||
**A**:
|
||||
|
||||
```bash
|
||||
# 1. 获取SSL证书
|
||||
# 2. 修改Nginx配置
|
||||
# 3. 更新docker-compose.yml端口映射
|
||||
# 4. 重启前端服务
|
||||
```
|
||||
|
||||
### Q5: 如何监控服务健康状态?
|
||||
|
||||
**A**:
|
||||
|
||||
```bash
|
||||
# 使用内置健康检查
|
||||
./deploy.sh health --wait
|
||||
|
||||
# 集成外部监控工具
|
||||
# - Prometheus + Grafana
|
||||
# - ELK Stack
|
||||
# - Zabbix
|
||||
```
|
||||
|
||||
### Q6: 如何处理数据库迁移?
|
||||
|
||||
**A**:
|
||||
|
||||
```bash
|
||||
# 1. 备份当前数据
|
||||
./scripts/backup.sh
|
||||
|
||||
# 2. 停止服务
|
||||
./deploy.sh stop
|
||||
|
||||
# 3. 更新数据库脚本
|
||||
# 4. 重启服务(自动执行迁移)
|
||||
./deploy.sh start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如果遇到问题,请按以下步骤获取帮助:
|
||||
|
||||
1. **查看日志**:`./deploy.sh logs -f`
|
||||
2. **检查状态**:`./deploy.sh health`
|
||||
3. **查阅文档**:参考本文档故障排除部分
|
||||
4. **收集信息**:准备错误日志、配置文件、系统信息
|
||||
5. **寻求帮助**:联系技术支持团队
|
||||
|
||||
### 信息收集脚本
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 收集诊断信息
|
||||
echo "=== 系统信息 ===" > diagnostic.log
|
||||
uname -a >> diagnostic.log
|
||||
docker --version >> diagnostic.log
|
||||
docker-compose --version >> diagnostic.log
|
||||
|
||||
echo "=== 服务状态 ===" >> diagnostic.log
|
||||
./deploy.sh status >> diagnostic.log
|
||||
|
||||
echo "=== 最近日志 ===" >> diagnostic.log
|
||||
./deploy.sh logs --tail 100 >> diagnostic.log
|
||||
|
||||
echo "诊断信息已保存到 diagnostic.log"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: 1.0.0
|
||||
**最后更新**: $(date '+%Y-%m-%d')
|
||||
**维护团队**: 若依框架开发团队
|
||||
60
docker/backend/.dockerignore
Normal file
60
docker/backend/.dockerignore
Normal file
@ -0,0 +1,60 @@
|
||||
# Docker ignore file for backend build
|
||||
# 排除不需要的文件和目录以优化构建上下文
|
||||
|
||||
# Git相关
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# IDE相关
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# 构建产物 (除了需要的JAR文件)
|
||||
target/
|
||||
!ruoyi-admin/target/ruoyi-admin.jar
|
||||
|
||||
# 日志文件
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# 临时文件
|
||||
*.tmp
|
||||
*.temp
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# 操作系统相关
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Node.js相关 (前端相关,后端不需要)
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Docker相关
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
docker-compose*.yml
|
||||
|
||||
# 文档
|
||||
README.md
|
||||
doc/
|
||||
*.md
|
||||
|
||||
# 前端相关目录
|
||||
RuoYi-Vue3/
|
||||
|
||||
# 其他Docker目录
|
||||
docker/frontend/
|
||||
docker/database/
|
||||
docker/configs/
|
||||
docker/scripts/
|
||||
|
||||
# 测试相关
|
||||
.jqwik-database
|
||||
2
docker/backend/.gitkeep
Normal file
2
docker/backend/.gitkeep
Normal file
@ -0,0 +1,2 @@
|
||||
# 后端容器配置目录
|
||||
# 此文件确保目录被Git跟踪
|
||||
111
docker/backend/Dockerfile
Normal file
111
docker/backend/Dockerfile
Normal file
@ -0,0 +1,111 @@
|
||||
# 多阶段构建 Dockerfile for 若依后端应用
|
||||
# Stage 1: 构建阶段 - 使用Maven构建应用
|
||||
FROM maven:3.8-openjdk-8 AS builder
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 复制Maven配置文件
|
||||
COPY pom.xml .
|
||||
COPY ruoyi-admin/pom.xml ruoyi-admin/
|
||||
COPY ruoyi-framework/pom.xml ruoyi-framework/
|
||||
COPY ruoyi-system/pom.xml ruoyi-system/
|
||||
COPY ruoyi-quartz/pom.xml ruoyi-quartz/
|
||||
COPY ruoyi-generator/pom.xml ruoyi-generator/
|
||||
COPY ruoyi-common/pom.xml ruoyi-common/
|
||||
COPY ruoyi-credit/pom.xml ruoyi-credit/
|
||||
COPY ruoyi-blockchain/pom.xml ruoyi-blockchain/
|
||||
COPY ruoyi-payment/pom.xml ruoyi-payment/
|
||||
COPY ruoyi-security/pom.xml ruoyi-security/
|
||||
COPY ruoyi-notification/pom.xml ruoyi-notification/
|
||||
COPY ruoyi-analytics/pom.xml ruoyi-analytics/
|
||||
COPY ruoyi-workflow/pom.xml ruoyi-workflow/
|
||||
COPY ruoyi-integration/pom.xml ruoyi-integration/
|
||||
COPY ruoyi-monitor/pom.xml ruoyi-monitor/
|
||||
|
||||
# 下载依赖 (利用Docker缓存层优化)
|
||||
RUN mvn dependency:go-offline -B
|
||||
|
||||
# 复制源代码
|
||||
COPY ruoyi-admin/src ruoyi-admin/src
|
||||
COPY ruoyi-framework/src ruoyi-framework/src
|
||||
COPY ruoyi-system/src ruoyi-system/src
|
||||
COPY ruoyi-quartz/src ruoyi-quartz/src
|
||||
COPY ruoyi-generator/src ruoyi-generator/src
|
||||
COPY ruoyi-common/src ruoyi-common/src
|
||||
COPY ruoyi-credit/src ruoyi-credit/src
|
||||
COPY ruoyi-blockchain/src ruoyi-blockchain/src
|
||||
COPY ruoyi-payment/src ruoyi-payment/src
|
||||
COPY ruoyi-security/src ruoyi-security/src
|
||||
COPY ruoyi-notification/src ruoyi-notification/src
|
||||
COPY ruoyi-analytics/src ruoyi-analytics/src
|
||||
COPY ruoyi-workflow/src ruoyi-workflow/src
|
||||
COPY ruoyi-integration/src ruoyi-integration/src
|
||||
COPY ruoyi-monitor/src ruoyi-monitor/src
|
||||
|
||||
# 执行Maven构建,跳过测试以加快构建速度
|
||||
RUN mvn clean package -DskipTests -B
|
||||
|
||||
# Stage 2: 运行阶段 - 使用轻量级JRE镜像
|
||||
FROM openjdk:8-jre-alpine
|
||||
|
||||
# 设置时区并安装必要工具
|
||||
RUN apk add --no-cache tzdata netcat-openbsd && \
|
||||
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
echo "Asia/Shanghai" > /etc/timezone && \
|
||||
apk del tzdata
|
||||
|
||||
# 创建应用用户 (安全最佳实践)
|
||||
RUN addgroup -g 1000 anxin && \
|
||||
adduser -D -s /bin/sh -u 1000 -G anxin anxin
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 从构建阶段复制JAR文件
|
||||
COPY --from=builder /app/ruoyi-admin/target/ruoyi-admin.jar app.jar
|
||||
|
||||
# 复制Docker环境配置文件和脚本
|
||||
COPY docker/configs/application-docker.yml /app/config/application-docker.yml
|
||||
COPY docker/configs/backend-env.sh /app/scripts/backend-env.sh
|
||||
COPY docker/configs/startup.sh /app/scripts/startup.sh
|
||||
|
||||
# 创建日志目录、配置目录和脚本目录
|
||||
RUN mkdir -p /app/logs /app/config /app/uploadPath /app/scripts && \
|
||||
chown -R anxin:anxin /app && \
|
||||
chmod +x /app/scripts/backend-env.sh /app/scripts/startup.sh
|
||||
|
||||
# 切换到应用用户
|
||||
USER anxin
|
||||
|
||||
# 暴露应用端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 设置环境变量 - 数据库连接配置
|
||||
ENV DB_HOST=anxin-mysql \
|
||||
DB_PORT=3306 \
|
||||
DB_NAME=anxin \
|
||||
DB_USER=anxin_user \
|
||||
DB_PASSWORD=anxin_password
|
||||
|
||||
# 设置环境变量 - 应用端口和网络配置
|
||||
ENV SERVER_PORT=8080 \
|
||||
SPRING_PROFILES_ACTIVE=docker
|
||||
|
||||
# 设置环境变量 - 日志和监控配置
|
||||
ENV LOG_LEVEL=INFO \
|
||||
LOG_PATH=/app/logs \
|
||||
LOG_MAX_SIZE=100MB \
|
||||
LOG_MAX_FILES=10 \
|
||||
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=health,info,metrics
|
||||
|
||||
# 设置环境变量 - JVM和性能配置
|
||||
ENV JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker" \
|
||||
TZ=Asia/Shanghai
|
||||
|
||||
# 健康检查 - 使用配置的端口
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${SERVER_PORT}/actuator/health || exit 1
|
||||
|
||||
# 启动应用 - 使用启动脚本
|
||||
ENTRYPOINT ["/app/scripts/startup.sh"]
|
||||
129
docker/backend/build.bat
Normal file
129
docker/backend/build.bat
Normal file
@ -0,0 +1,129 @@
|
||||
@echo off
|
||||
REM 后端Docker镜像构建脚本 (Windows版本)
|
||||
REM 用于构建若依后端应用的Docker镜像
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM 脚本配置
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
set "PROJECT_ROOT=%SCRIPT_DIR%..\..\"
|
||||
set "IMAGE_NAME=anxin-backend"
|
||||
set "IMAGE_TAG=latest"
|
||||
set "NO_CACHE="
|
||||
set "CLEAN_BUILD="
|
||||
|
||||
REM 解析命令行参数
|
||||
:parse_args
|
||||
if "%~1"=="" goto :check_docker
|
||||
if "%~1"=="-t" (
|
||||
set "IMAGE_TAG=%~2"
|
||||
shift
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="--tag" (
|
||||
set "IMAGE_TAG=%~2"
|
||||
shift
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="-n" (
|
||||
set "IMAGE_NAME=%~2"
|
||||
shift
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="--name" (
|
||||
set "IMAGE_NAME=%~2"
|
||||
shift
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="--no-cache" (
|
||||
set "NO_CACHE=--no-cache"
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="--clean" (
|
||||
set "CLEAN_BUILD=true"
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="-h" goto :show_help
|
||||
if "%~1"=="--help" goto :show_help
|
||||
|
||||
echo [ERROR] 未知参数: %~1
|
||||
goto :show_help
|
||||
|
||||
:show_help
|
||||
echo.
|
||||
echo 后端Docker镜像构建脚本
|
||||
echo.
|
||||
echo 用法: %~nx0 [选项]
|
||||
echo.
|
||||
echo 选项:
|
||||
echo -t, --tag TAG 设置镜像标签 (默认: latest)
|
||||
echo -n, --name NAME 设置镜像名称 (默认: anxin-backend)
|
||||
echo --no-cache 不使用缓存构建
|
||||
echo --clean 构建前清理Maven缓存
|
||||
echo -h, --help 显示此帮助信息
|
||||
echo.
|
||||
echo 示例:
|
||||
echo %~nx0 # 使用默认设置构建
|
||||
echo %~nx0 -t v1.0.0 # 构建并标记为v1.0.0
|
||||
echo %~nx0 --no-cache # 不使用缓存构建
|
||||
echo %~nx0 --clean -t dev # 清理后构建dev版本
|
||||
echo.
|
||||
exit /b 0
|
||||
|
||||
:check_docker
|
||||
echo [INFO] 检查Docker环境...
|
||||
docker --version >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Docker未安装或不在PATH中
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
docker info >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Docker守护进程未运行
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:clean_maven
|
||||
if "%CLEAN_BUILD%"=="true" (
|
||||
echo [INFO] 清理Maven缓存...
|
||||
cd /d "%PROJECT_ROOT%"
|
||||
where mvn >nul 2>&1
|
||||
if not errorlevel 1 (
|
||||
mvn clean
|
||||
) else (
|
||||
echo [WARNING] Maven未安装,跳过清理步骤
|
||||
)
|
||||
)
|
||||
|
||||
:build_image
|
||||
echo [INFO] 开始构建Docker镜像...
|
||||
echo [INFO] 项目根目录: %PROJECT_ROOT%
|
||||
echo [INFO] 镜像名称: %IMAGE_NAME%:%IMAGE_TAG%
|
||||
|
||||
cd /d "%PROJECT_ROOT%"
|
||||
|
||||
echo [INFO] 执行构建命令...
|
||||
docker build -f docker/backend/Dockerfile -t %IMAGE_NAME%:%IMAGE_TAG% %NO_CACHE% .
|
||||
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Docker镜像构建失败
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [SUCCESS] Docker镜像构建成功: %IMAGE_NAME%:%IMAGE_TAG%
|
||||
|
||||
:show_image_info
|
||||
echo [INFO] 镜像信息:
|
||||
docker images %IMAGE_NAME%:%IMAGE_TAG%
|
||||
|
||||
echo [SUCCESS] 构建完成!
|
||||
echo [INFO] 运行镜像: docker run -d -p 8080:8080 --name anxin-backend-container %IMAGE_NAME%:%IMAGE_TAG%
|
||||
|
||||
endlocal
|
||||
162
docker/backend/build.sh
Normal file
162
docker/backend/build.sh
Normal file
@ -0,0 +1,162 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 后端Docker镜像构建脚本
|
||||
# 用于构建若依后端应用的Docker镜像
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# 脚本配置
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
IMAGE_NAME="anxin-backend"
|
||||
IMAGE_TAG="latest"
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
后端Docker镜像构建脚本
|
||||
|
||||
用法: $0 [选项]
|
||||
|
||||
选项:
|
||||
-t, --tag TAG 设置镜像标签 (默认: latest)
|
||||
-n, --name NAME 设置镜像名称 (默认: anxin-backend)
|
||||
--no-cache 不使用缓存构建
|
||||
--clean 构建前清理Maven缓存
|
||||
-h, --help 显示此帮助信息
|
||||
|
||||
示例:
|
||||
$0 # 使用默认设置构建
|
||||
$0 -t v1.0.0 # 构建并标记为v1.0.0
|
||||
$0 --no-cache # 不使用缓存构建
|
||||
$0 --clean -t dev # 清理后构建dev版本
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 解析命令行参数
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-t|--tag)
|
||||
IMAGE_TAG="$2"
|
||||
shift 2
|
||||
;;
|
||||
-n|--name)
|
||||
IMAGE_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
--no-cache)
|
||||
NO_CACHE="--no-cache"
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
CLEAN_BUILD=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_error "未知参数: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# 检查Docker是否可用
|
||||
check_docker() {
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info &> /dev/null; then
|
||||
log_error "Docker守护进程未运行"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理Maven缓存
|
||||
clean_maven() {
|
||||
if [[ "$CLEAN_BUILD" == "true" ]]; then
|
||||
log_info "清理Maven缓存..."
|
||||
cd "$PROJECT_ROOT"
|
||||
if command -v mvn &> /dev/null; then
|
||||
mvn clean
|
||||
else
|
||||
log_warning "Maven未安装,跳过清理步骤"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 构建Docker镜像
|
||||
build_image() {
|
||||
log_info "开始构建Docker镜像..."
|
||||
log_info "项目根目录: $PROJECT_ROOT"
|
||||
log_info "镜像名称: $IMAGE_NAME:$IMAGE_TAG"
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# 构建命令
|
||||
BUILD_CMD="docker build -f docker/backend/Dockerfile -t $IMAGE_NAME:$IMAGE_TAG $NO_CACHE ."
|
||||
|
||||
log_info "执行构建命令: $BUILD_CMD"
|
||||
|
||||
if eval "$BUILD_CMD"; then
|
||||
log_success "Docker镜像构建成功: $IMAGE_NAME:$IMAGE_TAG"
|
||||
else
|
||||
log_error "Docker镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示镜像信息
|
||||
show_image_info() {
|
||||
log_info "镜像信息:"
|
||||
docker images "$IMAGE_NAME:$IMAGE_TAG" --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
log_info "开始构建若依后端Docker镜像..."
|
||||
|
||||
parse_args "$@"
|
||||
check_docker
|
||||
clean_maven
|
||||
build_image
|
||||
show_image_info
|
||||
|
||||
log_success "构建完成!"
|
||||
log_info "运行镜像: docker run -d -p 8080:8080 --name anxin-backend-container $IMAGE_NAME:$IMAGE_TAG"
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
776
docker/build.sh
Normal file
776
docker/build.sh
Normal file
@ -0,0 +1,776 @@
|
||||
#!/bin/bash
|
||||
# 主构建脚本 - 若依框架Docker部署方案
|
||||
# 实现一键构建所有镜像、代码拉取更新和环境配置切换功能
|
||||
# Requirements: 5.1, 5.2, 5.3
|
||||
|
||||
set -e
|
||||
|
||||
# ===========================================
|
||||
# 脚本配置
|
||||
# ===========================================
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
DOCKER_DIR="$SCRIPT_DIR"
|
||||
|
||||
# 默认配置
|
||||
DEFAULT_ENVIRONMENT="development"
|
||||
DEFAULT_TAG="latest"
|
||||
BUILD_ALL=false
|
||||
PULL_CODE=false
|
||||
NO_CACHE=false
|
||||
CLEAN_BUILD=false
|
||||
VERBOSE=false
|
||||
|
||||
# 镜像配置
|
||||
FRONTEND_IMAGE="anxin-frontend"
|
||||
BACKEND_IMAGE="anxin-backend"
|
||||
MYSQL_IMAGE="mysql:8.0"
|
||||
|
||||
# ===========================================
|
||||
# 颜色定义
|
||||
# ===========================================
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ===========================================
|
||||
# 日志函数
|
||||
# ===========================================
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_debug() {
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
echo -e "${PURPLE}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
fi
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${CYAN}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 帮助信息
|
||||
# ===========================================
|
||||
show_help() {
|
||||
cat << EOF
|
||||
若依框架Docker部署 - 主构建脚本
|
||||
|
||||
用法: $0 [选项] [命令]
|
||||
|
||||
命令:
|
||||
build 构建指定组件的Docker镜像
|
||||
build-all 构建所有Docker镜像 (默认)
|
||||
pull 拉取最新代码
|
||||
deploy 构建并部署到指定环境
|
||||
clean 清理构建缓存和临时文件
|
||||
status 查看当前构建状态
|
||||
help 显示此帮助信息
|
||||
|
||||
选项:
|
||||
-e, --env ENV 指定环境 (development|staging|production) [默认: development]
|
||||
-t, --tag TAG 指定镜像标签 [默认: latest]
|
||||
-c, --component COMP 指定构建组件 (frontend|backend|all) [默认: all]
|
||||
--pull 构建前拉取最新代码
|
||||
--no-cache 不使用Docker构建缓存
|
||||
--clean 构建前清理缓存
|
||||
--verbose 显示详细日志
|
||||
-h, --help 显示此帮助信息
|
||||
|
||||
环境配置:
|
||||
development (dev) 开发环境 - 启用调试模式,使用开发配置
|
||||
staging (stage) 测试环境 - 接近生产的测试配置
|
||||
production (prod) 生产环境 - 优化的生产配置
|
||||
|
||||
示例:
|
||||
$0 # 构建所有镜像 (开发环境)
|
||||
$0 build-all -e production # 构建所有镜像 (生产环境)
|
||||
$0 build -c frontend -t v1.0.0 # 构建前端镜像并标记为v1.0.0
|
||||
$0 deploy -e staging --pull # 拉取代码并部署到测试环境
|
||||
$0 pull # 仅拉取最新代码
|
||||
$0 clean # 清理构建缓存
|
||||
|
||||
Requirements Coverage:
|
||||
5.1 - 一键构建所有镜像功能
|
||||
5.2 - 代码拉取和更新功能
|
||||
5.3 - 环境配置切换功能
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 参数解析
|
||||
# ===========================================
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
build)
|
||||
COMMAND="build"
|
||||
shift
|
||||
;;
|
||||
build-all)
|
||||
COMMAND="build-all"
|
||||
BUILD_ALL=true
|
||||
shift
|
||||
;;
|
||||
pull)
|
||||
COMMAND="pull"
|
||||
shift
|
||||
;;
|
||||
deploy)
|
||||
COMMAND="deploy"
|
||||
BUILD_ALL=true
|
||||
shift
|
||||
;;
|
||||
clean)
|
||||
COMMAND="clean"
|
||||
shift
|
||||
;;
|
||||
status)
|
||||
COMMAND="status"
|
||||
shift
|
||||
;;
|
||||
-e|--env)
|
||||
ENVIRONMENT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-t|--tag)
|
||||
TAG="$2"
|
||||
shift 2
|
||||
;;
|
||||
-c|--component)
|
||||
COMPONENT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--pull)
|
||||
PULL_CODE=true
|
||||
shift
|
||||
;;
|
||||
--no-cache)
|
||||
NO_CACHE=true
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
CLEAN_BUILD=true
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_error "未知参数: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 设置默认值
|
||||
COMMAND=${COMMAND:-"build-all"}
|
||||
ENVIRONMENT=${ENVIRONMENT:-$DEFAULT_ENVIRONMENT}
|
||||
TAG=${TAG:-$DEFAULT_TAG}
|
||||
COMPONENT=${COMPONENT:-"all"}
|
||||
|
||||
# 如果没有指定组件但命令是build,则构建所有组件
|
||||
if [[ "$COMMAND" == "build" && "$COMPONENT" == "all" ]]; then
|
||||
BUILD_ALL=true
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 环境验证和配置
|
||||
# ===========================================
|
||||
validate_environment() {
|
||||
case $ENVIRONMENT in
|
||||
development|dev)
|
||||
ENVIRONMENT="development"
|
||||
;;
|
||||
staging|stage)
|
||||
ENVIRONMENT="staging"
|
||||
;;
|
||||
production|prod)
|
||||
ENVIRONMENT="production"
|
||||
;;
|
||||
*)
|
||||
log_error "无效的环境: $ENVIRONMENT"
|
||||
log_info "支持的环境: development, staging, production"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_debug "环境验证通过: $ENVIRONMENT"
|
||||
}
|
||||
|
||||
# 加载环境配置
|
||||
load_environment_config() {
|
||||
local env_file="${DOCKER_DIR}/environments/.env.${ENVIRONMENT}"
|
||||
|
||||
if [[ ! -f "$env_file" ]]; then
|
||||
log_error "环境配置文件不存在: $env_file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "加载环境配置: $ENVIRONMENT"
|
||||
source "$env_file"
|
||||
|
||||
# 导出关键环境变量
|
||||
export ENVIRONMENT
|
||||
export COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-"anxin-${ENVIRONMENT}"}
|
||||
export SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-"docker"}
|
||||
|
||||
log_debug "环境配置加载完成"
|
||||
log_debug "项目名称: $COMPOSE_PROJECT_NAME"
|
||||
log_debug "Spring配置: $SPRING_PROFILES_ACTIVE"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 系统检查
|
||||
# ===========================================
|
||||
check_prerequisites() {
|
||||
log_step "检查系统依赖..."
|
||||
|
||||
# 检查Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Docker Compose
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Docker守护进程
|
||||
if ! docker info &> /dev/null; then
|
||||
log_error "Docker守护进程未运行"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Git (如果需要拉取代码)
|
||||
if [[ "$PULL_CODE" == "true" ]] && ! command -v git &> /dev/null; then
|
||||
log_error "Git未安装或不在PATH中,无法拉取代码"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "系统依赖检查通过"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 代码拉取和更新功能 (Requirement 5.2)
|
||||
# ===========================================
|
||||
pull_latest_code() {
|
||||
log_step "拉取最新代码..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# 检查是否为Git仓库
|
||||
if [[ ! -d ".git" ]]; then
|
||||
log_warn "当前目录不是Git仓库,跳过代码拉取"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 获取当前分支
|
||||
local current_branch=$(git branch --show-current)
|
||||
log_info "当前分支: $current_branch"
|
||||
|
||||
# 检查是否有未提交的更改
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
log_warn "检测到未提交的更改"
|
||||
read -p "是否继续拉取代码? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "取消代码拉取"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 拉取最新代码
|
||||
log_info "从远程仓库拉取最新代码..."
|
||||
if git pull origin "$current_branch"; then
|
||||
log_success "代码拉取成功"
|
||||
|
||||
# 检查是否有子模块
|
||||
if [[ -f ".gitmodules" ]]; then
|
||||
log_info "更新Git子模块..."
|
||||
git submodule update --init --recursive
|
||||
fi
|
||||
|
||||
# 显示最新提交信息
|
||||
log_info "最新提交信息:"
|
||||
git log --oneline -5
|
||||
|
||||
else
|
||||
log_error "代码拉取失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 构建准备
|
||||
# ===========================================
|
||||
prepare_build() {
|
||||
log_step "准备构建环境..."
|
||||
|
||||
# 创建必要的目录
|
||||
local data_dirs=(
|
||||
"${DOCKER_DIR}/data/mysql"
|
||||
"${DOCKER_DIR}/data/mysql-logs"
|
||||
"${DOCKER_DIR}/data/backend-logs"
|
||||
"${DOCKER_DIR}/data/uploads"
|
||||
"${DOCKER_DIR}/data/nginx-logs"
|
||||
)
|
||||
|
||||
for dir in "${data_dirs[@]}"; do
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
log_debug "创建目录: $dir"
|
||||
mkdir -p "$dir"
|
||||
fi
|
||||
done
|
||||
|
||||
# 设置目录权限
|
||||
log_debug "设置目录权限..."
|
||||
chmod -R 755 "${DOCKER_DIR}/data"
|
||||
|
||||
# 清理构建缓存 (如果指定)
|
||||
if [[ "$CLEAN_BUILD" == "true" ]]; then
|
||||
clean_build_cache
|
||||
fi
|
||||
|
||||
log_success "构建环境准备完成"
|
||||
}
|
||||
|
||||
# 清理构建缓存
|
||||
clean_build_cache() {
|
||||
log_info "清理构建缓存..."
|
||||
|
||||
# 清理Docker构建缓存
|
||||
log_debug "清理Docker构建缓存..."
|
||||
docker builder prune -f
|
||||
|
||||
# 清理Maven缓存 (如果存在)
|
||||
if command -v mvn &> /dev/null; then
|
||||
log_debug "清理Maven缓存..."
|
||||
cd "$PROJECT_ROOT"
|
||||
mvn clean -q
|
||||
fi
|
||||
|
||||
# 清理npm缓存 (如果存在)
|
||||
if command -v npm &> /dev/null; then
|
||||
log_debug "清理npm缓存..."
|
||||
cd "${PROJECT_ROOT}/RuoYi-Vue3"
|
||||
if [[ -d "node_modules" ]]; then
|
||||
rm -rf node_modules
|
||||
fi
|
||||
if [[ -f "package-lock.json" ]]; then
|
||||
rm -f package-lock.json
|
||||
fi
|
||||
fi
|
||||
|
||||
log_success "构建缓存清理完成"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 镜像构建功能 (Requirement 5.1)
|
||||
# ===========================================
|
||||
build_frontend_image() {
|
||||
log_step "构建前端镜像..."
|
||||
|
||||
local image_name="${FRONTEND_IMAGE}:${TAG}"
|
||||
local dockerfile_path="${DOCKER_DIR}/frontend/Dockerfile"
|
||||
local build_args=""
|
||||
|
||||
# 根据环境设置构建参数
|
||||
case $ENVIRONMENT in
|
||||
production)
|
||||
build_args="--build-arg NODE_ENV=production --build-arg API_BASE_URL=${API_BASE_URL:-http://localhost:8080}"
|
||||
;;
|
||||
staging)
|
||||
build_args="--build-arg NODE_ENV=production --build-arg API_BASE_URL=${API_BASE_URL:-http://localhost:8080}"
|
||||
;;
|
||||
development)
|
||||
build_args="--build-arg NODE_ENV=development --build-arg API_BASE_URL=${API_BASE_URL:-http://localhost:8080}"
|
||||
;;
|
||||
esac
|
||||
|
||||
# 构建命令
|
||||
local build_cmd="docker build -f $dockerfile_path -t $image_name $build_args"
|
||||
|
||||
if [[ "$NO_CACHE" == "true" ]]; then
|
||||
build_cmd="$build_cmd --no-cache"
|
||||
fi
|
||||
|
||||
build_cmd="$build_cmd $PROJECT_ROOT"
|
||||
|
||||
log_info "构建前端镜像: $image_name"
|
||||
log_debug "构建命令: $build_cmd"
|
||||
|
||||
if eval "$build_cmd"; then
|
||||
log_success "前端镜像构建成功: $image_name"
|
||||
|
||||
# 显示镜像信息
|
||||
local image_size=$(docker images --format "table {{.Size}}" "$image_name" | tail -n 1)
|
||||
log_info "镜像大小: $image_size"
|
||||
|
||||
return 0
|
||||
else
|
||||
log_error "前端镜像构建失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
build_backend_image() {
|
||||
log_step "构建后端镜像..."
|
||||
|
||||
local image_name="${BACKEND_IMAGE}:${TAG}"
|
||||
local dockerfile_path="${DOCKER_DIR}/backend/Dockerfile"
|
||||
local build_args=""
|
||||
|
||||
# 根据环境设置构建参数
|
||||
case $ENVIRONMENT in
|
||||
production)
|
||||
build_args="--build-arg SPRING_PROFILES_ACTIVE=docker,prod"
|
||||
;;
|
||||
staging)
|
||||
build_args="--build-arg SPRING_PROFILES_ACTIVE=docker,staging"
|
||||
;;
|
||||
development)
|
||||
build_args="--build-arg SPRING_PROFILES_ACTIVE=docker,dev"
|
||||
;;
|
||||
esac
|
||||
|
||||
# 构建命令
|
||||
local build_cmd="docker build -f $dockerfile_path -t $image_name $build_args"
|
||||
|
||||
if [[ "$NO_CACHE" == "true" ]]; then
|
||||
build_cmd="$build_cmd --no-cache"
|
||||
fi
|
||||
|
||||
build_cmd="$build_cmd $PROJECT_ROOT"
|
||||
|
||||
log_info "构建后端镜像: $image_name"
|
||||
log_debug "构建命令: $build_cmd"
|
||||
|
||||
if eval "$build_cmd"; then
|
||||
log_success "后端镜像构建成功: $image_name"
|
||||
|
||||
# 显示镜像信息
|
||||
local image_size=$(docker images --format "table {{.Size}}" "$image_name" | tail -n 1)
|
||||
log_info "镜像大小: $image_size"
|
||||
|
||||
return 0
|
||||
else
|
||||
log_error "后端镜像构建失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 构建所有镜像
|
||||
build_all_images() {
|
||||
log_step "开始构建所有镜像..."
|
||||
|
||||
local build_start_time=$(date +%s)
|
||||
local failed_builds=()
|
||||
|
||||
# 构建前端镜像
|
||||
if ! build_frontend_image; then
|
||||
failed_builds+=("frontend")
|
||||
fi
|
||||
|
||||
# 构建后端镜像
|
||||
if ! build_backend_image; then
|
||||
failed_builds+=("backend")
|
||||
fi
|
||||
|
||||
# 拉取MySQL镜像
|
||||
log_info "拉取MySQL镜像: $MYSQL_IMAGE"
|
||||
if docker pull "$MYSQL_IMAGE"; then
|
||||
log_success "MySQL镜像拉取成功"
|
||||
else
|
||||
log_warn "MySQL镜像拉取失败,将使用本地镜像"
|
||||
fi
|
||||
|
||||
local build_end_time=$(date +%s)
|
||||
local build_duration=$((build_end_time - build_start_time))
|
||||
|
||||
# 构建结果汇总
|
||||
if [[ ${#failed_builds[@]} -eq 0 ]]; then
|
||||
log_success "所有镜像构建成功! 耗时: ${build_duration}秒"
|
||||
show_build_summary
|
||||
return 0
|
||||
else
|
||||
log_error "以下镜像构建失败: ${failed_builds[*]}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示构建摘要
|
||||
show_build_summary() {
|
||||
log_info "构建摘要:"
|
||||
echo "----------------------------------------"
|
||||
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}" | grep -E "(anxin-|REPOSITORY)"
|
||||
echo "----------------------------------------"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 部署功能
|
||||
# ===========================================
|
||||
deploy_to_environment() {
|
||||
log_step "部署到 $ENVIRONMENT 环境..."
|
||||
|
||||
local compose_file="${DOCKER_DIR}/docker-compose.${ENVIRONMENT}.yml"
|
||||
local env_file="${DOCKER_DIR}/environments/.env.${ENVIRONMENT}"
|
||||
|
||||
# 检查文件是否存在
|
||||
if [[ ! -f "$compose_file" ]]; then
|
||||
log_error "Docker Compose文件不存在: $compose_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$env_file" ]]; then
|
||||
log_error "环境配置文件不存在: $env_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 停止现有服务
|
||||
log_info "停止现有服务..."
|
||||
cd "$DOCKER_DIR"
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" down --remove-orphans || true
|
||||
|
||||
# 启动新服务
|
||||
log_info "启动服务..."
|
||||
if docker-compose -f "$compose_file" --env-file "$env_file" up -d; then
|
||||
log_success "服务启动成功"
|
||||
|
||||
# 等待服务就绪
|
||||
log_info "等待服务就绪..."
|
||||
sleep 15
|
||||
|
||||
# 检查服务状态
|
||||
check_deployment_status "$compose_file" "$env_file"
|
||||
|
||||
return 0
|
||||
else
|
||||
log_error "服务启动失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查部署状态
|
||||
check_deployment_status() {
|
||||
local compose_file="$1"
|
||||
local env_file="$2"
|
||||
|
||||
log_info "检查服务状态..."
|
||||
|
||||
cd "$DOCKER_DIR"
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" ps
|
||||
|
||||
# 健康检查
|
||||
local services=("anxin-mysql" "anxin-backend" "anxin-frontend")
|
||||
local healthy_count=0
|
||||
|
||||
for service in "${services[@]}"; do
|
||||
local container_name="${service}-${ENVIRONMENT}"
|
||||
if docker ps --format "{{.Names}}" | grep -q "$service"; then
|
||||
local health=$(docker inspect --format='{{.State.Health.Status}}' "$service" 2>/dev/null || echo "no-healthcheck")
|
||||
case $health in
|
||||
"healthy"|"no-healthcheck")
|
||||
log_success "✓ $service: 运行正常"
|
||||
((healthy_count++))
|
||||
;;
|
||||
"starting")
|
||||
log_warn "⚠ $service: 正在启动中..."
|
||||
;;
|
||||
*)
|
||||
log_error "✗ $service: 健康检查失败 ($health)"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
log_error "✗ $service: 容器未运行"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $healthy_count -eq ${#services[@]} ]]; then
|
||||
log_success "所有服务运行正常"
|
||||
show_access_info
|
||||
else
|
||||
log_warn "部分服务可能存在问题,请检查日志"
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示访问信息
|
||||
show_access_info() {
|
||||
log_info "服务访问信息:"
|
||||
echo "----------------------------------------"
|
||||
echo "前端应用: http://localhost:${FRONTEND_PORT:-80}"
|
||||
echo "后端API: http://localhost:${BACKEND_PORT:-8080}"
|
||||
echo "数据库: localhost:${DB_PORT:-3306}"
|
||||
echo "----------------------------------------"
|
||||
echo "查看日志: docker-compose -f docker-compose.${ENVIRONMENT}.yml logs -f"
|
||||
echo "停止服务: docker-compose -f docker-compose.${ENVIRONMENT}.yml down"
|
||||
echo "----------------------------------------"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 状态检查
|
||||
# ===========================================
|
||||
show_status() {
|
||||
log_info "当前构建状态:"
|
||||
echo "----------------------------------------"
|
||||
echo "环境: $ENVIRONMENT"
|
||||
echo "标签: $TAG"
|
||||
echo "项目根目录: $PROJECT_ROOT"
|
||||
echo "Docker目录: $DOCKER_DIR"
|
||||
echo "----------------------------------------"
|
||||
|
||||
log_info "Docker镜像:"
|
||||
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}" | grep -E "(anxin-|REPOSITORY)" || echo "未找到相关镜像"
|
||||
|
||||
log_info "运行中的容器:"
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "(anxin-|NAMES)" || echo "未找到相关容器"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 清理功能
|
||||
# ===========================================
|
||||
clean_all() {
|
||||
log_step "清理所有构建产物和缓存..."
|
||||
|
||||
# 停止所有相关容器
|
||||
log_info "停止相关容器..."
|
||||
docker ps -a --format "{{.Names}}" | grep "anxin-" | xargs -r docker stop
|
||||
docker ps -a --format "{{.Names}}" | grep "anxin-" | xargs -r docker rm
|
||||
|
||||
# 删除相关镜像
|
||||
log_info "删除相关镜像..."
|
||||
docker images --format "{{.Repository}}:{{.Tag}}" | grep "anxin-" | xargs -r docker rmi -f
|
||||
|
||||
# 清理构建缓存
|
||||
clean_build_cache
|
||||
|
||||
# 清理数据目录 (谨慎操作)
|
||||
read -p "是否清理数据目录? 这将删除所有持久化数据 (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_warn "清理数据目录..."
|
||||
rm -rf "${DOCKER_DIR}/data"
|
||||
mkdir -p "${DOCKER_DIR}/data"
|
||||
fi
|
||||
|
||||
log_success "清理完成"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 主函数
|
||||
# ===========================================
|
||||
main() {
|
||||
# 显示脚本信息
|
||||
log_info "若依框架Docker部署 - 主构建脚本"
|
||||
log_info "脚本版本: 1.0.0"
|
||||
log_info "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
# 解析参数
|
||||
parse_args "$@"
|
||||
|
||||
# 验证环境
|
||||
validate_environment
|
||||
|
||||
# 加载环境配置
|
||||
load_environment_config
|
||||
|
||||
# 检查系统依赖
|
||||
check_prerequisites
|
||||
|
||||
# 根据命令执行相应操作
|
||||
case $COMMAND in
|
||||
pull)
|
||||
pull_latest_code
|
||||
;;
|
||||
build)
|
||||
if [[ "$PULL_CODE" == "true" ]]; then
|
||||
pull_latest_code
|
||||
fi
|
||||
prepare_build
|
||||
|
||||
case $COMPONENT in
|
||||
frontend)
|
||||
build_frontend_image
|
||||
;;
|
||||
backend)
|
||||
build_backend_image
|
||||
;;
|
||||
all)
|
||||
build_all_images
|
||||
;;
|
||||
*)
|
||||
log_error "无效的组件: $COMPONENT"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
build-all)
|
||||
if [[ "$PULL_CODE" == "true" ]]; then
|
||||
pull_latest_code
|
||||
fi
|
||||
prepare_build
|
||||
build_all_images
|
||||
;;
|
||||
deploy)
|
||||
if [[ "$PULL_CODE" == "true" ]]; then
|
||||
pull_latest_code
|
||||
fi
|
||||
prepare_build
|
||||
build_all_images
|
||||
if [[ $? -eq 0 ]]; then
|
||||
deploy_to_environment
|
||||
else
|
||||
log_error "构建失败,取消部署"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
clean)
|
||||
clean_all
|
||||
;;
|
||||
*)
|
||||
log_error "未知命令: $COMMAND"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_success "脚本执行完成!"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 错误处理
|
||||
# ===========================================
|
||||
trap 'log_error "脚本执行被中断"; exit 1' INT TERM
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
2
docker/configs/.gitkeep
Normal file
2
docker/configs/.gitkeep
Normal file
@ -0,0 +1,2 @@
|
||||
# 配置文件模板目录
|
||||
# 此文件确保目录被Git跟踪
|
||||
139
docker/configs/backend-env.bat
Normal file
139
docker/configs/backend-env.bat
Normal file
@ -0,0 +1,139 @@
|
||||
@echo off
|
||||
REM 后端环境变量配置脚本 (Windows版本)
|
||||
REM 用于设置不同环境下的后端应用配置
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM 默认环境变量配置
|
||||
if not defined DB_HOST set DB_HOST=anxin-mysql
|
||||
if not defined DB_PORT set DB_PORT=3306
|
||||
if not defined DB_NAME set DB_NAME=anxin
|
||||
if not defined DB_USER set DB_USER=anxin_user
|
||||
if not defined DB_PASSWORD set DB_PASSWORD=anxin_password
|
||||
|
||||
REM 应用端口和网络配置
|
||||
if not defined SERVER_PORT set SERVER_PORT=8080
|
||||
if not defined SPRING_PROFILES_ACTIVE set SPRING_PROFILES_ACTIVE=docker
|
||||
|
||||
REM 日志配置
|
||||
if not defined LOG_LEVEL set LOG_LEVEL=INFO
|
||||
if not defined LOG_PATH set LOG_PATH=/app/logs
|
||||
if not defined LOG_MAX_SIZE set LOG_MAX_SIZE=100MB
|
||||
if not defined LOG_MAX_FILES set LOG_MAX_FILES=10
|
||||
|
||||
REM 监控配置
|
||||
if not defined MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE set MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=health,info,metrics
|
||||
|
||||
REM JVM配置
|
||||
if not defined JAVA_OPTS set JAVA_OPTS=-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom
|
||||
|
||||
REM 安全配置
|
||||
if not defined JWT_SECRET set JWT_SECRET=abcdefghijklmnopqrstuvwxyz
|
||||
if not defined JWT_EXPIRE_TIME set JWT_EXPIRE_TIME=30
|
||||
|
||||
REM Druid监控配置
|
||||
if not defined DRUID_USERNAME set DRUID_USERNAME=admin
|
||||
if not defined DRUID_PASSWORD set DRUID_PASSWORD=admin123
|
||||
|
||||
REM 文件上传路径
|
||||
if not defined UPLOAD_PATH set UPLOAD_PATH=/app/uploadPath
|
||||
|
||||
REM Swagger配置
|
||||
if not defined SWAGGER_ENABLED set SWAGGER_ENABLED=false
|
||||
|
||||
REM 时区配置
|
||||
if not defined TZ set TZ=Asia/Shanghai
|
||||
|
||||
goto :main
|
||||
|
||||
:validate_required_env
|
||||
echo 验证必需的环境变量...
|
||||
set missing_vars=
|
||||
if not defined DB_HOST set missing_vars=!missing_vars! DB_HOST
|
||||
if not defined DB_PORT set missing_vars=!missing_vars! DB_PORT
|
||||
if not defined DB_NAME set missing_vars=!missing_vars! DB_NAME
|
||||
if not defined DB_USER set missing_vars=!missing_vars! DB_USER
|
||||
if not defined DB_PASSWORD set missing_vars=!missing_vars! DB_PASSWORD
|
||||
|
||||
if not "!missing_vars!"=="" (
|
||||
echo 错误: 以下必需的环境变量未设置:
|
||||
echo !missing_vars!
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo 所有必需的环境变量已设置
|
||||
exit /b 0
|
||||
|
||||
:show_config
|
||||
echo === 后端应用环境配置 ===
|
||||
echo 数据库配置:
|
||||
echo DB_HOST: %DB_HOST%
|
||||
echo DB_PORT: %DB_PORT%
|
||||
echo DB_NAME: %DB_NAME%
|
||||
echo DB_USER: %DB_USER%
|
||||
echo DB_PASSWORD: [HIDDEN]
|
||||
echo.
|
||||
echo 应用配置:
|
||||
echo SERVER_PORT: %SERVER_PORT%
|
||||
echo SPRING_PROFILES_ACTIVE: %SPRING_PROFILES_ACTIVE%
|
||||
echo.
|
||||
echo 日志配置:
|
||||
echo LOG_LEVEL: %LOG_LEVEL%
|
||||
echo LOG_PATH: %LOG_PATH%
|
||||
echo LOG_MAX_SIZE: %LOG_MAX_SIZE%
|
||||
echo LOG_MAX_FILES: %LOG_MAX_FILES%
|
||||
echo.
|
||||
echo JVM配置:
|
||||
echo JAVA_OPTS: %JAVA_OPTS%
|
||||
echo.
|
||||
echo 其他配置:
|
||||
echo TZ: %TZ%
|
||||
echo UPLOAD_PATH: %UPLOAD_PATH%
|
||||
echo SWAGGER_ENABLED: %SWAGGER_ENABLED%
|
||||
echo ==========================
|
||||
exit /b 0
|
||||
|
||||
:load_environment
|
||||
set env_type=%1
|
||||
if "%env_type%"=="" set env_type=development
|
||||
|
||||
if "%env_type%"=="production" (
|
||||
set LOG_LEVEL=WARN
|
||||
set SWAGGER_ENABLED=false
|
||||
set JAVA_OPTS=-Xms1024m -Xmx2048m -Djava.security.egd=file:/dev/./urandom -XX:+UseG1GC
|
||||
echo 已加载生产环境配置
|
||||
) else if "%env_type%"=="staging" (
|
||||
set LOG_LEVEL=INFO
|
||||
set SWAGGER_ENABLED=true
|
||||
set JAVA_OPTS=-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom
|
||||
echo 已加载预发布环境配置
|
||||
) else if "%env_type%"=="development" (
|
||||
set LOG_LEVEL=DEBUG
|
||||
set SWAGGER_ENABLED=true
|
||||
set JAVA_OPTS=-Xms256m -Xmx512m -Djava.security.egd=file:/dev/./urandom
|
||||
echo 已加载开发环境配置
|
||||
) else (
|
||||
echo 警告: 未知的环境类型 '%env_type%',使用默认配置
|
||||
)
|
||||
exit /b 0
|
||||
|
||||
:main
|
||||
set command=%1
|
||||
if "%command%"=="" set command=show
|
||||
|
||||
if "%command%"=="validate" (
|
||||
call :validate_required_env
|
||||
) else if "%command%"=="show" (
|
||||
call :show_config
|
||||
) else if "%command%"=="load" (
|
||||
call :load_environment %2
|
||||
call :show_config
|
||||
) else (
|
||||
echo 用法: %0 {validate^|show^|load [environment]}
|
||||
echo validate - 验证必需的环境变量
|
||||
echo show - 显示当前环境配置
|
||||
echo load - 加载指定环境配置 ^(development^|staging^|production^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
endlocal
|
||||
157
docker/configs/backend-env.sh
Normal file
157
docker/configs/backend-env.sh
Normal file
@ -0,0 +1,157 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 后端环境变量配置脚本
|
||||
# 用于设置不同环境下的后端应用配置
|
||||
|
||||
set -e
|
||||
|
||||
# 默认环境变量配置
|
||||
export DB_HOST=${DB_HOST:-"anxin-mysql"}
|
||||
export DB_PORT=${DB_PORT:-"3306"}
|
||||
export DB_NAME=${DB_NAME:-"anxin"}
|
||||
export DB_USER=${DB_USER:-"anxin_user"}
|
||||
export DB_PASSWORD=${DB_PASSWORD:-"anxin_password"}
|
||||
|
||||
# 应用端口和网络配置
|
||||
export SERVER_PORT=${SERVER_PORT:-"8080"}
|
||||
export SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-"docker"}
|
||||
|
||||
# 日志配置
|
||||
export LOG_LEVEL=${LOG_LEVEL:-"INFO"}
|
||||
export LOG_PATH=${LOG_PATH:-"/app/logs"}
|
||||
export LOG_MAX_SIZE=${LOG_MAX_SIZE:-"100MB"}
|
||||
export LOG_MAX_FILES=${LOG_MAX_FILES:-"10"}
|
||||
|
||||
# 监控配置
|
||||
export MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE=${MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE:-"health,info,metrics"}
|
||||
|
||||
# JVM配置
|
||||
export JAVA_OPTS=${JAVA_OPTS:-"-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom"}
|
||||
|
||||
# 安全配置
|
||||
export JWT_SECRET=${JWT_SECRET:-"abcdefghijklmnopqrstuvwxyz"}
|
||||
export JWT_EXPIRE_TIME=${JWT_EXPIRE_TIME:-"30"}
|
||||
|
||||
# Druid监控配置
|
||||
export DRUID_USERNAME=${DRUID_USERNAME:-"admin"}
|
||||
export DRUID_PASSWORD=${DRUID_PASSWORD:-"admin123"}
|
||||
|
||||
# 文件上传路径
|
||||
export UPLOAD_PATH=${UPLOAD_PATH:-"/app/uploadPath"}
|
||||
|
||||
# Swagger配置
|
||||
export SWAGGER_ENABLED=${SWAGGER_ENABLED:-"false"}
|
||||
|
||||
# 时区配置
|
||||
export TZ=${TZ:-"Asia/Shanghai"}
|
||||
|
||||
# 函数:验证必需的环境变量
|
||||
validate_required_env() {
|
||||
local required_vars=("DB_HOST" "DB_PORT" "DB_NAME" "DB_USER" "DB_PASSWORD")
|
||||
local missing_vars=()
|
||||
|
||||
for var in "${required_vars[@]}"; do
|
||||
if [[ -z "${!var}" ]]; then
|
||||
missing_vars+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#missing_vars[@]} -gt 0 ]]; then
|
||||
echo "错误: 以下必需的环境变量未设置:"
|
||||
printf '%s\n' "${missing_vars[@]}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "所有必需的环境变量已设置"
|
||||
return 0
|
||||
}
|
||||
|
||||
# 函数:显示当前环境配置
|
||||
show_config() {
|
||||
echo "=== 后端应用环境配置 ==="
|
||||
echo "数据库配置:"
|
||||
echo " DB_HOST: $DB_HOST"
|
||||
echo " DB_PORT: $DB_PORT"
|
||||
echo " DB_NAME: $DB_NAME"
|
||||
echo " DB_USER: $DB_USER"
|
||||
echo " DB_PASSWORD: [HIDDEN]"
|
||||
echo ""
|
||||
echo "应用配置:"
|
||||
echo " SERVER_PORT: $SERVER_PORT"
|
||||
echo " SPRING_PROFILES_ACTIVE: $SPRING_PROFILES_ACTIVE"
|
||||
echo ""
|
||||
echo "日志配置:"
|
||||
echo " LOG_LEVEL: $LOG_LEVEL"
|
||||
echo " LOG_PATH: $LOG_PATH"
|
||||
echo " LOG_MAX_SIZE: $LOG_MAX_SIZE"
|
||||
echo " LOG_MAX_FILES: $LOG_MAX_FILES"
|
||||
echo ""
|
||||
echo "JVM配置:"
|
||||
echo " JAVA_OPTS: $JAVA_OPTS"
|
||||
echo ""
|
||||
echo "其他配置:"
|
||||
echo " TZ: $TZ"
|
||||
echo " UPLOAD_PATH: $UPLOAD_PATH"
|
||||
echo " SWAGGER_ENABLED: $SWAGGER_ENABLED"
|
||||
echo "=========================="
|
||||
}
|
||||
|
||||
# 函数:根据环境类型加载配置
|
||||
load_environment() {
|
||||
local env_type=${1:-"development"}
|
||||
|
||||
case $env_type in
|
||||
"production")
|
||||
export LOG_LEVEL="WARN"
|
||||
export SWAGGER_ENABLED="false"
|
||||
export JAVA_OPTS="-Xms1024m -Xmx2048m -Djava.security.egd=file:/dev/./urandom -XX:+UseG1GC"
|
||||
echo "已加载生产环境配置"
|
||||
;;
|
||||
"staging")
|
||||
export LOG_LEVEL="INFO"
|
||||
export SWAGGER_ENABLED="true"
|
||||
export JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom"
|
||||
echo "已加载预发布环境配置"
|
||||
;;
|
||||
"development")
|
||||
export LOG_LEVEL="DEBUG"
|
||||
export SWAGGER_ENABLED="true"
|
||||
export JAVA_OPTS="-Xms256m -Xmx512m -Djava.security.egd=file:/dev/./urandom"
|
||||
echo "已加载开发环境配置"
|
||||
;;
|
||||
*)
|
||||
echo "警告: 未知的环境类型 '$env_type',使用默认配置"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local command=${1:-"show"}
|
||||
|
||||
case $command in
|
||||
"validate")
|
||||
validate_required_env
|
||||
;;
|
||||
"show")
|
||||
show_config
|
||||
;;
|
||||
"load")
|
||||
local env_type=${2:-"development"}
|
||||
load_environment "$env_type"
|
||||
show_config
|
||||
;;
|
||||
*)
|
||||
echo "用法: $0 {validate|show|load [environment]}"
|
||||
echo " validate - 验证必需的环境变量"
|
||||
echo " show - 显示当前环境配置"
|
||||
echo " load - 加载指定环境配置 (development|staging|production)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 如果脚本被直接执行,运行主函数
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
71
docker/configs/my.cnf.prod
Normal file
71
docker/configs/my.cnf.prod
Normal file
@ -0,0 +1,71 @@
|
||||
# MySQL配置文件 - 生产环境
|
||||
# 针对生产环境优化的MySQL配置
|
||||
|
||||
[mysqld]
|
||||
# 基础配置
|
||||
user = mysql
|
||||
pid-file = /var/run/mysqld/mysqld.pid
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
port = 3306
|
||||
basedir = /usr
|
||||
datadir = /var/lib/mysql
|
||||
tmpdir = /tmp
|
||||
lc-messages-dir = /usr/share/mysql
|
||||
skip-external-locking
|
||||
|
||||
# 字符集配置
|
||||
character-set-server = utf8mb4
|
||||
collation-server = utf8mb4_unicode_ci
|
||||
init_connect = 'SET NAMES utf8mb4'
|
||||
|
||||
# 网络配置
|
||||
bind-address = 0.0.0.0
|
||||
max_connections = 200
|
||||
max_connect_errors = 100000
|
||||
max_allowed_packet = 64M
|
||||
interactive_timeout = 600
|
||||
wait_timeout = 600
|
||||
|
||||
# 缓存配置 - 生产环境优化
|
||||
key_buffer_size = 256M
|
||||
max_allowed_packet = 64M
|
||||
table_open_cache = 4000
|
||||
sort_buffer_size = 4M
|
||||
read_buffer_size = 2M
|
||||
read_rnd_buffer_size = 8M
|
||||
myisam_sort_buffer_size = 128M
|
||||
thread_cache_size = 50
|
||||
query_cache_type = 1
|
||||
query_cache_size = 128M
|
||||
query_cache_limit = 2M
|
||||
|
||||
# InnoDB配置 - 生产环境优化
|
||||
innodb_buffer_pool_size = 512M
|
||||
innodb_log_file_size = 128M
|
||||
innodb_log_buffer_size = 16M
|
||||
innodb_flush_log_at_trx_commit = 1
|
||||
innodb_lock_wait_timeout = 50
|
||||
innodb_file_per_table = 1
|
||||
innodb_flush_method = O_DIRECT
|
||||
|
||||
# 日志配置
|
||||
log_error = /var/log/mysql/error.log
|
||||
slow_query_log = 1
|
||||
slow_query_log_file = /var/log/mysql/slow.log
|
||||
long_query_time = 2
|
||||
log_queries_not_using_indexes = 1
|
||||
|
||||
# 二进制日志配置 - 生产环境启用
|
||||
log_bin = /var/log/mysql/mysql-bin.log
|
||||
binlog_format = ROW
|
||||
expire_logs_days = 7
|
||||
max_binlog_size = 100M
|
||||
|
||||
# 安全配置
|
||||
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
|
||||
|
||||
[mysql]
|
||||
default-character-set = utf8mb4
|
||||
|
||||
[client]
|
||||
default-character-set = utf8mb4
|
||||
62
docker/configs/nginx.conf.dev
Normal file
62
docker/configs/nginx.conf.dev
Normal file
@ -0,0 +1,62 @@
|
||||
# Nginx配置文件 - 开发环境
|
||||
# 用于Vue3前端静态文件服务和API代理
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
# 开发环境特有配置
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log debug;
|
||||
|
||||
# 静态文件服务
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# 开发环境禁用缓存
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
add_header Expires "0";
|
||||
}
|
||||
|
||||
# API代理到后端服务
|
||||
location /prod-api/ {
|
||||
proxy_pass http://anxin-backend:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 开发环境代理配置
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_buffering off;
|
||||
|
||||
# CORS配置用于开发环境
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
|
||||
|
||||
if ($request_method = 'OPTIONS') {
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
# 开发工具代理 (如果需要)
|
||||
location /sockjs-node/ {
|
||||
proxy_pass http://anxin-frontend:24678;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
# 健康检查端点
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
124
docker/configs/nginx.conf.prod
Normal file
124
docker/configs/nginx.conf.prod
Normal file
@ -0,0 +1,124 @@
|
||||
# Nginx配置文件 - 生产环境
|
||||
# 用于Vue3前端静态文件服务和API代理
|
||||
|
||||
# HTTP服务器 - 重定向到HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name anxin.com www.anxin.com;
|
||||
|
||||
# 强制重定向到HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
# HTTPS服务器 - 主要配置
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name anxin.com www.anxin.com;
|
||||
|
||||
# SSL配置
|
||||
ssl_certificate /etc/nginx/ssl/anxin.com.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/anxin.com.key;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_tickets off;
|
||||
|
||||
# 现代SSL配置
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# HSTS配置
|
||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||
|
||||
# 生产环境日志配置
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log error;
|
||||
|
||||
# 安全头配置
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.anxin.com;";
|
||||
|
||||
# Gzip压缩配置
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/json
|
||||
application/javascript
|
||||
application/xml+rss
|
||||
application/atom+xml
|
||||
image/svg+xml;
|
||||
|
||||
# 静态文件服务
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# 生产环境缓存配置
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ~* \.(html)$ {
|
||||
expires 1h;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
}
|
||||
|
||||
# API代理到后端服务
|
||||
location /prod-api/ {
|
||||
proxy_pass http://anxin-backend:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 生产环境代理配置
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_send_timeout 10s;
|
||||
proxy_read_timeout 10s;
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 8 4k;
|
||||
|
||||
# 限制请求大小
|
||||
client_max_body_size 5m;
|
||||
|
||||
# 代理缓存配置
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
}
|
||||
|
||||
# 健康检查端点
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# 拒绝访问敏感文件
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~ ~$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
}
|
||||
70
docker/configs/nginx.conf.staging
Normal file
70
docker/configs/nginx.conf.staging
Normal file
@ -0,0 +1,70 @@
|
||||
# Nginx配置文件 - 测试环境
|
||||
# 用于Vue3前端静态文件服务和API代理
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name staging.anxin.com localhost;
|
||||
|
||||
# 测试环境日志配置
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
# 安全头配置
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin";
|
||||
|
||||
# 静态文件服务
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# 测试环境缓存配置
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
||||
expires 1d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
location ~* \.(html)$ {
|
||||
expires 1h;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
}
|
||||
|
||||
# API代理到后端服务
|
||||
location /prod-api/ {
|
||||
proxy_pass http://anxin-backend:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 测试环境代理配置
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 8 4k;
|
||||
|
||||
# 限制请求大小
|
||||
client_max_body_size 10m;
|
||||
}
|
||||
|
||||
# 健康检查端点
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# 测试环境状态页面
|
||||
location /nginx_status {
|
||||
stub_status on;
|
||||
access_log off;
|
||||
allow 172.22.0.0/16;
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
68
docker/configs/startup.sh
Normal file
68
docker/configs/startup.sh
Normal file
@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 后端应用启动脚本
|
||||
# 负责验证环境配置并启动Spring Boot应用
|
||||
|
||||
set -e
|
||||
|
||||
# 导入环境配置脚本
|
||||
source /app/scripts/backend-env.sh
|
||||
|
||||
echo "=== 安信数字信贷系统后端启动 ==="
|
||||
echo "启动时间: $(date)"
|
||||
echo "时区: $TZ"
|
||||
|
||||
# 验证必需的环境变量
|
||||
echo "正在验证环境配置..."
|
||||
if ! validate_required_env; then
|
||||
echo "环境配置验证失败,退出启动"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 显示当前配置
|
||||
show_config
|
||||
|
||||
# 等待数据库服务可用
|
||||
echo "正在等待数据库服务可用..."
|
||||
max_attempts=30
|
||||
attempt=1
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if nc -z "$DB_HOST" "$DB_PORT" 2>/dev/null; then
|
||||
echo "数据库服务已可用 ($DB_HOST:$DB_PORT)"
|
||||
break
|
||||
fi
|
||||
|
||||
echo "等待数据库服务... (尝试 $attempt/$max_attempts)"
|
||||
sleep 2
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
|
||||
if [ $attempt -gt $max_attempts ]; then
|
||||
echo "错误: 无法连接到数据库服务 $DB_HOST:$DB_PORT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建必要的目录
|
||||
mkdir -p "$LOG_PATH" "$UPLOAD_PATH"
|
||||
|
||||
# 设置Spring Boot配置文件路径
|
||||
export SPRING_CONFIG_LOCATION="classpath:/application.yml,file:/app/config/application-docker.yml"
|
||||
|
||||
# 构建完整的Java启动命令
|
||||
JAVA_CMD="java $JAVA_OPTS \
|
||||
-Dserver.port=$SERVER_PORT \
|
||||
-Dspring.profiles.active=$SPRING_PROFILES_ACTIVE \
|
||||
-Dspring.config.location=$SPRING_CONFIG_LOCATION \
|
||||
-Dlogging.level.com.ruoyi=$LOG_LEVEL \
|
||||
-Dlogging.file.name=$LOG_PATH/anxin.log \
|
||||
-Dspring.datasource.url=jdbc:mysql://$DB_HOST:$DB_PORT/$DB_NAME?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true \
|
||||
-Dspring.datasource.username=$DB_USER \
|
||||
-Dspring.datasource.password=$DB_PASSWORD \
|
||||
-jar app.jar"
|
||||
|
||||
echo "启动命令: $JAVA_CMD"
|
||||
echo "=== 应用启动中... ==="
|
||||
|
||||
# 启动应用
|
||||
exec $JAVA_CMD
|
||||
2
docker/database/.gitkeep
Normal file
2
docker/database/.gitkeep
Normal file
@ -0,0 +1,2 @@
|
||||
# 数据库容器配置目录
|
||||
# 此文件确保目录被Git跟踪
|
||||
258
docker/database/README.md
Normal file
258
docker/database/README.md
Normal file
@ -0,0 +1,258 @@
|
||||
# 数据库Docker配置
|
||||
|
||||
本目录包含MySQL数据库的Docker容器化配置文件和管理脚本。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
database/
|
||||
├── init/ # 数据库初始化脚本目录
|
||||
│ ├── 01-init-database.sql # 数据库和用户初始化
|
||||
│ └── 02-schema.sql # 数据库表结构
|
||||
├── data/ # 数据存储目录(运行时创建)
|
||||
│ ├── mysql/ # MySQL数据文件
|
||||
│ └── logs/ # MySQL日志文件
|
||||
├── backup/ # 数据库备份目录(运行时创建)
|
||||
├── docker-compose.database.yml # 数据库服务Docker Compose配置
|
||||
├── .env.database.template # 环境变量配置模板
|
||||
├── database-manager.sh # 数据库管理脚本(Linux/Mac)
|
||||
├── database-manager.bat # 数据库管理脚本(Windows)
|
||||
└── README.md # 本文件
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 配置环境变量
|
||||
|
||||
复制环境变量模板并根据需要修改:
|
||||
|
||||
```bash
|
||||
# Linux/Mac
|
||||
cp .env.database.template .env.database
|
||||
|
||||
# Windows
|
||||
copy .env.database.template .env.database
|
||||
```
|
||||
|
||||
编辑 `.env.database` 文件,修改数据库密码等配置。
|
||||
|
||||
### 2. 启动数据库
|
||||
|
||||
```bash
|
||||
# Linux/Mac
|
||||
./database-manager.sh start
|
||||
|
||||
# Windows
|
||||
database-manager.bat start
|
||||
```
|
||||
|
||||
### 3. 检查状态
|
||||
|
||||
```bash
|
||||
# Linux/Mac
|
||||
./database-manager.sh status
|
||||
|
||||
# Windows
|
||||
database-manager.bat status
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
主要的环境变量配置项:
|
||||
|
||||
| 变量名 | 默认值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `DB_HOST` | anxin-mysql | 数据库主机名 |
|
||||
| `DB_PORT` | 3306 | 数据库端口 |
|
||||
| `DB_NAME` | anxin | 数据库名称 |
|
||||
| `DB_USER` | anxin | 应用数据库用户 |
|
||||
| `DB_PASSWORD` | anxin123 | 应用数据库密码 |
|
||||
| `MYSQL_ROOT_PASSWORD` | root123 | MySQL root密码 |
|
||||
| `DATABASE_MEMORY_LIMIT` | 512M | 内存限制 |
|
||||
| `DATABASE_CPU_LIMIT` | 0.5 | CPU限制 |
|
||||
|
||||
### MySQL配置
|
||||
|
||||
MySQL配置文件位于 `../configs/my.cnf.template`,包含以下优化:
|
||||
|
||||
- 字符集:utf8mb4
|
||||
- 时区:Asia/Shanghai
|
||||
- 连接数:200
|
||||
- InnoDB缓冲池:128M
|
||||
- 慢查询日志:启用
|
||||
|
||||
### 数据持久化
|
||||
|
||||
数据持久化通过Docker卷实现:
|
||||
|
||||
- **mysql-data**: 数据库数据文件,挂载到 `./data/mysql`
|
||||
- **mysql-logs**: 数据库日志文件,挂载到 `./data/logs/mysql`
|
||||
|
||||
### 初始化脚本
|
||||
|
||||
初始化脚本按文件名字母顺序执行:
|
||||
|
||||
1. `01-init-database.sql`: 创建数据库和用户
|
||||
2. `02-schema.sql`: 导入数据库表结构
|
||||
|
||||
## 管理脚本使用
|
||||
|
||||
### 基本操作
|
||||
|
||||
```bash
|
||||
# 启动数据库
|
||||
./database-manager.sh start
|
||||
|
||||
# 停止数据库
|
||||
./database-manager.sh stop
|
||||
|
||||
# 重启数据库
|
||||
./database-manager.sh restart
|
||||
|
||||
# 查看状态
|
||||
./database-manager.sh status
|
||||
```
|
||||
|
||||
### 日志查看
|
||||
|
||||
```bash
|
||||
# 查看最近100行日志
|
||||
./database-manager.sh logs
|
||||
|
||||
# 查看最近50行日志
|
||||
./database-manager.sh logs 50
|
||||
|
||||
# 实时跟踪日志
|
||||
./database-manager.sh logs
|
||||
```
|
||||
|
||||
### 数据库连接
|
||||
|
||||
```bash
|
||||
# 进入数据库容器
|
||||
./database-manager.sh exec
|
||||
|
||||
# 直接连接MySQL
|
||||
./database-manager.sh connect
|
||||
```
|
||||
|
||||
### 备份和恢复
|
||||
|
||||
```bash
|
||||
# 备份数据库
|
||||
./database-manager.sh backup
|
||||
|
||||
# 恢复数据库
|
||||
./database-manager.sh restore backup/anxin_20250104_120000.sql
|
||||
```
|
||||
|
||||
## 网络配置
|
||||
|
||||
数据库容器运行在自定义网络 `anxin-network` 中:
|
||||
|
||||
- 网络类型:bridge
|
||||
- 子网:172.20.0.0/16
|
||||
- 网关:172.20.0.1
|
||||
|
||||
## 安全配置
|
||||
|
||||
### 密码安全
|
||||
|
||||
- 生产环境请修改默认密码
|
||||
- 使用强密码策略
|
||||
- 定期更换密码
|
||||
|
||||
### 网络安全
|
||||
|
||||
- 数据库端口仅在需要时暴露到宿主机
|
||||
- 使用内部网络进行容器间通信
|
||||
- 启用防火墙规则
|
||||
|
||||
### 文件权限
|
||||
|
||||
- 数据目录权限:755
|
||||
- 配置文件权限:644
|
||||
- 脚本文件权限:755
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **容器启动失败**
|
||||
- 检查端口是否被占用
|
||||
- 检查数据目录权限
|
||||
- 查看容器日志
|
||||
|
||||
2. **数据库连接失败**
|
||||
- 检查网络配置
|
||||
- 验证用户名密码
|
||||
- 确认数据库已完全启动
|
||||
|
||||
3. **初始化脚本执行失败**
|
||||
- 检查SQL语法
|
||||
- 查看初始化日志
|
||||
- 验证文件权限
|
||||
|
||||
### 日志位置
|
||||
|
||||
- 容器日志:`docker-compose logs`
|
||||
- MySQL错误日志:`./data/logs/mysql/error.log`
|
||||
- MySQL慢查询日志:`./data/logs/mysql/slow.log`
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 内存配置
|
||||
|
||||
根据服务器配置调整内存限制:
|
||||
|
||||
```bash
|
||||
# 开发环境
|
||||
DATABASE_MEMORY_LIMIT=512M
|
||||
|
||||
# 测试环境
|
||||
DATABASE_MEMORY_LIMIT=1024M
|
||||
|
||||
# 生产环境
|
||||
DATABASE_MEMORY_LIMIT=2048M
|
||||
```
|
||||
|
||||
### InnoDB优化
|
||||
|
||||
主要的InnoDB配置项:
|
||||
|
||||
- `innodb_buffer_pool_size`: 缓冲池大小
|
||||
- `innodb_log_file_size`: 日志文件大小
|
||||
- `innodb_flush_log_at_trx_commit`: 事务提交策略
|
||||
|
||||
## 监控和维护
|
||||
|
||||
### 健康检查
|
||||
|
||||
容器配置了健康检查:
|
||||
|
||||
- 检查间隔:30秒
|
||||
- 超时时间:20秒
|
||||
- 重试次数:10次
|
||||
- 启动等待:60秒
|
||||
|
||||
### 定期维护
|
||||
|
||||
建议的维护任务:
|
||||
|
||||
- 定期备份数据库
|
||||
- 监控磁盘使用情况
|
||||
- 检查慢查询日志
|
||||
- 更新安全补丁
|
||||
|
||||
## 集成说明
|
||||
|
||||
本数据库配置可以与以下组件集成:
|
||||
|
||||
- 后端Spring Boot应用
|
||||
- 前端Vue3应用
|
||||
- 监控系统
|
||||
- 备份系统
|
||||
|
||||
通过Docker Compose的依赖配置,确保数据库在其他服务之前启动。
|
||||
210
docker/database/database-manager.bat
Normal file
210
docker/database/database-manager.bat
Normal file
@ -0,0 +1,210 @@
|
||||
@echo off
|
||||
REM 数据库管理脚本 (Windows版本)
|
||||
REM 用于管理MySQL数据库容器的启动、停止、备份等操作
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM 脚本配置
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
set "PROJECT_ROOT=%SCRIPT_DIR%..\.."
|
||||
set "COMPOSE_FILE=%SCRIPT_DIR%docker-compose.database.yml"
|
||||
set "ENV_FILE=%SCRIPT_DIR%.env.database"
|
||||
|
||||
REM 检查环境文件
|
||||
:check_env_file
|
||||
if not exist "%ENV_FILE%" (
|
||||
echo [WARNING] 环境文件不存在: %ENV_FILE%
|
||||
echo [INFO] 从模板创建环境文件...
|
||||
copy "%ENV_FILE%.template" "%ENV_FILE%" >nul
|
||||
echo [SUCCESS] 环境文件已创建,请根据需要修改配置
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM 创建必要的目录
|
||||
:create_directories
|
||||
set "DATA_DIR=%SCRIPT_DIR%data"
|
||||
set "MYSQL_DIR=%DATA_DIR%\mysql"
|
||||
set "LOGS_DIR=%DATA_DIR%\logs\mysql"
|
||||
|
||||
echo [INFO] 创建数据目录...
|
||||
if not exist "%MYSQL_DIR%" mkdir "%MYSQL_DIR%"
|
||||
if not exist "%LOGS_DIR%" mkdir "%LOGS_DIR%"
|
||||
echo [SUCCESS] 数据目录创建完成
|
||||
goto :eof
|
||||
|
||||
REM 启动数据库
|
||||
:start_database
|
||||
echo [INFO] 启动MySQL数据库容器...
|
||||
|
||||
call :check_env_file
|
||||
call :create_directories
|
||||
|
||||
REM 使用docker-compose启动
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" up -d
|
||||
|
||||
echo [SUCCESS] 数据库容器启动完成
|
||||
echo [INFO] 等待数据库初始化...
|
||||
|
||||
REM 等待健康检查通过
|
||||
set /a max_attempts=30
|
||||
set /a attempt=1
|
||||
|
||||
:wait_loop
|
||||
if !attempt! gtr !max_attempts! (
|
||||
echo [ERROR] 数据库启动超时
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" ps | findstr "healthy" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo [SUCCESS] 数据库已就绪
|
||||
goto :eof
|
||||
)
|
||||
|
||||
echo [INFO] 等待数据库启动... (!attempt!/!max_attempts!)
|
||||
timeout /t 10 /nobreak >nul
|
||||
set /a attempt+=1
|
||||
goto wait_loop
|
||||
|
||||
REM 停止数据库
|
||||
:stop_database
|
||||
echo [INFO] 停止MySQL数据库容器...
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" down
|
||||
echo [SUCCESS] 数据库容器已停止
|
||||
goto :eof
|
||||
|
||||
REM 重启数据库
|
||||
:restart_database
|
||||
echo [INFO] 重启MySQL数据库容器...
|
||||
call :stop_database
|
||||
call :start_database
|
||||
goto :eof
|
||||
|
||||
REM 查看数据库状态
|
||||
:status_database
|
||||
echo [INFO] 数据库容器状态:
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" ps
|
||||
goto :eof
|
||||
|
||||
REM 查看数据库日志
|
||||
:logs_database
|
||||
set "lines=%~1"
|
||||
if "%lines%"=="" set "lines=100"
|
||||
echo [INFO] 显示数据库日志 (最近 %lines% 行):
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" logs --tail=%lines% -f
|
||||
goto :eof
|
||||
|
||||
REM 进入数据库容器
|
||||
:exec_database
|
||||
echo [INFO] 进入数据库容器...
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" exec anxin-mysql bash
|
||||
goto :eof
|
||||
|
||||
REM 连接到MySQL
|
||||
:connect_mysql
|
||||
echo [INFO] 连接到MySQL数据库...
|
||||
REM 读取环境变量(简化版本,实际使用时需要解析.env文件)
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" exec anxin-mysql mysql -uanxin -panxin123 anxin
|
||||
goto :eof
|
||||
|
||||
REM 备份数据库
|
||||
:backup_database
|
||||
set "backup_file=%SCRIPT_DIR%backup\anxin_%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%.sql"
|
||||
set "backup_dir=%SCRIPT_DIR%backup"
|
||||
|
||||
echo [INFO] 备份数据库到: %backup_file%
|
||||
|
||||
REM 创建备份目录
|
||||
if not exist "%backup_dir%" mkdir "%backup_dir%"
|
||||
|
||||
REM 执行备份
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" exec -T anxin-mysql mysqldump -uanxin -panxin123 --single-transaction --routines --triggers anxin > "%backup_file%"
|
||||
|
||||
echo [SUCCESS] 数据库备份完成: %backup_file%
|
||||
goto :eof
|
||||
|
||||
REM 恢复数据库
|
||||
:restore_database
|
||||
set "backup_file=%~1"
|
||||
|
||||
if "%backup_file%"=="" (
|
||||
echo [ERROR] 请指定有效的备份文件
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "%backup_file%" (
|
||||
echo [ERROR] 备份文件不存在: %backup_file%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [INFO] 从备份文件恢复数据库: %backup_file%
|
||||
|
||||
REM 执行恢复
|
||||
docker-compose -f "%COMPOSE_FILE%" --env-file "%ENV_FILE%" exec -T anxin-mysql mysql -uanxin -panxin123 anxin < "%backup_file%"
|
||||
|
||||
echo [SUCCESS] 数据库恢复完成
|
||||
goto :eof
|
||||
|
||||
REM 显示帮助信息
|
||||
:show_help
|
||||
echo 数据库管理脚本 (Windows版本)
|
||||
echo.
|
||||
echo 用法: %~nx0 [命令] [参数]
|
||||
echo.
|
||||
echo 命令:
|
||||
echo start 启动数据库容器
|
||||
echo stop 停止数据库容器
|
||||
echo restart 重启数据库容器
|
||||
echo status 查看数据库容器状态
|
||||
echo logs [lines] 查看数据库日志 (默认100行)
|
||||
echo exec 进入数据库容器
|
||||
echo connect 连接到MySQL数据库
|
||||
echo backup 备份数据库
|
||||
echo restore ^<file^> 从备份文件恢复数据库
|
||||
echo help 显示此帮助信息
|
||||
echo.
|
||||
echo 示例:
|
||||
echo %~nx0 start # 启动数据库
|
||||
echo %~nx0 logs 50 # 查看最近50行日志
|
||||
echo %~nx0 restore backup.sql # 从backup.sql恢复数据库
|
||||
goto :eof
|
||||
|
||||
REM 主函数
|
||||
:main
|
||||
set "command=%~1"
|
||||
if "%command%"=="" set "command=help"
|
||||
|
||||
if "%command%"=="start" (
|
||||
call :start_database
|
||||
) else if "%command%"=="stop" (
|
||||
call :stop_database
|
||||
) else if "%command%"=="restart" (
|
||||
call :restart_database
|
||||
) else if "%command%"=="status" (
|
||||
call :status_database
|
||||
) else if "%command%"=="logs" (
|
||||
call :logs_database "%~2"
|
||||
) else if "%command%"=="exec" (
|
||||
call :exec_database
|
||||
) else if "%command%"=="connect" (
|
||||
call :connect_mysql
|
||||
) else if "%command%"=="backup" (
|
||||
call :backup_database
|
||||
) else if "%command%"=="restore" (
|
||||
call :restore_database "%~2"
|
||||
) else if "%command%"=="help" (
|
||||
call :show_help
|
||||
) else if "%command%"=="--help" (
|
||||
call :show_help
|
||||
) else if "%command%"=="-h" (
|
||||
call :show_help
|
||||
) else (
|
||||
echo [ERROR] 未知命令: %command%
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
goto :eof
|
||||
|
||||
REM 执行主函数
|
||||
call :main %*
|
||||
249
docker/database/database-manager.sh
Normal file
249
docker/database/database-manager.sh
Normal file
@ -0,0 +1,249 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 数据库管理脚本
|
||||
# 用于管理MySQL数据库容器的启动、停止、备份等操作
|
||||
|
||||
set -e
|
||||
|
||||
# 脚本配置
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
COMPOSE_FILE="$SCRIPT_DIR/docker-compose.database.yml"
|
||||
ENV_FILE="$SCRIPT_DIR/.env.database"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查环境文件
|
||||
check_env_file() {
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_warning "环境文件不存在: $ENV_FILE"
|
||||
log_info "从模板创建环境文件..."
|
||||
cp "$ENV_FILE.template" "$ENV_FILE"
|
||||
log_success "环境文件已创建,请根据需要修改配置"
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建必要的目录
|
||||
create_directories() {
|
||||
local data_dir="$SCRIPT_DIR/data"
|
||||
local mysql_dir="$data_dir/mysql"
|
||||
local logs_dir="$data_dir/logs/mysql"
|
||||
|
||||
log_info "创建数据目录..."
|
||||
mkdir -p "$mysql_dir" "$logs_dir"
|
||||
|
||||
# 设置权限(MySQL需要特定的权限)
|
||||
chmod 755 "$mysql_dir" "$logs_dir"
|
||||
|
||||
log_success "数据目录创建完成"
|
||||
}
|
||||
|
||||
# 启动数据库
|
||||
start_database() {
|
||||
log_info "启动MySQL数据库容器..."
|
||||
|
||||
check_env_file
|
||||
create_directories
|
||||
|
||||
# 使用docker-compose启动
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d
|
||||
|
||||
log_success "数据库容器启动完成"
|
||||
log_info "等待数据库初始化..."
|
||||
|
||||
# 等待健康检查通过
|
||||
local max_attempts=30
|
||||
local attempt=1
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps | grep -q "healthy"; then
|
||||
log_success "数据库已就绪"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "等待数据库启动... ($attempt/$max_attempts)"
|
||||
sleep 10
|
||||
((attempt++))
|
||||
done
|
||||
|
||||
log_error "数据库启动超时"
|
||||
return 1
|
||||
}
|
||||
|
||||
# 停止数据库
|
||||
stop_database() {
|
||||
log_info "停止MySQL数据库容器..."
|
||||
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down
|
||||
|
||||
log_success "数据库容器已停止"
|
||||
}
|
||||
|
||||
# 重启数据库
|
||||
restart_database() {
|
||||
log_info "重启MySQL数据库容器..."
|
||||
|
||||
stop_database
|
||||
start_database
|
||||
}
|
||||
|
||||
# 查看数据库状态
|
||||
status_database() {
|
||||
log_info "数据库容器状态:"
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps
|
||||
}
|
||||
|
||||
# 查看数据库日志
|
||||
logs_database() {
|
||||
local lines=${1:-100}
|
||||
log_info "显示数据库日志 (最近 $lines 行):"
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs --tail="$lines" -f
|
||||
}
|
||||
|
||||
# 进入数据库容器
|
||||
exec_database() {
|
||||
log_info "进入数据库容器..."
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec anxin-mysql bash
|
||||
}
|
||||
|
||||
# 连接到MySQL
|
||||
connect_mysql() {
|
||||
log_info "连接到MySQL数据库..."
|
||||
|
||||
# 从环境文件读取配置
|
||||
source "$ENV_FILE"
|
||||
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec anxin-mysql \
|
||||
mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME"
|
||||
}
|
||||
|
||||
# 备份数据库
|
||||
backup_database() {
|
||||
local backup_file="$SCRIPT_DIR/backup/anxin_$(date +%Y%m%d_%H%M%S).sql"
|
||||
local backup_dir="$(dirname "$backup_file")"
|
||||
|
||||
log_info "备份数据库到: $backup_file"
|
||||
|
||||
# 创建备份目录
|
||||
mkdir -p "$backup_dir"
|
||||
|
||||
# 从环境文件读取配置
|
||||
source "$ENV_FILE"
|
||||
|
||||
# 执行备份
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T anxin-mysql \
|
||||
mysqldump -u"$DB_USER" -p"$DB_PASSWORD" --single-transaction --routines --triggers "$DB_NAME" > "$backup_file"
|
||||
|
||||
log_success "数据库备份完成: $backup_file"
|
||||
}
|
||||
|
||||
# 恢复数据库
|
||||
restore_database() {
|
||||
local backup_file="$1"
|
||||
|
||||
if [ -z "$backup_file" ] || [ ! -f "$backup_file" ]; then
|
||||
log_error "请指定有效的备份文件"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "从备份文件恢复数据库: $backup_file"
|
||||
|
||||
# 从环境文件读取配置
|
||||
source "$ENV_FILE"
|
||||
|
||||
# 执行恢复
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T anxin-mysql \
|
||||
mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < "$backup_file"
|
||||
|
||||
log_success "数据库恢复完成"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
echo "数据库管理脚本"
|
||||
echo ""
|
||||
echo "用法: $0 [命令] [参数]"
|
||||
echo ""
|
||||
echo "命令:"
|
||||
echo " start 启动数据库容器"
|
||||
echo " stop 停止数据库容器"
|
||||
echo " restart 重启数据库容器"
|
||||
echo " status 查看数据库容器状态"
|
||||
echo " logs [lines] 查看数据库日志 (默认100行)"
|
||||
echo " exec 进入数据库容器"
|
||||
echo " connect 连接到MySQL数据库"
|
||||
echo " backup 备份数据库"
|
||||
echo " restore <file> 从备份文件恢复数据库"
|
||||
echo " help 显示此帮助信息"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 start # 启动数据库"
|
||||
echo " $0 logs 50 # 查看最近50行日志"
|
||||
echo " $0 restore backup.sql # 从backup.sql恢复数据库"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
case "${1:-help}" in
|
||||
start)
|
||||
start_database
|
||||
;;
|
||||
stop)
|
||||
stop_database
|
||||
;;
|
||||
restart)
|
||||
restart_database
|
||||
;;
|
||||
status)
|
||||
status_database
|
||||
;;
|
||||
logs)
|
||||
logs_database "$2"
|
||||
;;
|
||||
exec)
|
||||
exec_database
|
||||
;;
|
||||
connect)
|
||||
connect_mysql
|
||||
;;
|
||||
backup)
|
||||
backup_database
|
||||
;;
|
||||
restore)
|
||||
restore_database "$2"
|
||||
;;
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
log_error "未知命令: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
123
docker/database/docker-compose.database.yml
Normal file
123
docker/database/docker-compose.database.yml
Normal file
@ -0,0 +1,123 @@
|
||||
# 数据库服务独立配置文件
|
||||
# 可用于单独启动和管理数据库服务
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# MySQL数据库服务
|
||||
anxin-mysql:
|
||||
image: mysql:8.0
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-anxin}-mysql
|
||||
restart: unless-stopped
|
||||
|
||||
# 环境变量配置
|
||||
environment:
|
||||
# 必需的环境变量
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123}
|
||||
MYSQL_DATABASE: ${DB_NAME:-anxin}
|
||||
MYSQL_USER: ${DB_USER:-anxin}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD:-anxin123}
|
||||
|
||||
# 可选的环境变量
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: ${MYSQL_ALLOW_EMPTY_PASSWORD:-no}
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: ${MYSQL_RANDOM_ROOT_PASSWORD:-no}
|
||||
|
||||
# 系统配置
|
||||
TZ: ${TIMEZONE:-Asia/Shanghai}
|
||||
|
||||
# 端口映射
|
||||
ports:
|
||||
- "${DB_PORT:-3306}:3306"
|
||||
|
||||
# 卷挂载配置
|
||||
volumes:
|
||||
# 数据持久化 - 挂载数据目录
|
||||
- mysql-data:/var/lib/mysql
|
||||
|
||||
# 初始化脚本 - 按字母顺序执行
|
||||
- ./init:/docker-entrypoint-initdb.d:ro
|
||||
|
||||
# MySQL配置文件
|
||||
- ../configs/my.cnf.template:/etc/mysql/conf.d/custom.cnf:ro
|
||||
|
||||
# 日志目录
|
||||
- mysql-logs:/var/log/mysql
|
||||
|
||||
# 临时文件目录
|
||||
- mysql-tmp:/tmp
|
||||
|
||||
# 网络配置
|
||||
networks:
|
||||
- anxin-network
|
||||
|
||||
# 资源限制
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${DATABASE_MEMORY_LIMIT:-512M}
|
||||
cpus: '${DATABASE_CPU_LIMIT:-0.5}'
|
||||
reservations:
|
||||
memory: ${DATABASE_MEMORY_RESERVATION:-256M}
|
||||
cpus: '${DATABASE_CPU_RESERVATION:-0.25}'
|
||||
|
||||
# 健康检查
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-root123}"]
|
||||
interval: 30s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
start_period: 60s
|
||||
|
||||
# 安全配置
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
# 用户配置(可选,用于安全加固)
|
||||
# user: "999:999"
|
||||
|
||||
# 命令覆盖(可选,用于自定义启动参数)
|
||||
command: >
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_unicode_ci
|
||||
--default-time-zone='+08:00'
|
||||
--max-connections=200
|
||||
--innodb-buffer-pool-size=128M
|
||||
--innodb-log-file-size=32M
|
||||
--innodb-flush-log-at-trx-commit=1
|
||||
--slow-query-log=1
|
||||
--slow-query-log-file=/var/log/mysql/slow.log
|
||||
--long-query-time=3
|
||||
--log-error=/var/log/mysql/error.log
|
||||
|
||||
# 网络配置
|
||||
networks:
|
||||
anxin-network:
|
||||
name: ${NETWORK_NAME:-anxin-network}
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: ${SUBNET:-172.20.0.0/16}
|
||||
gateway: ${GATEWAY:-172.20.0.1}
|
||||
|
||||
# 卷配置
|
||||
volumes:
|
||||
# 数据库数据卷 - 持久化存储
|
||||
mysql-data:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_DATA_PATH:-./data/mysql}
|
||||
|
||||
# 数据库日志卷
|
||||
mysql-logs:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_LOGS_PATH:-./data/logs/mysql}
|
||||
|
||||
# 临时文件卷
|
||||
mysql-tmp:
|
||||
driver: local
|
||||
33
docker/database/init/00-mysql-config.sql
Normal file
33
docker/database/init/00-mysql-config.sql
Normal file
@ -0,0 +1,33 @@
|
||||
-- MySQL服务器配置脚本
|
||||
-- 在数据库和表创建之前执行的配置
|
||||
|
||||
-- 设置MySQL服务器全局配置
|
||||
-- 字符集配置
|
||||
SET GLOBAL character_set_server = 'utf8mb4';
|
||||
SET GLOBAL collation_server = 'utf8mb4_unicode_ci';
|
||||
|
||||
-- 时区配置
|
||||
SET GLOBAL time_zone = '+8:00';
|
||||
|
||||
-- SQL模式配置(兼容性设置)
|
||||
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO';
|
||||
|
||||
-- 连接和性能配置
|
||||
SET GLOBAL max_connections = 1000;
|
||||
SET GLOBAL max_allowed_packet = 64*1024*1024; -- 64MB
|
||||
SET GLOBAL innodb_buffer_pool_size = 128*1024*1024; -- 128MB
|
||||
|
||||
-- 日志配置
|
||||
SET GLOBAL general_log = 'OFF';
|
||||
SET GLOBAL slow_query_log = 'ON';
|
||||
SET GLOBAL long_query_time = 2;
|
||||
|
||||
-- 二进制日志配置(用于复制和备份)
|
||||
SET GLOBAL binlog_format = 'ROW';
|
||||
SET GLOBAL expire_logs_days = 7;
|
||||
|
||||
-- 事务隔离级别
|
||||
SET GLOBAL transaction_isolation = 'READ-COMMITTED';
|
||||
|
||||
-- 显示配置状态
|
||||
SELECT 'MySQL server configuration completed' as ConfigStatus;
|
||||
61
docker/database/init/01-init-database.sql
Normal file
61
docker/database/init/01-init-database.sql
Normal file
@ -0,0 +1,61 @@
|
||||
-- 数据库初始化脚本
|
||||
-- 创建数据库和用户,配置字符集和时区
|
||||
|
||||
-- 设置字符集和编码
|
||||
SET NAMES utf8mb4;
|
||||
SET character_set_client = utf8mb4;
|
||||
SET character_set_connection = utf8mb4;
|
||||
SET character_set_database = utf8mb4;
|
||||
SET character_set_results = utf8mb4;
|
||||
SET character_set_server = utf8mb4;
|
||||
SET collation_connection = utf8mb4_unicode_ci;
|
||||
SET collation_database = utf8mb4_unicode_ci;
|
||||
SET collation_server = utf8mb4_unicode_ci;
|
||||
|
||||
-- 禁用外键检查以避免初始化时的依赖问题
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- 设置时区为中国标准时间
|
||||
SET time_zone = '+8:00';
|
||||
SET GLOBAL time_zone = '+8:00';
|
||||
|
||||
-- 创建数据库(如果不存在)
|
||||
CREATE DATABASE IF NOT EXISTS `anxin`
|
||||
DEFAULT CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- 使用数据库
|
||||
USE `anxin`;
|
||||
|
||||
-- 创建应用用户(如果不存在)
|
||||
-- 使用环境变量或默认值
|
||||
SET @app_user = IFNULL(@MYSQL_USER, 'anxin');
|
||||
SET @app_password = IFNULL(@MYSQL_PASSWORD, 'anxin123');
|
||||
|
||||
-- 创建用户并设置密码
|
||||
SET @sql = CONCAT('CREATE USER IF NOT EXISTS ''', @app_user, '''@''%'' IDENTIFIED BY ''', @app_password, '''');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 授予数据库权限
|
||||
SET @sql = CONCAT('GRANT ALL PRIVILEGES ON `anxin`.* TO ''', @app_user, '''@''%''');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 授予必要的系统权限(用于应用正常运行)
|
||||
SET @sql = CONCAT('GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON `anxin`.* TO ''', @app_user, '''@''%''');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 刷新权限
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
-- 恢复外键检查
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
-- 显示创建的数据库和用户信息
|
||||
SELECT 'Database anxin created successfully' as Status;
|
||||
SELECT CONCAT('User ', @app_user, ' created and granted permissions') as UserStatus;
|
||||
7994
docker/database/init/02-schema.sql
Normal file
7994
docker/database/init/02-schema.sql
Normal file
File diff suppressed because one or more lines are too long
52
docker/database/init/99-validation.sql
Normal file
52
docker/database/init/99-validation.sql
Normal file
@ -0,0 +1,52 @@
|
||||
-- 数据库初始化验证脚本
|
||||
-- 在所有初始化脚本执行完成后运行
|
||||
|
||||
USE `anxin`;
|
||||
|
||||
-- 验证数据库字符集
|
||||
SELECT
|
||||
SCHEMA_NAME as 'Database',
|
||||
DEFAULT_CHARACTER_SET_NAME as 'Character Set',
|
||||
DEFAULT_COLLATION_NAME as 'Collation'
|
||||
FROM information_schema.SCHEMATA
|
||||
WHERE SCHEMA_NAME = 'anxin';
|
||||
|
||||
-- 验证时区设置
|
||||
SELECT @@global.time_zone as 'Global Timezone', @@session.time_zone as 'Session Timezone';
|
||||
|
||||
-- 验证用户权限
|
||||
SELECT
|
||||
User as 'Username',
|
||||
Host as 'Host',
|
||||
Select_priv as 'SELECT',
|
||||
Insert_priv as 'INSERT',
|
||||
Update_priv as 'UPDATE',
|
||||
Delete_priv as 'DELETE'
|
||||
FROM mysql.user
|
||||
WHERE User IN ('anxin', 'root');
|
||||
|
||||
-- 验证数据库表数量
|
||||
SELECT COUNT(*) as 'Total Tables' FROM information_schema.tables WHERE table_schema = 'anxin';
|
||||
|
||||
-- 验证关键表是否存在
|
||||
SELECT
|
||||
TABLE_NAME as 'Table Name',
|
||||
TABLE_ROWS as 'Row Count',
|
||||
CREATE_TIME as 'Created Time'
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'anxin'
|
||||
AND TABLE_NAME IN (
|
||||
'sys_user', 'sys_role', 'sys_menu', 'sys_dept',
|
||||
'dc_service_contract', 'dc_employee', 'dc_financing_application'
|
||||
)
|
||||
ORDER BY TABLE_NAME;
|
||||
|
||||
-- 验证字符集配置
|
||||
SHOW VARIABLES LIKE 'character_set%';
|
||||
SHOW VARIABLES LIKE 'collation%';
|
||||
|
||||
-- 显示初始化完成状态
|
||||
SELECT
|
||||
'Database initialization completed successfully' as Status,
|
||||
NOW() as CompletionTime,
|
||||
@@version as MySQLVersion;
|
||||
892
docker/deploy.sh
Normal file
892
docker/deploy.sh
Normal file
@ -0,0 +1,892 @@
|
||||
#!/bin/bash
|
||||
# 部署脚本 - 若依框架Docker部署方案
|
||||
# 实现服务启动和停止功能、服务健康检查、日志查看功能
|
||||
# Requirements: 5.4, 5.5
|
||||
|
||||
set -e
|
||||
|
||||
# ===========================================
|
||||
# 脚本配置
|
||||
# ===========================================
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
DOCKER_DIR="$SCRIPT_DIR"
|
||||
|
||||
# 默认配置
|
||||
DEFAULT_ENVIRONMENT="development"
|
||||
DEFAULT_ACTION="status"
|
||||
FOLLOW_LOGS=false
|
||||
VERBOSE=false
|
||||
FORCE_RECREATE=false
|
||||
TIMEOUT=300
|
||||
|
||||
# 服务配置
|
||||
SERVICES=("anxin-mysql" "anxin-backend" "anxin-frontend")
|
||||
ALL_SERVICES="all"
|
||||
|
||||
# ===========================================
|
||||
# 颜色定义
|
||||
# ===========================================
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ===========================================
|
||||
# 日志函数
|
||||
# ===========================================
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
log_debug() {
|
||||
if [[ "$VERBOSE" == "true" ]]; then
|
||||
echo -e "${PURPLE}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
fi
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${CYAN}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 帮助信息
|
||||
# ===========================================
|
||||
show_help() {
|
||||
cat << EOF
|
||||
若依框架Docker部署 - 部署管理脚本
|
||||
|
||||
用法: $0 [选项] [动作] [服务]
|
||||
|
||||
动作:
|
||||
start 启动服务 (默认: 所有服务)
|
||||
stop 停止服务 (默认: 所有服务)
|
||||
restart 重启服务 (默认: 所有服务)
|
||||
status 查看服务状态 (默认动作)
|
||||
health 执行健康检查
|
||||
logs 查看服务日志
|
||||
ps 查看运行中的容器
|
||||
down 停止并删除所有容器、网络和卷
|
||||
up 启动所有服务 (等同于start all)
|
||||
|
||||
服务:
|
||||
all 所有服务 (默认)
|
||||
mysql 数据库服务
|
||||
backend 后端服务
|
||||
frontend 前端服务
|
||||
anxin-mysql 数据库服务 (完整名称)
|
||||
anxin-backend 后端服务 (完整名称)
|
||||
anxin-frontend 前端服务 (完整名称)
|
||||
|
||||
选项:
|
||||
-e, --env ENV 指定环境 (development|staging|production) [默认: development]
|
||||
-f, --follow 跟踪日志输出 (仅用于logs动作)
|
||||
-t, --timeout SECONDS 设置操作超时时间 [默认: 300秒]
|
||||
--force 强制重新创建容器
|
||||
--verbose 显示详细日志
|
||||
-h, --help 显示此帮助信息
|
||||
|
||||
健康检查选项:
|
||||
--wait 等待所有服务健康后退出
|
||||
--retry COUNT 健康检查重试次数 [默认: 10]
|
||||
--interval SECONDS 健康检查间隔 [默认: 30秒]
|
||||
|
||||
日志选项:
|
||||
--tail LINES 显示最后N行日志 [默认: 100]
|
||||
--since TIME 显示指定时间后的日志 (如: 2h, 30m)
|
||||
|
||||
示例:
|
||||
$0 # 查看服务状态 (开发环境)
|
||||
$0 start # 启动所有服务
|
||||
$0 start mysql # 仅启动数据库服务
|
||||
$0 stop backend frontend # 停止后端和前端服务
|
||||
$0 restart -e production # 重启生产环境所有服务
|
||||
$0 health --wait # 等待所有服务健康
|
||||
$0 logs backend -f # 跟踪后端服务日志
|
||||
$0 logs --tail 50 --since 1h # 查看最近1小时的50行日志
|
||||
$0 status -e staging # 查看测试环境状态
|
||||
|
||||
Requirements Coverage:
|
||||
5.4 - 日志输出用于问题排查
|
||||
5.5 - 验证服务可用性 (健康检查)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 参数解析
|
||||
# ===========================================
|
||||
parse_args() {
|
||||
SERVICES_TO_MANAGE=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
start|stop|restart|status|health|logs|ps|down|up)
|
||||
ACTION="$1"
|
||||
shift
|
||||
;;
|
||||
-e|--env)
|
||||
ENVIRONMENT="$2"
|
||||
shift 2
|
||||
;;
|
||||
-f|--follow)
|
||||
FOLLOW_LOGS=true
|
||||
shift
|
||||
;;
|
||||
-t|--timeout)
|
||||
TIMEOUT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--force)
|
||||
FORCE_RECREATE=true
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
--wait)
|
||||
WAIT_FOR_HEALTH=true
|
||||
shift
|
||||
;;
|
||||
--retry)
|
||||
HEALTH_RETRY_COUNT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--interval)
|
||||
HEALTH_CHECK_INTERVAL="$2"
|
||||
shift 2
|
||||
;;
|
||||
--tail)
|
||||
LOG_TAIL_LINES="$2"
|
||||
shift 2
|
||||
;;
|
||||
--since)
|
||||
LOG_SINCE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
all|mysql|backend|frontend|anxin-mysql|anxin-backend|anxin-frontend)
|
||||
# 标准化服务名称
|
||||
case $1 in
|
||||
mysql) SERVICES_TO_MANAGE+=("anxin-mysql") ;;
|
||||
backend) SERVICES_TO_MANAGE+=("anxin-backend") ;;
|
||||
frontend) SERVICES_TO_MANAGE+=("anxin-frontend") ;;
|
||||
all) SERVICES_TO_MANAGE=("${SERVICES[@]}") ;;
|
||||
*) SERVICES_TO_MANAGE+=("$1") ;;
|
||||
esac
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
log_error "未知参数: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 设置默认值
|
||||
ACTION=${ACTION:-$DEFAULT_ACTION}
|
||||
ENVIRONMENT=${ENVIRONMENT:-$DEFAULT_ENVIRONMENT}
|
||||
HEALTH_RETRY_COUNT=${HEALTH_RETRY_COUNT:-10}
|
||||
HEALTH_CHECK_INTERVAL=${HEALTH_CHECK_INTERVAL:-30}
|
||||
LOG_TAIL_LINES=${LOG_TAIL_LINES:-100}
|
||||
|
||||
# 如果没有指定服务,默认为所有服务
|
||||
if [[ ${#SERVICES_TO_MANAGE[@]} -eq 0 ]]; then
|
||||
SERVICES_TO_MANAGE=("${SERVICES[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 环境验证和配置
|
||||
# ===========================================
|
||||
validate_environment() {
|
||||
case $ENVIRONMENT in
|
||||
development|dev)
|
||||
ENVIRONMENT="development"
|
||||
;;
|
||||
staging|stage)
|
||||
ENVIRONMENT="staging"
|
||||
;;
|
||||
production|prod)
|
||||
ENVIRONMENT="production"
|
||||
;;
|
||||
*)
|
||||
log_error "无效的环境: $ENVIRONMENT"
|
||||
log_info "支持的环境: development, staging, production"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_debug "环境验证通过: $ENVIRONMENT"
|
||||
}
|
||||
|
||||
# 加载环境配置
|
||||
load_environment_config() {
|
||||
local env_file="${DOCKER_DIR}/environments/.env.${ENVIRONMENT}"
|
||||
|
||||
if [[ ! -f "$env_file" ]]; then
|
||||
log_error "环境配置文件不存在: $env_file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_debug "加载环境配置: $ENVIRONMENT"
|
||||
source "$env_file"
|
||||
|
||||
# 设置Docker Compose文件路径
|
||||
COMPOSE_FILE="${DOCKER_DIR}/docker-compose.${ENVIRONMENT}.yml"
|
||||
ENV_FILE="$env_file"
|
||||
|
||||
if [[ ! -f "$COMPOSE_FILE" ]]; then
|
||||
log_error "Docker Compose文件不存在: $COMPOSE_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 导出关键环境变量
|
||||
export ENVIRONMENT
|
||||
export COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-"anxin-${ENVIRONMENT}"}
|
||||
|
||||
log_debug "环境配置加载完成"
|
||||
log_debug "Compose文件: $COMPOSE_FILE"
|
||||
log_debug "环境文件: $ENV_FILE"
|
||||
log_debug "项目名称: $COMPOSE_PROJECT_NAME"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 系统检查
|
||||
# ===========================================
|
||||
check_prerequisites() {
|
||||
log_debug "检查系统依赖..."
|
||||
|
||||
# 检查Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Docker Compose
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查Docker守护进程
|
||||
if ! docker info &> /dev/null; then
|
||||
log_error "Docker守护进程未运行"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_debug "系统依赖检查通过"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# Docker Compose操作封装
|
||||
# ===========================================
|
||||
compose_cmd() {
|
||||
local cmd="$1"
|
||||
shift
|
||||
|
||||
cd "$DOCKER_DIR"
|
||||
log_debug "执行: docker-compose -f $COMPOSE_FILE --env-file $ENV_FILE $cmd $*"
|
||||
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" "$cmd" "$@"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 服务启动功能 (Requirement 5.5)
|
||||
# ===========================================
|
||||
start_services() {
|
||||
local services_list=("$@")
|
||||
|
||||
if [[ ${#services_list[@]} -eq 0 ]] || [[ "${services_list[*]}" == "${SERVICES[*]}" ]]; then
|
||||
log_step "启动所有服务..."
|
||||
services_list=() # 空数组表示所有服务
|
||||
else
|
||||
log_step "启动指定服务: ${services_list[*]}"
|
||||
fi
|
||||
|
||||
# 创建必要的数据目录
|
||||
create_data_directories
|
||||
|
||||
# 构建启动命令
|
||||
local compose_args=("up" "-d")
|
||||
|
||||
if [[ "$FORCE_RECREATE" == "true" ]]; then
|
||||
compose_args+=("--force-recreate")
|
||||
fi
|
||||
|
||||
# 添加服务列表
|
||||
if [[ ${#services_list[@]} -gt 0 ]]; then
|
||||
compose_args+=("${services_list[@]}")
|
||||
fi
|
||||
|
||||
# 执行启动命令
|
||||
log_info "正在启动服务..."
|
||||
if compose_cmd "${compose_args[@]}"; then
|
||||
log_success "服务启动命令执行成功"
|
||||
|
||||
# 等待服务启动
|
||||
log_info "等待服务启动完成..."
|
||||
sleep 10
|
||||
|
||||
# 检查服务状态
|
||||
check_services_status "${services_list[@]}"
|
||||
|
||||
# 显示访问信息
|
||||
show_access_info
|
||||
|
||||
else
|
||||
log_error "服务启动失败"
|
||||
log_info "查看详细错误信息:"
|
||||
compose_cmd logs --tail 50
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 创建数据目录
|
||||
create_data_directories() {
|
||||
log_debug "创建必要的数据目录..."
|
||||
|
||||
local data_dirs=(
|
||||
"${DOCKER_DIR}/data/${ENVIRONMENT}/mysql"
|
||||
"${DOCKER_DIR}/data/${ENVIRONMENT}/mysql-logs"
|
||||
"${DOCKER_DIR}/data/${ENVIRONMENT}/backend-logs"
|
||||
"${DOCKER_DIR}/data/${ENVIRONMENT}/uploads"
|
||||
"${DOCKER_DIR}/data/${ENVIRONMENT}/nginx-logs"
|
||||
)
|
||||
|
||||
for dir in "${data_dirs[@]}"; do
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
log_debug "创建目录: $dir"
|
||||
mkdir -p "$dir"
|
||||
fi
|
||||
done
|
||||
|
||||
# 设置目录权限
|
||||
chmod -R 755 "${DOCKER_DIR}/data/${ENVIRONMENT}"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 服务停止功能
|
||||
# ===========================================
|
||||
stop_services() {
|
||||
local services_list=("$@")
|
||||
|
||||
if [[ ${#services_list[@]} -eq 0 ]] || [[ "${services_list[*]}" == "${SERVICES[*]}" ]]; then
|
||||
log_step "停止所有服务..."
|
||||
services_list=() # 空数组表示所有服务
|
||||
else
|
||||
log_step "停止指定服务: ${services_list[*]}"
|
||||
fi
|
||||
|
||||
# 构建停止命令
|
||||
local compose_args=("stop")
|
||||
|
||||
# 添加超时参数
|
||||
compose_args+=("-t" "$TIMEOUT")
|
||||
|
||||
# 添加服务列表
|
||||
if [[ ${#services_list[@]} -gt 0 ]]; then
|
||||
compose_args+=("${services_list[@]}")
|
||||
fi
|
||||
|
||||
# 执行停止命令
|
||||
log_info "正在停止服务..."
|
||||
if compose_cmd "${compose_args[@]}"; then
|
||||
log_success "服务停止成功"
|
||||
|
||||
# 显示当前状态
|
||||
show_services_status
|
||||
|
||||
else
|
||||
log_error "服务停止失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 服务重启功能
|
||||
# ===========================================
|
||||
restart_services() {
|
||||
local services_list=("$@")
|
||||
|
||||
log_step "重启服务: ${services_list[*]:-所有服务}"
|
||||
|
||||
# 先停止服务
|
||||
if stop_services "${services_list[@]}"; then
|
||||
# 等待一段时间确保服务完全停止
|
||||
log_info "等待服务完全停止..."
|
||||
sleep 5
|
||||
|
||||
# 再启动服务
|
||||
start_services "${services_list[@]}"
|
||||
else
|
||||
log_error "重启失败: 服务停止阶段出错"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 服务健康检查功能 (Requirement 5.5)
|
||||
# ===========================================
|
||||
check_services_health() {
|
||||
local services_list=("$@")
|
||||
local wait_for_health=${WAIT_FOR_HEALTH:-false}
|
||||
|
||||
if [[ ${#services_list[@]} -eq 0 ]]; then
|
||||
services_list=("${SERVICES[@]}")
|
||||
fi
|
||||
|
||||
log_step "执行服务健康检查..."
|
||||
|
||||
local healthy_services=()
|
||||
local unhealthy_services=()
|
||||
local retry_count=0
|
||||
local max_retries=$HEALTH_RETRY_COUNT
|
||||
|
||||
while [[ $retry_count -lt $max_retries ]]; do
|
||||
healthy_services=()
|
||||
unhealthy_services=()
|
||||
|
||||
log_info "健康检查 (第 $((retry_count + 1))/$max_retries 次)..."
|
||||
|
||||
for service in "${services_list[@]}"; do
|
||||
local container_name="${service}-${ENVIRONMENT}"
|
||||
local health_status=$(get_service_health_status "$service")
|
||||
|
||||
case $health_status in
|
||||
"healthy")
|
||||
log_success "✓ $service: 健康"
|
||||
healthy_services+=("$service")
|
||||
;;
|
||||
"starting")
|
||||
log_warn "⚠ $service: 启动中..."
|
||||
unhealthy_services+=("$service")
|
||||
;;
|
||||
"unhealthy")
|
||||
log_error "✗ $service: 不健康"
|
||||
unhealthy_services+=("$service")
|
||||
;;
|
||||
"no-healthcheck")
|
||||
# 对于没有健康检查的服务,检查容器是否运行
|
||||
if is_service_running "$service"; then
|
||||
log_success "✓ $service: 运行中 (无健康检查)"
|
||||
healthy_services+=("$service")
|
||||
else
|
||||
log_error "✗ $service: 未运行"
|
||||
unhealthy_services+=("$service")
|
||||
fi
|
||||
;;
|
||||
"not-found")
|
||||
log_error "✗ $service: 容器未找到"
|
||||
unhealthy_services+=("$service")
|
||||
;;
|
||||
*)
|
||||
log_error "✗ $service: 状态未知 ($health_status)"
|
||||
unhealthy_services+=("$service")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 如果所有服务都健康,或者不需要等待,则退出循环
|
||||
if [[ ${#unhealthy_services[@]} -eq 0 ]] || [[ "$wait_for_health" != "true" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
# 等待下次检查
|
||||
if [[ $retry_count -lt $((max_retries - 1)) ]]; then
|
||||
log_info "等待 ${HEALTH_CHECK_INTERVAL} 秒后重试..."
|
||||
sleep "$HEALTH_CHECK_INTERVAL"
|
||||
fi
|
||||
|
||||
((retry_count++))
|
||||
done
|
||||
|
||||
# 显示最终结果
|
||||
echo "========================================"
|
||||
log_info "健康检查结果:"
|
||||
log_success "健康服务 (${#healthy_services[@]}): ${healthy_services[*]:-无}"
|
||||
|
||||
if [[ ${#unhealthy_services[@]} -gt 0 ]]; then
|
||||
log_error "不健康服务 (${#unhealthy_services[@]}): ${unhealthy_services[*]}"
|
||||
|
||||
# 显示不健康服务的详细信息
|
||||
for service in "${unhealthy_services[@]}"; do
|
||||
show_service_details "$service"
|
||||
done
|
||||
|
||||
return 1
|
||||
else
|
||||
log_success "所有服务健康检查通过!"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# 获取服务健康状态
|
||||
get_service_health_status() {
|
||||
local service="$1"
|
||||
local container_name="${service}-${ENVIRONMENT}"
|
||||
|
||||
# 检查容器是否存在
|
||||
if ! docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
|
||||
echo "not-found"
|
||||
return
|
||||
fi
|
||||
|
||||
# 检查容器是否运行
|
||||
if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
|
||||
echo "stopped"
|
||||
return
|
||||
fi
|
||||
|
||||
# 获取健康检查状态
|
||||
local health_status=$(docker inspect --format='{{.State.Health.Status}}' "$container_name" 2>/dev/null || echo "no-healthcheck")
|
||||
echo "$health_status"
|
||||
}
|
||||
|
||||
# 检查服务是否运行
|
||||
is_service_running() {
|
||||
local service="$1"
|
||||
local container_name="${service}-${ENVIRONMENT}"
|
||||
|
||||
docker ps --format "{{.Names}}" | grep -q "^${container_name}$"
|
||||
}
|
||||
|
||||
# 显示服务详细信息
|
||||
show_service_details() {
|
||||
local service="$1"
|
||||
local container_name="${service}-${ENVIRONMENT}"
|
||||
|
||||
log_info "服务详细信息: $service"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# 容器状态
|
||||
local container_status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null || echo "not-found")
|
||||
echo "容器状态: $container_status"
|
||||
|
||||
# 如果容器存在,显示更多信息
|
||||
if [[ "$container_status" != "not-found" ]]; then
|
||||
# 启动时间
|
||||
local started_at=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)
|
||||
echo "启动时间: $started_at"
|
||||
|
||||
# 重启次数
|
||||
local restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
|
||||
echo "重启次数: $restart_count"
|
||||
|
||||
# 最近日志
|
||||
echo "最近日志:"
|
||||
docker logs --tail 10 "$container_name" 2>&1 | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
echo "----------------------------------------"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 服务状态查看功能
|
||||
# ===========================================
|
||||
show_services_status() {
|
||||
log_step "查看服务状态..."
|
||||
|
||||
# 显示Docker Compose服务状态
|
||||
log_info "Docker Compose服务状态:"
|
||||
compose_cmd ps
|
||||
|
||||
echo ""
|
||||
|
||||
# 显示详细的容器信息
|
||||
log_info "容器详细信息:"
|
||||
echo "----------------------------------------"
|
||||
printf "%-20s %-15s %-15s %-20s %-10s\n" "服务名称" "容器状态" "健康状态" "端口映射" "重启次数"
|
||||
echo "----------------------------------------"
|
||||
|
||||
for service in "${SERVICES[@]}"; do
|
||||
local container_name="${service}-${ENVIRONMENT}"
|
||||
|
||||
# 获取容器信息
|
||||
if docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
|
||||
local status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
|
||||
local health=$(get_service_health_status "$service")
|
||||
local ports=$(docker port "$container_name" 2>/dev/null | tr '\n' ' ' | sed 's/[[:space:]]*$//')
|
||||
local restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
|
||||
|
||||
# 格式化健康状态显示
|
||||
case $health in
|
||||
"healthy") health="✓ 健康" ;;
|
||||
"starting") health="⚠ 启动中" ;;
|
||||
"unhealthy") health="✗ 不健康" ;;
|
||||
"no-healthcheck") health="- 无检查" ;;
|
||||
*) health="? 未知" ;;
|
||||
esac
|
||||
|
||||
printf "%-20s %-15s %-15s %-20s %-10s\n" "$service" "$status" "$health" "${ports:-无}" "$restart_count"
|
||||
else
|
||||
printf "%-20s %-15s %-15s %-20s %-10s\n" "$service" "未创建" "-" "-" "-"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "----------------------------------------"
|
||||
|
||||
# 显示网络信息
|
||||
show_network_info
|
||||
|
||||
# 显示卷信息
|
||||
show_volume_info
|
||||
}
|
||||
|
||||
# 显示网络信息
|
||||
show_network_info() {
|
||||
log_info "网络信息:"
|
||||
local network_name="${COMPOSE_PROJECT_NAME}_default"
|
||||
|
||||
if docker network ls --format "{{.Name}}" | grep -q "^${network_name}$"; then
|
||||
docker network inspect "$network_name" --format "网络名称: {{.Name}}, 驱动: {{.Driver}}, 子网: {{range .IPAM.Config}}{{.Subnet}}{{end}}"
|
||||
else
|
||||
echo "网络未创建: $network_name"
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示卷信息
|
||||
show_volume_info() {
|
||||
log_info "数据卷信息:"
|
||||
echo "----------------------------------------"
|
||||
|
||||
local volumes=(
|
||||
"mysql-data-${ENVIRONMENT}"
|
||||
"mysql-logs-${ENVIRONMENT}"
|
||||
"backend-logs-${ENVIRONMENT}"
|
||||
"backend-uploads-${ENVIRONMENT}"
|
||||
"frontend-logs-${ENVIRONMENT}"
|
||||
)
|
||||
|
||||
for volume in "${volumes[@]}"; do
|
||||
local full_volume_name="${COMPOSE_PROJECT_NAME}_${volume}"
|
||||
if docker volume ls --format "{{.Name}}" | grep -q "^${full_volume_name}$"; then
|
||||
local mount_point=$(docker volume inspect "$full_volume_name" --format "{{.Mountpoint}}" 2>/dev/null)
|
||||
echo "✓ $volume -> $mount_point"
|
||||
else
|
||||
echo "✗ $volume (未创建)"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "----------------------------------------"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 日志查看功能 (Requirement 5.4)
|
||||
# ===========================================
|
||||
show_services_logs() {
|
||||
local services_list=("$@")
|
||||
|
||||
if [[ ${#services_list[@]} -eq 0 ]]; then
|
||||
services_list=("${SERVICES[@]}")
|
||||
fi
|
||||
|
||||
log_step "查看服务日志: ${services_list[*]}"
|
||||
|
||||
# 构建日志命令
|
||||
local compose_args=("logs")
|
||||
|
||||
# 添加日志选项
|
||||
if [[ "$FOLLOW_LOGS" == "true" ]]; then
|
||||
compose_args+=("-f")
|
||||
fi
|
||||
|
||||
if [[ -n "$LOG_TAIL_LINES" ]]; then
|
||||
compose_args+=("--tail" "$LOG_TAIL_LINES")
|
||||
fi
|
||||
|
||||
if [[ -n "$LOG_SINCE" ]]; then
|
||||
compose_args+=("--since" "$LOG_SINCE")
|
||||
fi
|
||||
|
||||
# 添加时间戳
|
||||
compose_args+=("-t")
|
||||
|
||||
# 添加服务列表
|
||||
compose_args+=("${services_list[@]}")
|
||||
|
||||
# 执行日志命令
|
||||
log_info "日志查看选项: tail=${LOG_TAIL_LINES:-all}, since=${LOG_SINCE:-all}, follow=${FOLLOW_LOGS}"
|
||||
|
||||
if [[ "$FOLLOW_LOGS" == "true" ]]; then
|
||||
log_info "开始跟踪日志 (按 Ctrl+C 退出)..."
|
||||
fi
|
||||
|
||||
compose_cmd "${compose_args[@]}"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 完整清理功能
|
||||
# ===========================================
|
||||
down_all_services() {
|
||||
log_step "停止并清理所有服务..."
|
||||
|
||||
log_warn "这将停止所有容器并删除网络,但保留数据卷"
|
||||
read -p "确认继续? (y/N): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "操作已取消"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 执行down命令
|
||||
if compose_cmd down --remove-orphans; then
|
||||
log_success "服务清理完成"
|
||||
|
||||
# 显示清理后的状态
|
||||
log_info "清理后状态:"
|
||||
compose_cmd ps
|
||||
|
||||
else
|
||||
log_error "服务清理失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 显示访问信息
|
||||
# ===========================================
|
||||
show_access_info() {
|
||||
log_info "服务访问信息:"
|
||||
echo "========================================"
|
||||
echo "环境: $ENVIRONMENT"
|
||||
echo "----------------------------------------"
|
||||
echo "前端应用: http://localhost:${FRONTEND_PORT:-80}"
|
||||
echo "后端API: http://localhost:${BACKEND_PORT:-8080}"
|
||||
echo "数据库: localhost:${DB_PORT:-3306}"
|
||||
echo "----------------------------------------"
|
||||
echo "管理命令:"
|
||||
echo " 查看状态: $0 status -e $ENVIRONMENT"
|
||||
echo " 查看日志: $0 logs -e $ENVIRONMENT"
|
||||
echo " 健康检查: $0 health -e $ENVIRONMENT"
|
||||
echo " 停止服务: $0 stop -e $ENVIRONMENT"
|
||||
echo "========================================"
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 检查服务状态 (内部使用)
|
||||
# ===========================================
|
||||
check_services_status() {
|
||||
local services_list=("$@")
|
||||
|
||||
if [[ ${#services_list[@]} -eq 0 ]]; then
|
||||
services_list=("${SERVICES[@]}")
|
||||
fi
|
||||
|
||||
log_info "检查服务启动状态..."
|
||||
|
||||
local running_services=()
|
||||
local failed_services=()
|
||||
|
||||
for service in "${services_list[@]}"; do
|
||||
if is_service_running "$service"; then
|
||||
running_services+=("$service")
|
||||
log_success "✓ $service: 运行中"
|
||||
else
|
||||
failed_services+=("$service")
|
||||
log_error "✗ $service: 未运行"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#failed_services[@]} -gt 0 ]]; then
|
||||
log_warn "部分服务启动失败: ${failed_services[*]}"
|
||||
log_info "建议执行健康检查: $0 health -e $ENVIRONMENT"
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 主函数
|
||||
# ===========================================
|
||||
main() {
|
||||
# 显示脚本信息
|
||||
log_info "若依框架Docker部署 - 部署管理脚本"
|
||||
log_info "脚本版本: 1.0.0"
|
||||
log_info "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
# 解析参数
|
||||
parse_args "$@"
|
||||
|
||||
# 验证环境
|
||||
validate_environment
|
||||
|
||||
# 加载环境配置
|
||||
load_environment_config
|
||||
|
||||
# 检查系统依赖
|
||||
check_prerequisites
|
||||
|
||||
# 显示当前配置
|
||||
log_debug "当前配置:"
|
||||
log_debug " 动作: $ACTION"
|
||||
log_debug " 环境: $ENVIRONMENT"
|
||||
log_debug " 服务: ${SERVICES_TO_MANAGE[*]}"
|
||||
log_debug " 超时: ${TIMEOUT}秒"
|
||||
|
||||
# 根据动作执行相应操作
|
||||
case $ACTION in
|
||||
start|up)
|
||||
start_services "${SERVICES_TO_MANAGE[@]}"
|
||||
;;
|
||||
stop)
|
||||
stop_services "${SERVICES_TO_MANAGE[@]}"
|
||||
;;
|
||||
restart)
|
||||
restart_services "${SERVICES_TO_MANAGE[@]}"
|
||||
;;
|
||||
status|ps)
|
||||
show_services_status
|
||||
;;
|
||||
health)
|
||||
check_services_health "${SERVICES_TO_MANAGE[@]}"
|
||||
;;
|
||||
logs)
|
||||
show_services_logs "${SERVICES_TO_MANAGE[@]}"
|
||||
;;
|
||||
down)
|
||||
down_all_services
|
||||
;;
|
||||
*)
|
||||
log_error "未知动作: $ACTION"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
local exit_code=$?
|
||||
|
||||
if [[ $exit_code -eq 0 ]]; then
|
||||
log_success "操作完成!"
|
||||
else
|
||||
log_error "操作失败 (退出代码: $exit_code)"
|
||||
fi
|
||||
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
# ===========================================
|
||||
# 错误处理
|
||||
# ===========================================
|
||||
trap 'log_error "脚本执行被中断"; exit 1' INT TERM
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
179
docker/docker-compose.development.yml
Normal file
179
docker/docker-compose.development.yml
Normal file
@ -0,0 +1,179 @@
|
||||
# Docker Compose开发环境配置文件
|
||||
# 若依框架前后端分离Docker部署方案 - 开发环境
|
||||
# Requirements: 5.3, 6.5
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# MySQL数据库服务 - 开发环境配置
|
||||
anxin-mysql:
|
||||
image: mysql:8.0
|
||||
container_name: anxin-mysql-dev
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-dev_root_password}
|
||||
MYSQL_DATABASE: ${DB_NAME:-anxin_dev}
|
||||
MYSQL_USER: ${DB_USER:-anxin_dev}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD:-dev_password}
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- "${DB_PORT:-3306}:3306"
|
||||
volumes:
|
||||
- mysql-data-dev:/var/lib/mysql
|
||||
- ./database/init:/docker-entrypoint-initdb.d:ro
|
||||
- ./configs/my.cnf:/etc/mysql/conf.d/my.cnf:ro
|
||||
- mysql-logs-dev:/var/log/mysql
|
||||
networks:
|
||||
- anxin-dev-network
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${DATABASE_MEMORY_LIMIT:-256M}
|
||||
cpus: '${DATABASE_CPU_LIMIT:-0.25}'
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-dev_root_password}"]
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
interval: 30s
|
||||
start_period: 60s
|
||||
|
||||
# Spring Boot后端服务 - 开发环境配置
|
||||
anxin-backend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/backend/Dockerfile
|
||||
target: development
|
||||
image: anxin-backend:dev
|
||||
container_name: anxin-backend-dev
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-dev}
|
||||
SPRING_DATASOURCE_URL: jdbc:mysql://anxin-mysql:3306/${DB_NAME:-anxin_dev}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
|
||||
SPRING_DATASOURCE_USERNAME: ${DB_USER:-anxin_dev}
|
||||
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD:-dev_password}
|
||||
JAVA_OPTS: ${JAVA_OPTS:--Xms256m -Xmx512m -Djava.security.egd=file:/dev/./urandom}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-DEBUG}
|
||||
TZ: Asia/Shanghai
|
||||
# 开发环境特有配置
|
||||
SPRING_DEVTOOLS_RESTART_ENABLED: true
|
||||
SPRING_DEVTOOLS_LIVERELOAD_ENABLED: true
|
||||
LOGGING_LEVEL_COM_RUOYI: DEBUG
|
||||
LOGGING_LEVEL_ROOT: DEBUG
|
||||
ports:
|
||||
- "${BACKEND_PORT:-8080}:8080"
|
||||
- "35729:35729" # LiveReload端口
|
||||
volumes:
|
||||
- backend-logs-dev:/app/logs
|
||||
- backend-uploads-dev:/app/uploadPath
|
||||
- ./configs:/app/config:ro
|
||||
# 开发环境代码热重载
|
||||
- ../ruoyi-admin/src:/app/src:ro
|
||||
networks:
|
||||
- anxin-dev-network
|
||||
depends_on:
|
||||
anxin-mysql:
|
||||
condition: service_healthy
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${BACKEND_MEMORY_LIMIT:-512M}
|
||||
cpus: '${BACKEND_CPU_LIMIT:-0.5}'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
interval: 30s
|
||||
start_period: 90s
|
||||
|
||||
# Vue3前端服务 - 开发环境配置
|
||||
anxin-frontend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/frontend/Dockerfile
|
||||
target: development
|
||||
args:
|
||||
API_BASE_URL: ${API_BASE_URL:-http://localhost:8080}
|
||||
NODE_ENV: development
|
||||
image: anxin-frontend:dev
|
||||
container_name: anxin-frontend-dev
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
NODE_ENV: development
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-3000}:80"
|
||||
- "24678:24678" # Vite HMR端口
|
||||
volumes:
|
||||
- frontend-logs-dev:/var/log/nginx
|
||||
- ./configs/nginx.conf.dev:/etc/nginx/conf.d/default.conf:ro
|
||||
# 开发环境源码挂载用于热重载
|
||||
- ../RuoYi-Vue3/src:/app/src:ro
|
||||
networks:
|
||||
- anxin-dev-network
|
||||
depends_on:
|
||||
anxin-backend:
|
||||
condition: service_healthy
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${FRONTEND_MEMORY_LIMIT:-128M}
|
||||
cpus: '${FRONTEND_CPU_LIMIT:-0.25}'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"]
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
interval: 30s
|
||||
start_period: 30s
|
||||
|
||||
# 网络配置 - 开发环境
|
||||
networks:
|
||||
anxin-dev-network:
|
||||
name: ${NETWORK_NAME:-anxin-dev-network}
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: ${SUBNET:-172.21.0.0/16}
|
||||
gateway: ${GATEWAY:-172.21.0.1}
|
||||
|
||||
# 卷配置 - 开发环境
|
||||
volumes:
|
||||
# 数据库数据持久化卷
|
||||
mysql-data-dev:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_DATA_PATH:-./data/dev/mysql}
|
||||
|
||||
# 数据库日志卷
|
||||
mysql-logs-dev:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_LOG_PATH:-./data/dev/mysql-logs}
|
||||
|
||||
# 后端应用日志卷
|
||||
backend-logs-dev:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKEND_LOG_PATH:-./data/dev/backend-logs}
|
||||
|
||||
# 后端文件上传卷
|
||||
backend-uploads-dev:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKEND_UPLOAD_PATH:-./data/dev/uploads}
|
||||
|
||||
# 前端Nginx日志卷
|
||||
frontend-logs-dev:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${FRONTEND_LOG_PATH:-./data/dev/nginx-logs}
|
||||
291
docker/docker-compose.production.yml
Normal file
291
docker/docker-compose.production.yml
Normal file
@ -0,0 +1,291 @@
|
||||
# Docker Compose生产环境配置文件
|
||||
# 若依框架前后端分离Docker部署方案 - 生产环境
|
||||
# Requirements: 5.3, 6.5
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# MySQL数据库服务 - 生产环境配置
|
||||
anxin-mysql:
|
||||
image: mysql:8.0
|
||||
container_name: anxin-mysql-prod
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
MYSQL_DATABASE: ${DB_NAME:-anxin_prod}
|
||||
MYSQL_USER: ${DB_USER:-anxin_prod}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- "127.0.0.1:${DB_PORT:-3306}:3306" # 生产环境仅绑定本地接口
|
||||
volumes:
|
||||
- mysql-data-prod:/var/lib/mysql
|
||||
- ./database/init:/docker-entrypoint-initdb.d:ro
|
||||
- ./configs/my.cnf.prod:/etc/mysql/conf.d/my.cnf:ro
|
||||
- mysql-logs-prod:/var/log/mysql
|
||||
networks:
|
||||
- anxin-prod-network
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${DATABASE_MEMORY_LIMIT:-1024M}
|
||||
cpus: '${DATABASE_CPU_LIMIT:-1.0}'
|
||||
reservations:
|
||||
memory: 512M
|
||||
cpus: '0.5'
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
interval: 30s
|
||||
start_period: 60s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-200m}"
|
||||
max-file: "${LOG_MAX_FILES:-15}"
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /var/run/mysqld
|
||||
|
||||
# Spring Boot后端服务 - 生产环境配置
|
||||
anxin-backend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/backend/Dockerfile
|
||||
target: production
|
||||
image: anxin-backend:prod
|
||||
container_name: anxin-backend-prod
|
||||
restart: always
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
||||
SPRING_DATASOURCE_URL: jdbc:mysql://anxin-mysql:3306/${DB_NAME:-anxin_prod}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&requireSSL=true
|
||||
SPRING_DATASOURCE_USERNAME: ${DB_USER:-anxin_prod}
|
||||
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
|
||||
JAVA_OPTS: ${JAVA_OPTS:--Xms1024m -Xmx2048m -Djava.security.egd=file:/dev/./urandom -XX:+UseG1GC -XX:+UseStringDeduplication}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-WARN}
|
||||
TZ: Asia/Shanghai
|
||||
# 生产环境特有配置
|
||||
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: health,info,metrics
|
||||
MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS: never
|
||||
LOGGING_LEVEL_COM_RUOYI: WARN
|
||||
LOGGING_LEVEL_ROOT: WARN
|
||||
# 安全配置
|
||||
SPRING_SECURITY_REQUIRE_SSL: true
|
||||
SERVER_SSL_ENABLED: false # 通过反向代理处理SSL
|
||||
ports:
|
||||
- "127.0.0.1:${BACKEND_PORT:-8080}:8080" # 生产环境仅绑定本地接口
|
||||
volumes:
|
||||
- backend-logs-prod:/app/logs
|
||||
- backend-uploads-prod:/app/uploadPath
|
||||
- ./configs:/app/config:ro
|
||||
networks:
|
||||
- anxin-prod-network
|
||||
depends_on:
|
||||
anxin-mysql:
|
||||
condition: service_healthy
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${BACKEND_MEMORY_LIMIT:-2048M}
|
||||
cpus: '${BACKEND_CPU_LIMIT:-2.0}'
|
||||
reservations:
|
||||
memory: 1024M
|
||||
cpus: '1.0'
|
||||
replicas: ${BACKEND_REPLICAS:-1}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
interval: 30s
|
||||
start_period: 120s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-200m}"
|
||||
max-file: "${LOG_MAX_FILES:-15}"
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
|
||||
# Vue3前端服务 - 生产环境配置
|
||||
anxin-frontend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/frontend/Dockerfile
|
||||
target: production
|
||||
args:
|
||||
API_BASE_URL: ${API_BASE_URL:-https://api.anxin.com}
|
||||
NODE_ENV: production
|
||||
image: anxin-frontend:prod
|
||||
container_name: anxin-frontend-prod
|
||||
restart: always
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
NODE_ENV: production
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-80}:80"
|
||||
- "${FRONTEND_SSL_PORT:-443}:443"
|
||||
volumes:
|
||||
- frontend-logs-prod:/var/log/nginx
|
||||
- ./configs/nginx.conf.prod:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./configs/ssl:/etc/nginx/ssl:ro # SSL证书
|
||||
networks:
|
||||
- anxin-prod-network
|
||||
depends_on:
|
||||
anxin-backend:
|
||||
condition: service_healthy
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${FRONTEND_MEMORY_LIMIT:-512M}
|
||||
cpus: '${FRONTEND_CPU_LIMIT:-1.0}'
|
||||
reservations:
|
||||
memory: 256M
|
||||
cpus: '0.5'
|
||||
replicas: ${FRONTEND_REPLICAS:-1}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"]
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
interval: 30s
|
||||
start_period: 30s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-200m}"
|
||||
max-file: "${LOG_MAX_FILES:-15}"
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
|
||||
# 生产环境专用服务 - 数据库备份服务
|
||||
anxin-db-backup:
|
||||
image: mysql:8.0
|
||||
container_name: anxin-db-backup-prod
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
BACKUP_SCHEDULE: ${BACKUP_SCHEDULE:-0 2 * * *} # 每天凌晨2点备份
|
||||
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-30}
|
||||
volumes:
|
||||
- mysql-data-prod:/var/lib/mysql:ro
|
||||
- backup-data-prod:/backup
|
||||
- ./scripts/backup-prod.sh:/backup.sh:ro
|
||||
networks:
|
||||
- anxin-prod-network
|
||||
depends_on:
|
||||
anxin-mysql:
|
||||
condition: service_healthy
|
||||
command: >
|
||||
sh -c "
|
||||
echo 'Starting database backup service for production environment...'
|
||||
echo '${BACKUP_SCHEDULE} /backup.sh' | crontab -
|
||||
crond -f
|
||||
"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
cpus: '0.2'
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "5"
|
||||
|
||||
# 生产环境专用服务 - 监控服务
|
||||
anxin-monitor:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: anxin-monitor-prod
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:9100:9100"
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
networks:
|
||||
- anxin-prod-network
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.rootfs=/rootfs'
|
||||
- '--path.sysfs=/host/sys'
|
||||
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 128M
|
||||
cpus: '0.1'
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# 网络配置 - 生产环境
|
||||
networks:
|
||||
anxin-prod-network:
|
||||
name: ${NETWORK_NAME:-anxin-prod-network}
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: ${SUBNET:-172.23.0.0/16}
|
||||
gateway: ${GATEWAY:-172.23.0.1}
|
||||
driver_opts:
|
||||
com.docker.network.bridge.name: anxin-prod-br0
|
||||
|
||||
# 卷配置 - 生产环境
|
||||
volumes:
|
||||
# 数据库数据持久化卷
|
||||
mysql-data-prod:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_DATA_PATH:-/var/lib/anxin/mysql}
|
||||
|
||||
# 数据库日志卷
|
||||
mysql-logs-prod:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_LOG_PATH:-/var/log/anxin/mysql}
|
||||
|
||||
# 后端应用日志卷
|
||||
backend-logs-prod:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKEND_LOG_PATH:-/var/log/anxin/backend}
|
||||
|
||||
# 后端文件上传卷
|
||||
backend-uploads-prod:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKEND_UPLOAD_PATH:-/var/lib/anxin/uploads}
|
||||
|
||||
# 前端Nginx日志卷
|
||||
frontend-logs-prod:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${FRONTEND_LOG_PATH:-/var/log/anxin/nginx}
|
||||
|
||||
# 数据库备份卷
|
||||
backup-data-prod:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKUP_DATA_PATH:-/var/lib/anxin/backups}
|
||||
225
docker/docker-compose.staging.yml
Normal file
225
docker/docker-compose.staging.yml
Normal file
@ -0,0 +1,225 @@
|
||||
# Docker Compose测试环境配置文件
|
||||
# 若依框架前后端分离Docker部署方案 - 测试环境
|
||||
# Requirements: 5.3, 6.5
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# MySQL数据库服务 - 测试环境配置
|
||||
anxin-mysql:
|
||||
image: mysql:8.0
|
||||
container_name: anxin-mysql-staging
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-staging_root_password}
|
||||
MYSQL_DATABASE: ${DB_NAME:-anxin_staging}
|
||||
MYSQL_USER: ${DB_USER:-anxin_staging}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD:-staging_password}
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- "${DB_PORT:-3306}:3306"
|
||||
volumes:
|
||||
- mysql-data-staging:/var/lib/mysql
|
||||
- ./database/init:/docker-entrypoint-initdb.d:ro
|
||||
- ./configs/my.cnf:/etc/mysql/conf.d/my.cnf:ro
|
||||
- mysql-logs-staging:/var/log/mysql
|
||||
networks:
|
||||
- anxin-staging-network
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${DATABASE_MEMORY_LIMIT:-384M}
|
||||
cpus: '${DATABASE_CPU_LIMIT:-0.5}'
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-staging_root_password}"]
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
interval: 30s
|
||||
start_period: 60s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-100m}"
|
||||
max-file: "${LOG_MAX_FILES:-7}"
|
||||
|
||||
# Spring Boot后端服务 - 测试环境配置
|
||||
anxin-backend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/backend/Dockerfile
|
||||
target: production
|
||||
image: anxin-backend:staging
|
||||
container_name: anxin-backend-staging
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-staging}
|
||||
SPRING_DATASOURCE_URL: jdbc:mysql://anxin-mysql:3306/${DB_NAME:-anxin_staging}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
SPRING_DATASOURCE_USERNAME: ${DB_USER:-anxin_staging}
|
||||
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD:-staging_password}
|
||||
JAVA_OPTS: ${JAVA_OPTS:--Xms512m -Xmx768m -Djava.security.egd=file:/dev/./urandom}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
||||
TZ: Asia/Shanghai
|
||||
# 测试环境特有配置
|
||||
SPRING_JPA_SHOW_SQL: true
|
||||
LOGGING_LEVEL_COM_RUOYI: INFO
|
||||
MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE: health,info,metrics,prometheus
|
||||
ports:
|
||||
- "${BACKEND_PORT:-8080}:8080"
|
||||
volumes:
|
||||
- backend-logs-staging:/app/logs
|
||||
- backend-uploads-staging:/app/uploadPath
|
||||
- ./configs:/app/config:ro
|
||||
networks:
|
||||
- anxin-staging-network
|
||||
depends_on:
|
||||
anxin-mysql:
|
||||
condition: service_healthy
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${BACKEND_MEMORY_LIMIT:-768M}
|
||||
cpus: '${BACKEND_CPU_LIMIT:-0.75}'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
|
||||
timeout: 30s
|
||||
retries: 5
|
||||
interval: 30s
|
||||
start_period: 90s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-100m}"
|
||||
max-file: "${LOG_MAX_FILES:-7}"
|
||||
|
||||
# Vue3前端服务 - 测试环境配置
|
||||
anxin-frontend:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/frontend/Dockerfile
|
||||
target: production
|
||||
args:
|
||||
API_BASE_URL: ${API_BASE_URL:-http://staging-api.anxin.com}
|
||||
NODE_ENV: production
|
||||
image: anxin-frontend:staging
|
||||
container_name: anxin-frontend-staging
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
NODE_ENV: production
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-80}:80"
|
||||
volumes:
|
||||
- frontend-logs-staging:/var/log/nginx
|
||||
- ./configs/nginx.conf.staging:/etc/nginx/conf.d/default.conf:ro
|
||||
networks:
|
||||
- anxin-staging-network
|
||||
depends_on:
|
||||
anxin-backend:
|
||||
condition: service_healthy
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: ${FRONTEND_MEMORY_LIMIT:-192M}
|
||||
cpus: '${FRONTEND_CPU_LIMIT:-0.5}'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"]
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
interval: 30s
|
||||
start_period: 30s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "${LOG_MAX_SIZE:-100m}"
|
||||
max-file: "${LOG_MAX_FILES:-7}"
|
||||
|
||||
# 测试环境专用服务 - 数据库备份服务
|
||||
anxin-db-backup:
|
||||
image: mysql:8.0
|
||||
container_name: anxin-db-backup-staging
|
||||
restart: "no"
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-staging_root_password}
|
||||
volumes:
|
||||
- mysql-data-staging:/var/lib/mysql:ro
|
||||
- backup-data-staging:/backup
|
||||
- ./scripts/backup.sh:/backup.sh:ro
|
||||
networks:
|
||||
- anxin-staging-network
|
||||
depends_on:
|
||||
anxin-mysql:
|
||||
condition: service_healthy
|
||||
command: >
|
||||
sh -c "
|
||||
echo 'Starting database backup service for staging environment...'
|
||||
while true; do
|
||||
sleep 86400
|
||||
/backup.sh
|
||||
done
|
||||
"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 128M
|
||||
cpus: '0.1'
|
||||
|
||||
# 网络配置 - 测试环境
|
||||
networks:
|
||||
anxin-staging-network:
|
||||
name: ${NETWORK_NAME:-anxin-staging-network}
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: ${SUBNET:-172.22.0.0/16}
|
||||
gateway: ${GATEWAY:-172.22.0.1}
|
||||
|
||||
# 卷配置 - 测试环境
|
||||
volumes:
|
||||
# 数据库数据持久化卷
|
||||
mysql-data-staging:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_DATA_PATH:-./data/staging/mysql}
|
||||
|
||||
# 数据库日志卷
|
||||
mysql-logs-staging:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${MYSQL_LOG_PATH:-./data/staging/mysql-logs}
|
||||
|
||||
# 后端应用日志卷
|
||||
backend-logs-staging:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKEND_LOG_PATH:-./data/staging/backend-logs}
|
||||
|
||||
# 后端文件上传卷
|
||||
backend-uploads-staging:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKEND_UPLOAD_PATH:-./data/staging/uploads}
|
||||
|
||||
# 前端Nginx日志卷
|
||||
frontend-logs-staging:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${FRONTEND_LOG_PATH:-./data/staging/nginx-logs}
|
||||
|
||||
# 数据库备份卷
|
||||
backup-data-staging:
|
||||
driver: local
|
||||
driver_opts:
|
||||
type: none
|
||||
o: bind
|
||||
device: ${BACKUP_DATA_PATH:-./data/staging/backups}
|
||||
44
docker/environments/.env.development
Normal file
44
docker/environments/.env.development
Normal file
@ -0,0 +1,44 @@
|
||||
# 开发环境配置 (Requirements 6.5)
|
||||
ENVIRONMENT=development
|
||||
COMPOSE_PROJECT_NAME=anxin-dev
|
||||
|
||||
# 数据库配置
|
||||
DB_HOST=anxin-mysql
|
||||
DB_PORT=3306
|
||||
DB_NAME=anxin_dev
|
||||
DB_USER=anxin_dev
|
||||
DB_PASSWORD=dev_password
|
||||
MYSQL_ROOT_PASSWORD=dev_root_password
|
||||
|
||||
# 后端服务配置
|
||||
BACKEND_PORT=8080
|
||||
SPRING_PROFILES_ACTIVE=dev
|
||||
JAVA_OPTS=-Xms256m -Xmx512m
|
||||
|
||||
# 前端服务配置
|
||||
FRONTEND_PORT=3000
|
||||
API_BASE_URL=http://localhost:8080
|
||||
|
||||
# 容器资源配置 (开发环境使用较少资源)
|
||||
FRONTEND_MEMORY_LIMIT=128
|
||||
BACKEND_MEMORY_LIMIT=512
|
||||
DATABASE_MEMORY_LIMIT=256
|
||||
|
||||
FRONTEND_CPU_LIMIT=0.25
|
||||
BACKEND_CPU_LIMIT=0.5
|
||||
DATABASE_CPU_LIMIT=0.25
|
||||
|
||||
# 日志配置 (开发环境使用DEBUG级别)
|
||||
LOG_LEVEL=DEBUG
|
||||
LOG_PATH=./logs/dev
|
||||
LOG_MAX_SIZE=50MB
|
||||
LOG_MAX_FILES=5
|
||||
|
||||
# 网络配置
|
||||
NETWORK_NAME=anxin-dev-network
|
||||
SUBNET=172.21.0.0/16
|
||||
|
||||
# 卷配置
|
||||
MYSQL_DATA_PATH=./data/dev/mysql
|
||||
LOG_DATA_PATH=./data/dev/logs
|
||||
CONFIG_DATA_PATH=./data/dev/configs
|
||||
44
docker/environments/.env.production
Normal file
44
docker/environments/.env.production
Normal file
@ -0,0 +1,44 @@
|
||||
# 生产环境配置 (Requirements 6.5)
|
||||
ENVIRONMENT=production
|
||||
COMPOSE_PROJECT_NAME=anxin-prod
|
||||
|
||||
# 数据库配置
|
||||
DB_HOST=anxin-mysql
|
||||
DB_PORT=3306
|
||||
DB_NAME=anxin_prod
|
||||
DB_USER=anxin_prod
|
||||
DB_PASSWORD=CHANGE_ME_PRODUCTION_PASSWORD
|
||||
MYSQL_ROOT_PASSWORD=CHANGE_ME_ROOT_PASSWORD
|
||||
|
||||
# 后端服务配置
|
||||
BACKEND_PORT=8080
|
||||
SPRING_PROFILES_ACTIVE=prod
|
||||
JAVA_OPTS=-Xms1024m -Xmx2048m
|
||||
|
||||
# 前端服务配置
|
||||
FRONTEND_PORT=80
|
||||
API_BASE_URL=https://api.anxin.com
|
||||
|
||||
# 容器资源配置 (生产环境使用更多资源)
|
||||
FRONTEND_MEMORY_LIMIT=512
|
||||
BACKEND_MEMORY_LIMIT=2048
|
||||
DATABASE_MEMORY_LIMIT=1024
|
||||
|
||||
FRONTEND_CPU_LIMIT=1.0
|
||||
BACKEND_CPU_LIMIT=2.0
|
||||
DATABASE_CPU_LIMIT=1.0
|
||||
|
||||
# 日志配置 (生产环境使用WARN级别)
|
||||
LOG_LEVEL=WARN
|
||||
LOG_PATH=./logs/prod
|
||||
LOG_MAX_SIZE=200MB
|
||||
LOG_MAX_FILES=15
|
||||
|
||||
# 网络配置
|
||||
NETWORK_NAME=anxin-prod-network
|
||||
SUBNET=172.23.0.0/16
|
||||
|
||||
# 卷配置
|
||||
MYSQL_DATA_PATH=./data/prod/mysql
|
||||
LOG_DATA_PATH=./data/prod/logs
|
||||
CONFIG_DATA_PATH=./data/prod/configs
|
||||
44
docker/environments/.env.staging
Normal file
44
docker/environments/.env.staging
Normal file
@ -0,0 +1,44 @@
|
||||
# 测试环境配置 (Requirements 6.5)
|
||||
ENVIRONMENT=staging
|
||||
COMPOSE_PROJECT_NAME=anxin-staging
|
||||
|
||||
# 数据库配置
|
||||
DB_HOST=anxin-mysql
|
||||
DB_PORT=3306
|
||||
DB_NAME=anxin_staging
|
||||
DB_USER=anxin_staging
|
||||
DB_PASSWORD=staging_password
|
||||
MYSQL_ROOT_PASSWORD=staging_root_password
|
||||
|
||||
# 后端服务配置
|
||||
BACKEND_PORT=8080
|
||||
SPRING_PROFILES_ACTIVE=staging
|
||||
JAVA_OPTS=-Xms512m -Xmx768m
|
||||
|
||||
# 前端服务配置
|
||||
FRONTEND_PORT=80
|
||||
API_BASE_URL=http://staging-api.anxin.com
|
||||
|
||||
# 容器资源配置 (测试环境使用中等资源)
|
||||
FRONTEND_MEMORY_LIMIT=192
|
||||
BACKEND_MEMORY_LIMIT=768
|
||||
DATABASE_MEMORY_LIMIT=384
|
||||
|
||||
FRONTEND_CPU_LIMIT=0.5
|
||||
BACKEND_CPU_LIMIT=0.75
|
||||
DATABASE_CPU_LIMIT=0.5
|
||||
|
||||
# 日志配置
|
||||
LOG_LEVEL=INFO
|
||||
LOG_PATH=./logs/staging
|
||||
LOG_MAX_SIZE=100MB
|
||||
LOG_MAX_FILES=7
|
||||
|
||||
# 网络配置
|
||||
NETWORK_NAME=anxin-staging-network
|
||||
SUBNET=172.22.0.0/16
|
||||
|
||||
# 卷配置
|
||||
MYSQL_DATA_PATH=./data/staging/mysql
|
||||
LOG_DATA_PATH=./data/staging/logs
|
||||
CONFIG_DATA_PATH=./data/staging/configs
|
||||
40
docker/frontend/.dockerignore
Normal file
40
docker/frontend/.dockerignore
Normal file
@ -0,0 +1,40 @@
|
||||
# Node modules
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Build outputs
|
||||
dist
|
||||
.tmp
|
||||
.cache
|
||||
|
||||
# IDE files
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Documentation
|
||||
README.md
|
||||
*.md
|
||||
|
||||
# Test files
|
||||
tests
|
||||
__tests__
|
||||
*.test.js
|
||||
*.spec.js
|
||||
|
||||
# Environment files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
2
docker/frontend/.gitkeep
Normal file
2
docker/frontend/.gitkeep
Normal file
@ -0,0 +1,2 @@
|
||||
# 前端容器配置目录
|
||||
# 此文件确保目录被Git跟踪
|
||||
43
docker/frontend/Dockerfile
Normal file
43
docker/frontend/Dockerfile
Normal file
@ -0,0 +1,43 @@
|
||||
# 多阶段构建 Dockerfile for 若依 Vue3 前端应用
|
||||
|
||||
# 第一阶段:构建阶段
|
||||
FROM node:18-alpine AS build-stage
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 复制 package.json 和 package-lock.json(如果存在)
|
||||
COPY RuoYi-Vue3/package*.json ./
|
||||
|
||||
# 安装依赖
|
||||
RUN npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
# 复制源代码
|
||||
COPY RuoYi-Vue3/ .
|
||||
|
||||
# 构建应用
|
||||
RUN npm run build:prod
|
||||
|
||||
# 第二阶段:运行阶段
|
||||
FROM nginx:alpine AS production-stage
|
||||
|
||||
# 安装 tzdata 用于时区设置
|
||||
RUN apk add --no-cache tzdata
|
||||
|
||||
# 设置时区
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
# 从构建阶段复制构建产物到 nginx 默认目录
|
||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
||||
|
||||
# 复制 nginx 配置文件
|
||||
COPY docker/configs/nginx.conf.template /etc/nginx/conf.d/default.conf
|
||||
|
||||
# 创建日志目录
|
||||
RUN mkdir -p /var/log/nginx
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 80
|
||||
|
||||
# 启动 nginx
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
67
docker/frontend/build.sh
Normal file
67
docker/frontend/build.sh
Normal file
@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 前端容器构建脚本
|
||||
# 用于构建若依 Vue3 前端 Docker 镜像
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查 Docker 是否安装
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker 未安装或不在 PATH 中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 设置变量
|
||||
IMAGE_NAME="anxin-frontend"
|
||||
TAG="${1:-latest}"
|
||||
DOCKERFILE_PATH="docker/frontend/Dockerfile"
|
||||
|
||||
log_info "开始构建前端 Docker 镜像..."
|
||||
log_info "镜像名称: ${IMAGE_NAME}:${TAG}"
|
||||
log_info "Dockerfile 路径: ${DOCKERFILE_PATH}"
|
||||
|
||||
# 检查 Dockerfile 是否存在
|
||||
if [ ! -f "${DOCKERFILE_PATH}" ]; then
|
||||
log_error "Dockerfile 不存在: ${DOCKERFILE_PATH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查前端源码目录是否存在
|
||||
if [ ! -d "RuoYi-Vue3" ]; then
|
||||
log_error "前端源码目录不存在: RuoYi-Vue3"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 构建镜像
|
||||
log_info "正在构建镜像..."
|
||||
if docker build -t "${IMAGE_NAME}:${TAG}" -f "${DOCKERFILE_PATH}" .; then
|
||||
log_info "镜像构建成功: ${IMAGE_NAME}:${TAG}"
|
||||
|
||||
# 显示镜像信息
|
||||
log_info "镜像信息:"
|
||||
docker images "${IMAGE_NAME}:${TAG}"
|
||||
else
|
||||
log_error "镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "前端镜像构建完成!"
|
||||
2
docker/scripts/.gitkeep
Normal file
2
docker/scripts/.gitkeep
Normal file
@ -0,0 +1,2 @@
|
||||
# 构建和部署脚本目录
|
||||
# 此文件确保目录被Git跟踪
|
||||
104
docker/scripts/backup-prod.sh
Normal file
104
docker/scripts/backup-prod.sh
Normal file
@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
# 生产环境数据库备份脚本
|
||||
# Requirements: 5.3, 6.5
|
||||
|
||||
set -e
|
||||
|
||||
# 配置变量
|
||||
BACKUP_DIR="/backup"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
DB_NAME=${DB_NAME:-anxin_prod}
|
||||
DB_USER=${DB_USER:-anxin_prod}
|
||||
DB_PASSWORD=${DB_PASSWORD}
|
||||
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
|
||||
RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-30}
|
||||
|
||||
# 日志函数
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
|
||||
# 创建备份目录
|
||||
mkdir -p "${BACKUP_DIR}/daily"
|
||||
mkdir -p "${BACKUP_DIR}/weekly"
|
||||
mkdir -p "${BACKUP_DIR}/monthly"
|
||||
|
||||
# 执行数据库备份
|
||||
log "Starting database backup for production environment..."
|
||||
|
||||
# 全量备份
|
||||
BACKUP_FILE="${BACKUP_DIR}/daily/${DB_NAME}_${DATE}.sql.gz"
|
||||
log "Creating full backup: ${BACKUP_FILE}"
|
||||
|
||||
mysqldump -h anxin-mysql \
|
||||
-u root \
|
||||
-p"${MYSQL_ROOT_PASSWORD}" \
|
||||
--single-transaction \
|
||||
--routines \
|
||||
--triggers \
|
||||
--events \
|
||||
--hex-blob \
|
||||
--opt \
|
||||
--lock-tables=false \
|
||||
"${DB_NAME}" | gzip > "${BACKUP_FILE}"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Database backup completed successfully"
|
||||
|
||||
# 验证备份文件
|
||||
if [ -f "${BACKUP_FILE}" ] && [ -s "${BACKUP_FILE}" ]; then
|
||||
log "Backup file verification passed: $(du -h ${BACKUP_FILE} | cut -f1)"
|
||||
else
|
||||
log "ERROR: Backup file verification failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "ERROR: Database backup failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 周备份 (每周日)
|
||||
if [ $(date +%u) -eq 7 ]; then
|
||||
WEEKLY_BACKUP="${BACKUP_DIR}/weekly/${DB_NAME}_week_${DATE}.sql.gz"
|
||||
log "Creating weekly backup: ${WEEKLY_BACKUP}"
|
||||
cp "${BACKUP_FILE}" "${WEEKLY_BACKUP}"
|
||||
fi
|
||||
|
||||
# 月备份 (每月1号)
|
||||
if [ $(date +%d) -eq 01 ]; then
|
||||
MONTHLY_BACKUP="${BACKUP_DIR}/monthly/${DB_NAME}_month_${DATE}.sql.gz"
|
||||
log "Creating monthly backup: ${MONTHLY_BACKUP}"
|
||||
cp "${BACKUP_FILE}" "${MONTHLY_BACKUP}"
|
||||
fi
|
||||
|
||||
# 清理过期备份
|
||||
log "Cleaning up old backups..."
|
||||
|
||||
# 清理日备份 (保留指定天数)
|
||||
find "${BACKUP_DIR}/daily" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
|
||||
log "Cleaned up daily backups older than ${RETENTION_DAYS} days"
|
||||
|
||||
# 清理周备份 (保留12周)
|
||||
find "${BACKUP_DIR}/weekly" -name "*.sql.gz" -mtime +84 -delete
|
||||
log "Cleaned up weekly backups older than 12 weeks"
|
||||
|
||||
# 清理月备份 (保留12个月)
|
||||
find "${BACKUP_DIR}/monthly" -name "*.sql.gz" -mtime +365 -delete
|
||||
log "Cleaned up monthly backups older than 12 months"
|
||||
|
||||
# 备份统计
|
||||
DAILY_COUNT=$(ls -1 "${BACKUP_DIR}/daily"/*.sql.gz 2>/dev/null | wc -l)
|
||||
WEEKLY_COUNT=$(ls -1 "${BACKUP_DIR}/weekly"/*.sql.gz 2>/dev/null | wc -l)
|
||||
MONTHLY_COUNT=$(ls -1 "${BACKUP_DIR}/monthly"/*.sql.gz 2>/dev/null | wc -l)
|
||||
|
||||
log "Backup statistics: Daily: ${DAILY_COUNT}, Weekly: ${WEEKLY_COUNT}, Monthly: ${MONTHLY_COUNT}"
|
||||
|
||||
# 发送备份状态通知 (如果配置了通知)
|
||||
if [ -n "${BACKUP_NOTIFICATION_URL}" ]; then
|
||||
curl -X POST "${BACKUP_NOTIFICATION_URL}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"status\":\"success\",\"message\":\"Production database backup completed\",\"timestamp\":\"${DATE}\"}" \
|
||||
2>/dev/null || log "Failed to send backup notification"
|
||||
fi
|
||||
|
||||
log "Production database backup process completed successfully"
|
||||
65
docker/scripts/backup.sh
Normal file
65
docker/scripts/backup.sh
Normal file
@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# 测试环境数据库备份脚本
|
||||
# Requirements: 5.3, 6.5
|
||||
|
||||
set -e
|
||||
|
||||
# 配置变量
|
||||
BACKUP_DIR="/backup"
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
DB_NAME=${DB_NAME:-anxin_staging}
|
||||
DB_USER=${DB_USER:-anxin_staging}
|
||||
DB_PASSWORD=${DB_PASSWORD:-staging_password}
|
||||
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-staging_root_password}
|
||||
RETENTION_DAYS=${BACKUP_RETENTION_DAYS:-7}
|
||||
|
||||
# 日志函数
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
|
||||
# 创建备份目录
|
||||
mkdir -p "${BACKUP_DIR}"
|
||||
|
||||
# 执行数据库备份
|
||||
log "Starting database backup for staging environment..."
|
||||
|
||||
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE}.sql.gz"
|
||||
log "Creating backup: ${BACKUP_FILE}"
|
||||
|
||||
mysqldump -h anxin-mysql \
|
||||
-u root \
|
||||
-p"${MYSQL_ROOT_PASSWORD}" \
|
||||
--single-transaction \
|
||||
--routines \
|
||||
--triggers \
|
||||
--hex-blob \
|
||||
--opt \
|
||||
--lock-tables=false \
|
||||
"${DB_NAME}" | gzip > "${BACKUP_FILE}"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
log "Database backup completed successfully"
|
||||
|
||||
# 验证备份文件
|
||||
if [ -f "${BACKUP_FILE}" ] && [ -s "${BACKUP_FILE}" ]; then
|
||||
log "Backup file verification passed: $(du -h ${BACKUP_FILE} | cut -f1)"
|
||||
else
|
||||
log "ERROR: Backup file verification failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log "ERROR: Database backup failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 清理过期备份
|
||||
log "Cleaning up old backups..."
|
||||
find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
|
||||
log "Cleaned up backups older than ${RETENTION_DAYS} days"
|
||||
|
||||
# 备份统计
|
||||
BACKUP_COUNT=$(ls -1 "${BACKUP_DIR}"/*.sql.gz 2>/dev/null | wc -l)
|
||||
log "Current backup count: ${BACKUP_COUNT}"
|
||||
|
||||
log "Staging database backup process completed successfully"
|
||||
701
docker/scripts/env-config.sh
Normal file
701
docker/scripts/env-config.sh
Normal file
@ -0,0 +1,701 @@
|
||||
#!/bin/bash
|
||||
# 环境配置管理脚本 (env-config.sh)
|
||||
# 实现环境变量配置管理、支持不同环境的参数切换、添加配置验证功能
|
||||
# Requirements: 6.1, 6.2, 6.3, 6.4
|
||||
|
||||
set -e
|
||||
|
||||
# 脚本目录和项目路径
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DOCKER_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PROJECT_ROOT="$(dirname "$DOCKER_DIR")"
|
||||
ENVIRONMENTS_DIR="${DOCKER_DIR}/environments"
|
||||
CONFIGS_DIR="${DOCKER_DIR}/configs"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_debug() {
|
||||
echo -e "${BLUE}[DEBUG]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${CYAN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
环境配置管理脚本 - 若依框架Docker部署
|
||||
|
||||
用法: $0 [命令] [环境] [选项]
|
||||
|
||||
命令:
|
||||
validate 验证环境配置文件
|
||||
switch 切换到指定环境配置
|
||||
show 显示环境配置信息
|
||||
compare 比较不同环境配置
|
||||
backup 备份当前环境配置
|
||||
restore 恢复环境配置
|
||||
template 生成环境配置模板
|
||||
check 检查配置完整性
|
||||
list 列出所有可用环境
|
||||
help 显示此帮助信息
|
||||
|
||||
环境:
|
||||
development (dev) 开发环境
|
||||
staging (stage) 测试环境
|
||||
production (prod) 生产环境
|
||||
|
||||
选项:
|
||||
--force 强制执行操作(跳过确认)
|
||||
--verbose 详细输出模式
|
||||
--dry-run 预览模式(不实际执行)
|
||||
|
||||
示例:
|
||||
$0 validate development # 验证开发环境配置
|
||||
$0 switch production # 切换到生产环境
|
||||
$0 show staging # 显示测试环境配置
|
||||
$0 compare dev prod # 比较开发和生产环境配置
|
||||
$0 backup # 备份当前配置
|
||||
$0 template development # 生成开发环境配置模板
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 验证环境参数
|
||||
validate_environment() {
|
||||
local env=$1
|
||||
case $env in
|
||||
development|dev)
|
||||
echo "development"
|
||||
;;
|
||||
staging|stage)
|
||||
echo "staging"
|
||||
;;
|
||||
production|prod)
|
||||
echo "production"
|
||||
;;
|
||||
*)
|
||||
log_error "无效的环境: $env"
|
||||
log_info "支持的环境: development, staging, production"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 获取环境配置文件路径
|
||||
get_env_file() {
|
||||
local env=$1
|
||||
echo "${ENVIRONMENTS_DIR}/.env.${env}"
|
||||
}
|
||||
|
||||
# 获取当前活动的环境配置文件路径
|
||||
get_active_env_file() {
|
||||
echo "${DOCKER_DIR}/.env"
|
||||
}
|
||||
|
||||
# 检查环境配置文件是否存在
|
||||
check_env_file_exists() {
|
||||
local env=$1
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
if [ ! -f "$env_file" ]; then
|
||||
log_error "环境配置文件不存在: $env_file"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# 验证环境配置文件 (Requirements 6.1, 6.2, 6.3, 6.4)
|
||||
validate_env_config() {
|
||||
local env=$1
|
||||
local env_file=$(get_env_file $env)
|
||||
local errors=0
|
||||
|
||||
log_info "验证 $env 环境配置文件: $env_file"
|
||||
|
||||
if ! check_env_file_exists $env; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 必需的配置项列表
|
||||
local required_vars=(
|
||||
"ENVIRONMENT"
|
||||
"COMPOSE_PROJECT_NAME"
|
||||
"DB_HOST"
|
||||
"DB_PORT"
|
||||
"DB_NAME"
|
||||
"DB_USER"
|
||||
"DB_PASSWORD"
|
||||
"MYSQL_ROOT_PASSWORD"
|
||||
"BACKEND_PORT"
|
||||
"FRONTEND_PORT"
|
||||
"SPRING_PROFILES_ACTIVE"
|
||||
"API_BASE_URL"
|
||||
"LOG_LEVEL"
|
||||
"NETWORK_NAME"
|
||||
"MYSQL_DATA_PATH"
|
||||
)
|
||||
|
||||
# 检查必需的环境变量
|
||||
log_debug "检查必需的环境变量..."
|
||||
for var in "${required_vars[@]}"; do
|
||||
if ! grep -q "^${var}=" "$env_file"; then
|
||||
log_error "缺少必需的环境变量: $var"
|
||||
((errors++))
|
||||
else
|
||||
local value=$(grep "^${var}=" "$env_file" | cut -d'=' -f2-)
|
||||
if [ -z "$value" ] || [ "$value" = "CHANGE_ME_PRODUCTION_PASSWORD" ] || [ "$value" = "CHANGE_ME_ROOT_PASSWORD" ]; then
|
||||
log_warn "环境变量 $var 需要设置有效值"
|
||||
((errors++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 验证数据库连接配置 (Requirement 6.1)
|
||||
log_debug "验证数据库连接配置..."
|
||||
local db_port=$(grep "^DB_PORT=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$db_port" ] && ! [[ "$db_port" =~ ^[0-9]+$ ]]; then
|
||||
log_error "DB_PORT 必须是数字: $db_port"
|
||||
((errors++))
|
||||
fi
|
||||
|
||||
# 验证前端API基础URL配置 (Requirement 6.2)
|
||||
log_debug "验证前端API基础URL配置..."
|
||||
local api_url=$(grep "^API_BASE_URL=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$api_url" ] && ! [[ "$api_url" =~ ^https?:// ]]; then
|
||||
log_error "API_BASE_URL 必须是有效的HTTP/HTTPS URL: $api_url"
|
||||
((errors++))
|
||||
fi
|
||||
|
||||
# 验证容器资源限制配置 (Requirement 6.3)
|
||||
log_debug "验证容器资源限制配置..."
|
||||
local memory_vars=("FRONTEND_MEMORY_LIMIT" "BACKEND_MEMORY_LIMIT" "DATABASE_MEMORY_LIMIT")
|
||||
for var in "${memory_vars[@]}"; do
|
||||
local value=$(grep "^${var}=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$value" ] && ! [[ "$value" =~ ^[0-9]+$ ]]; then
|
||||
log_error "$var 必须是数字 (MB): $value"
|
||||
((errors++))
|
||||
fi
|
||||
done
|
||||
|
||||
local cpu_vars=("FRONTEND_CPU_LIMIT" "BACKEND_CPU_LIMIT" "DATABASE_CPU_LIMIT")
|
||||
for var in "${cpu_vars[@]}"; do
|
||||
local value=$(grep "^${var}=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$value" ] && ! [[ "$value" =~ ^[0-9]+\.?[0-9]*$ ]]; then
|
||||
log_error "$var 必须是有效的CPU限制值: $value"
|
||||
((errors++))
|
||||
fi
|
||||
done
|
||||
|
||||
# 验证日志级别和输出路径配置 (Requirement 6.4)
|
||||
log_debug "验证日志配置..."
|
||||
local log_level=$(grep "^LOG_LEVEL=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$log_level" ] && ! [[ "$log_level" =~ ^(DEBUG|INFO|WARN|ERROR)$ ]]; then
|
||||
log_error "LOG_LEVEL 必须是 DEBUG, INFO, WARN 或 ERROR: $log_level"
|
||||
((errors++))
|
||||
fi
|
||||
|
||||
local log_path=$(grep "^LOG_PATH=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$log_path" ] && [[ "$log_path" =~ ^/ ]] && [ ! -d "$(dirname "$log_path")" ]; then
|
||||
log_warn "日志路径的父目录不存在: $(dirname "$log_path")"
|
||||
fi
|
||||
|
||||
# 验证网络配置
|
||||
log_debug "验证网络配置..."
|
||||
local subnet=$(grep "^SUBNET=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$subnet" ] && ! [[ "$subnet" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]]; then
|
||||
log_error "SUBNET 必须是有效的CIDR格式: $subnet"
|
||||
((errors++))
|
||||
fi
|
||||
|
||||
# 验证端口配置
|
||||
log_debug "验证端口配置..."
|
||||
local ports=("BACKEND_PORT" "FRONTEND_PORT" "DB_PORT")
|
||||
for port_var in "${ports[@]}"; do
|
||||
local port=$(grep "^${port_var}=" "$env_file" | cut -d'=' -f2)
|
||||
if [ -n "$port" ]; then
|
||||
if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
|
||||
log_error "$port_var 必须是1-65535之间的数字: $port"
|
||||
((errors++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 报告验证结果
|
||||
if [ $errors -eq 0 ]; then
|
||||
log_success "$env 环境配置验证通过"
|
||||
return 0
|
||||
else
|
||||
log_error "$env 环境配置验证失败,发现 $errors 个错误"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 切换环境配置
|
||||
switch_environment() {
|
||||
local env=$1
|
||||
local force=${2:-false}
|
||||
local dry_run=${3:-false}
|
||||
|
||||
log_info "切换到 $env 环境配置..."
|
||||
|
||||
# 验证目标环境配置
|
||||
if ! validate_env_config $env; then
|
||||
log_error "目标环境配置验证失败,无法切换"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local source_file=$(get_env_file $env)
|
||||
local target_file=$(get_active_env_file)
|
||||
|
||||
# 备份当前配置
|
||||
if [ -f "$target_file" ] && [ "$force" != "true" ]; then
|
||||
local backup_file="${target_file}.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
if [ "$dry_run" != "true" ]; then
|
||||
cp "$target_file" "$backup_file"
|
||||
log_info "当前配置已备份到: $backup_file"
|
||||
else
|
||||
log_info "[DRY-RUN] 将备份当前配置到: $backup_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 复制环境配置
|
||||
if [ "$dry_run" != "true" ]; then
|
||||
cp "$source_file" "$target_file"
|
||||
log_success "已切换到 $env 环境配置"
|
||||
|
||||
# 显示关键配置信息
|
||||
show_key_config "$env"
|
||||
else
|
||||
log_info "[DRY-RUN] 将复制 $source_file 到 $target_file"
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示环境配置信息
|
||||
show_env_config() {
|
||||
local env=$1
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
if ! check_env_file_exists $env; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "显示 $env 环境配置:"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# 显示关键配置项
|
||||
local key_vars=(
|
||||
"ENVIRONMENT"
|
||||
"COMPOSE_PROJECT_NAME"
|
||||
"DB_NAME"
|
||||
"DB_USER"
|
||||
"BACKEND_PORT"
|
||||
"FRONTEND_PORT"
|
||||
"API_BASE_URL"
|
||||
"LOG_LEVEL"
|
||||
"SPRING_PROFILES_ACTIVE"
|
||||
)
|
||||
|
||||
for var in "${key_vars[@]}"; do
|
||||
local value=$(grep "^${var}=" "$env_file" | cut -d'=' -f2-)
|
||||
if [ -n "$value" ]; then
|
||||
printf "%-25s: %s\n" "$var" "$value"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "----------------------------------------"
|
||||
}
|
||||
|
||||
# 显示关键配置信息
|
||||
show_key_config() {
|
||||
local env=$1
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
echo
|
||||
log_info "当前环境关键配置:"
|
||||
echo " 环境: $(grep "^ENVIRONMENT=" "$env_file" | cut -d'=' -f2)"
|
||||
echo " 项目: $(grep "^COMPOSE_PROJECT_NAME=" "$env_file" | cut -d'=' -f2)"
|
||||
echo " 前端端口: $(grep "^FRONTEND_PORT=" "$env_file" | cut -d'=' -f2)"
|
||||
echo " 后端端口: $(grep "^BACKEND_PORT=" "$env_file" | cut -d'=' -f2)"
|
||||
echo " 数据库: $(grep "^DB_NAME=" "$env_file" | cut -d'=' -f2)"
|
||||
echo " 日志级别: $(grep "^LOG_LEVEL=" "$env_file" | cut -d'=' -f2)"
|
||||
echo
|
||||
}
|
||||
|
||||
# 比较不同环境配置
|
||||
compare_environments() {
|
||||
local env1=$1
|
||||
local env2=$2
|
||||
|
||||
log_info "比较 $env1 和 $env2 环境配置..."
|
||||
|
||||
if ! check_env_file_exists $env1 || ! check_env_file_exists $env2; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local file1=$(get_env_file $env1)
|
||||
local file2=$(get_env_file $env2)
|
||||
|
||||
echo "=========================================="
|
||||
echo "配置差异 ($env1 vs $env2):"
|
||||
echo "=========================================="
|
||||
|
||||
# 使用diff命令比较文件
|
||||
if command -v diff &> /dev/null; then
|
||||
diff -u "$file1" "$file2" || true
|
||||
else
|
||||
log_warn "diff命令不可用,使用基本比较"
|
||||
|
||||
# 基本比较逻辑
|
||||
local vars1=$(grep "^[A-Z]" "$file1" | cut -d'=' -f1 | sort)
|
||||
local vars2=$(grep "^[A-Z]" "$file2" | cut -d'=' -f1 | sort)
|
||||
|
||||
# 找出差异变量
|
||||
local all_vars=$(echo -e "$vars1\n$vars2" | sort -u)
|
||||
|
||||
for var in $all_vars; do
|
||||
local val1=$(grep "^${var}=" "$file1" | cut -d'=' -f2- 2>/dev/null || echo "")
|
||||
local val2=$(grep "^${var}=" "$file2" | cut -d'=' -f2- 2>/dev/null || echo "")
|
||||
|
||||
if [ "$val1" != "$val2" ]; then
|
||||
printf "%-25s: %-20s | %s\n" "$var" "$val1" "$val2"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "=========================================="
|
||||
}
|
||||
|
||||
# 备份环境配置
|
||||
backup_config() {
|
||||
local timestamp=$(date +%Y%m%d_%H%M%S)
|
||||
local backup_dir="${DOCKER_DIR}/backups/config_${timestamp}"
|
||||
|
||||
log_info "备份环境配置到: $backup_dir"
|
||||
|
||||
mkdir -p "$backup_dir"
|
||||
|
||||
# 备份所有环境配置文件
|
||||
cp -r "$ENVIRONMENTS_DIR" "$backup_dir/"
|
||||
|
||||
# 备份当前活动配置
|
||||
if [ -f "$(get_active_env_file)" ]; then
|
||||
cp "$(get_active_env_file)" "$backup_dir/active.env"
|
||||
fi
|
||||
|
||||
# 创建备份信息文件
|
||||
cat > "$backup_dir/backup_info.txt" << EOF
|
||||
备份时间: $(date)
|
||||
备份内容: 环境配置文件
|
||||
备份路径: $backup_dir
|
||||
当前环境: $(grep "^ENVIRONMENT=" "$(get_active_env_file)" 2>/dev/null | cut -d'=' -f2 || echo "未知")
|
||||
EOF
|
||||
|
||||
log_success "配置备份完成: $backup_dir"
|
||||
}
|
||||
|
||||
# 恢复环境配置
|
||||
restore_config() {
|
||||
local backup_path=$1
|
||||
|
||||
if [ -z "$backup_path" ]; then
|
||||
log_error "请指定备份路径"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$backup_path" ]; then
|
||||
log_error "备份路径不存在: $backup_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "从备份恢复环境配置: $backup_path"
|
||||
|
||||
# 确认操作
|
||||
read -p "确认恢复配置? 这将覆盖当前配置 (y/N): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
# 恢复环境配置目录
|
||||
if [ -d "$backup_path/environments" ]; then
|
||||
cp -r "$backup_path/environments/"* "$ENVIRONMENTS_DIR/"
|
||||
log_info "环境配置文件已恢复"
|
||||
fi
|
||||
|
||||
# 恢复活动配置
|
||||
if [ -f "$backup_path/active.env" ]; then
|
||||
cp "$backup_path/active.env" "$(get_active_env_file)"
|
||||
log_info "活动配置文件已恢复"
|
||||
fi
|
||||
|
||||
log_success "配置恢复完成"
|
||||
else
|
||||
log_info "取消恢复操作"
|
||||
fi
|
||||
}
|
||||
|
||||
# 生成环境配置模板
|
||||
generate_template() {
|
||||
local env=$1
|
||||
local template_file="${ENVIRONMENTS_DIR}/.env.${env}.template"
|
||||
|
||||
log_info "生成 $env 环境配置模板: $template_file"
|
||||
|
||||
cat > "$template_file" << EOF
|
||||
# $env 环境配置模板
|
||||
# 复制此文件为 .env.$env 并根据实际环境修改配置
|
||||
|
||||
ENVIRONMENT=$env
|
||||
COMPOSE_PROJECT_NAME=anxin-$env
|
||||
|
||||
# 数据库配置 (Requirement 6.1)
|
||||
DB_HOST=anxin-mysql
|
||||
DB_PORT=3306
|
||||
DB_NAME=anxin_$env
|
||||
DB_USER=anxin_$env
|
||||
DB_PASSWORD=CHANGE_ME_PASSWORD
|
||||
MYSQL_ROOT_PASSWORD=CHANGE_ME_ROOT_PASSWORD
|
||||
|
||||
# 后端服务配置
|
||||
BACKEND_PORT=8080
|
||||
SPRING_PROFILES_ACTIVE=$env
|
||||
JAVA_OPTS=-Xms512m -Xmx1024m
|
||||
|
||||
# 前端服务配置 (Requirement 6.2)
|
||||
FRONTEND_PORT=80
|
||||
API_BASE_URL=http://localhost:8080
|
||||
|
||||
# 容器资源配置 (Requirement 6.3)
|
||||
FRONTEND_MEMORY_LIMIT=256
|
||||
BACKEND_MEMORY_LIMIT=1024
|
||||
DATABASE_MEMORY_LIMIT=512
|
||||
|
||||
FRONTEND_CPU_LIMIT=0.5
|
||||
BACKEND_CPU_LIMIT=1.0
|
||||
DATABASE_CPU_LIMIT=0.5
|
||||
|
||||
# 日志配置 (Requirement 6.4)
|
||||
LOG_LEVEL=INFO
|
||||
LOG_PATH=./logs/$env
|
||||
LOG_MAX_SIZE=100MB
|
||||
LOG_MAX_FILES=10
|
||||
|
||||
# 网络配置
|
||||
NETWORK_NAME=anxin-$env-network
|
||||
SUBNET=172.20.0.0/16
|
||||
|
||||
# 卷配置
|
||||
MYSQL_DATA_PATH=./data/$env/mysql
|
||||
LOG_DATA_PATH=./data/$env/logs
|
||||
CONFIG_DATA_PATH=./data/$env/configs
|
||||
EOF
|
||||
|
||||
log_success "模板生成完成: $template_file"
|
||||
}
|
||||
|
||||
# 检查配置完整性
|
||||
check_config_integrity() {
|
||||
log_info "检查所有环境配置完整性..."
|
||||
|
||||
local environments=("development" "staging" "production")
|
||||
local total_errors=0
|
||||
|
||||
for env in "${environments[@]}"; do
|
||||
echo
|
||||
if validate_env_config $env; then
|
||||
log_success "$env 环境配置完整"
|
||||
else
|
||||
((total_errors++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
if [ $total_errors -eq 0 ]; then
|
||||
log_success "所有环境配置检查通过"
|
||||
return 0
|
||||
else
|
||||
log_error "发现 $total_errors 个环境配置问题"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 列出所有可用环境
|
||||
list_environments() {
|
||||
log_info "可用环境配置:"
|
||||
|
||||
for env_file in "$ENVIRONMENTS_DIR"/.env.*; do
|
||||
if [ -f "$env_file" ] && [[ ! "$env_file" =~ \.template$ ]] && [[ ! "$env_file" =~ \.example$ ]]; then
|
||||
local env_name=$(basename "$env_file" | sed 's/^\.env\.//')
|
||||
local env_desc=""
|
||||
|
||||
case $env_name in
|
||||
development)
|
||||
env_desc="开发环境"
|
||||
;;
|
||||
staging)
|
||||
env_desc="测试环境"
|
||||
;;
|
||||
production)
|
||||
env_desc="生产环境"
|
||||
;;
|
||||
*)
|
||||
env_desc="自定义环境"
|
||||
;;
|
||||
esac
|
||||
|
||||
printf " %-12s - %s\n" "$env_name" "$env_desc"
|
||||
|
||||
# 显示关键信息
|
||||
if [ -f "$env_file" ]; then
|
||||
local project=$(grep "^COMPOSE_PROJECT_NAME=" "$env_file" | cut -d'=' -f2)
|
||||
local frontend_port=$(grep "^FRONTEND_PORT=" "$env_file" | cut -d'=' -f2)
|
||||
local backend_port=$(grep "^BACKEND_PORT=" "$env_file" | cut -d'=' -f2)
|
||||
printf " 项目: %s, 前端: %s, 后端: %s\n" "$project" "$frontend_port" "$backend_port"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo
|
||||
|
||||
# 显示当前活动环境
|
||||
local active_file=$(get_active_env_file)
|
||||
if [ -f "$active_file" ]; then
|
||||
local current_env=$(grep "^ENVIRONMENT=" "$active_file" | cut -d'=' -f2)
|
||||
log_info "当前活动环境: $current_env"
|
||||
else
|
||||
log_warn "未找到活动环境配置"
|
||||
fi
|
||||
}
|
||||
|
||||
# 解析命令行参数
|
||||
parse_args() {
|
||||
FORCE=false
|
||||
VERBOSE=false
|
||||
DRY_RUN=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--force)
|
||||
FORCE=true
|
||||
shift
|
||||
;;
|
||||
--verbose)
|
||||
VERBOSE=true
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
COMMAND=$1
|
||||
ENVIRONMENT=$2
|
||||
ENVIRONMENT2=$3
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
case $COMMAND in
|
||||
validate)
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$ENVIRONMENT")
|
||||
validate_env_config "$env"
|
||||
;;
|
||||
switch)
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$ENVIRONMENT")
|
||||
switch_environment "$env" "$FORCE" "$DRY_RUN"
|
||||
;;
|
||||
show)
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$ENVIRONMENT")
|
||||
show_env_config "$env"
|
||||
;;
|
||||
compare)
|
||||
if [ -z "$ENVIRONMENT" ] || [ -z "$ENVIRONMENT2" ]; then
|
||||
log_error "请指定两个环境进行比较"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env1=$(validate_environment "$ENVIRONMENT")
|
||||
env2=$(validate_environment "$ENVIRONMENT2")
|
||||
compare_environments "$env1" "$env2"
|
||||
;;
|
||||
backup)
|
||||
backup_config
|
||||
;;
|
||||
restore)
|
||||
restore_config "$ENVIRONMENT"
|
||||
;;
|
||||
template)
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$ENVIRONMENT")
|
||||
generate_template "$env"
|
||||
;;
|
||||
check)
|
||||
check_config_integrity
|
||||
;;
|
||||
list)
|
||||
list_environments
|
||||
;;
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
log_error "未知命令: $COMMAND"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 检查必要的目录
|
||||
if [ ! -d "$ENVIRONMENTS_DIR" ]; then
|
||||
log_error "环境配置目录不存在: $ENVIRONMENTS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
346
docker/scripts/env-manager.bat
Normal file
346
docker/scripts/env-manager.bat
Normal file
@ -0,0 +1,346 @@
|
||||
@echo off
|
||||
REM 环境管理脚本 - Windows版本
|
||||
REM 用于切换不同环境的Docker Compose配置
|
||||
REM Requirements: 5.3, 6.5
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM 设置脚本目录
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
set "DOCKER_DIR=%SCRIPT_DIR%.."
|
||||
set "PROJECT_ROOT=%DOCKER_DIR%\.."
|
||||
|
||||
REM 颜色定义 (Windows不支持颜色,使用文本标识)
|
||||
set "INFO=[INFO]"
|
||||
set "WARN=[WARN]"
|
||||
set "ERROR=[ERROR]"
|
||||
set "DEBUG=[DEBUG]"
|
||||
|
||||
REM 显示帮助信息
|
||||
:show_help
|
||||
echo 环境管理脚本 - 若依框架Docker部署 (Windows版本)
|
||||
echo.
|
||||
echo 用法: %~nx0 [命令] [环境]
|
||||
echo.
|
||||
echo 命令:
|
||||
echo deploy 部署指定环境
|
||||
echo stop 停止指定环境
|
||||
echo restart 重启指定环境
|
||||
echo status 查看指定环境状态
|
||||
echo logs 查看指定环境日志
|
||||
echo clean 清理指定环境
|
||||
echo backup 备份指定环境数据
|
||||
echo list 列出所有可用环境
|
||||
echo help 显示此帮助信息
|
||||
echo.
|
||||
echo 环境:
|
||||
echo development (dev) 开发环境
|
||||
echo staging (stage) 测试环境
|
||||
echo production (prod) 生产环境
|
||||
echo.
|
||||
echo 示例:
|
||||
echo %~nx0 deploy development # 部署开发环境
|
||||
echo %~nx0 stop prod # 停止生产环境
|
||||
echo %~nx0 logs staging # 查看测试环境日志
|
||||
echo %~nx0 status dev # 查看开发环境状态
|
||||
echo.
|
||||
goto :eof
|
||||
|
||||
REM 验证环境参数
|
||||
:validate_environment
|
||||
set "input_env=%1"
|
||||
if "%input_env%"=="development" set "validated_env=development" & goto :eof
|
||||
if "%input_env%"=="dev" set "validated_env=development" & goto :eof
|
||||
if "%input_env%"=="staging" set "validated_env=staging" & goto :eof
|
||||
if "%input_env%"=="stage" set "validated_env=staging" & goto :eof
|
||||
if "%input_env%"=="production" set "validated_env=production" & goto :eof
|
||||
if "%input_env%"=="prod" set "validated_env=production" & goto :eof
|
||||
|
||||
echo %ERROR% 无效的环境: %input_env%
|
||||
echo %INFO% 支持的环境: development, staging, production
|
||||
exit /b 1
|
||||
|
||||
REM 获取compose文件路径
|
||||
:get_compose_file
|
||||
set "compose_file=%DOCKER_DIR%\docker-compose.%1.yml"
|
||||
goto :eof
|
||||
|
||||
REM 获取环境配置文件路径
|
||||
:get_env_file
|
||||
set "env_file=%DOCKER_DIR%\environments\.env.%1"
|
||||
goto :eof
|
||||
|
||||
REM 检查文件是否存在
|
||||
:check_files
|
||||
call :get_compose_file %1
|
||||
call :get_env_file %1
|
||||
|
||||
if not exist "%compose_file%" (
|
||||
echo %ERROR% Compose文件不存在: %compose_file%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "%env_file%" (
|
||||
echo %ERROR% 环境配置文件不存在: %env_file%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo %DEBUG% 文件检查通过: %compose_file%, %env_file%
|
||||
goto :eof
|
||||
|
||||
REM 创建数据目录
|
||||
:create_directories
|
||||
set "env=%1"
|
||||
echo %INFO% 创建数据目录...
|
||||
|
||||
REM 创建基础目录结构
|
||||
if not exist "%DOCKER_DIR%\data\%env%" mkdir "%DOCKER_DIR%\data\%env%"
|
||||
if not exist "%DOCKER_DIR%\data\%env%\mysql" mkdir "%DOCKER_DIR%\data\%env%\mysql"
|
||||
if not exist "%DOCKER_DIR%\data\%env%\mysql-logs" mkdir "%DOCKER_DIR%\data\%env%\mysql-logs"
|
||||
if not exist "%DOCKER_DIR%\data\%env%\backend-logs" mkdir "%DOCKER_DIR%\data\%env%\backend-logs"
|
||||
if not exist "%DOCKER_DIR%\data\%env%\uploads" mkdir "%DOCKER_DIR%\data\%env%\uploads"
|
||||
if not exist "%DOCKER_DIR%\data\%env%\nginx-logs" mkdir "%DOCKER_DIR%\data\%env%\nginx-logs"
|
||||
|
||||
if not "%env%"=="development" (
|
||||
if not exist "%DOCKER_DIR%\data\%env%\backups" mkdir "%DOCKER_DIR%\data\%env%\backups"
|
||||
)
|
||||
|
||||
goto :eof
|
||||
|
||||
REM 部署环境
|
||||
:deploy_environment
|
||||
set "env=%1"
|
||||
echo %INFO% 开始部署 %env% 环境...
|
||||
|
||||
call :check_files %env%
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
call :create_directories %env%
|
||||
|
||||
echo %INFO% 启动Docker Compose服务...
|
||||
cd /d "%DOCKER_DIR%"
|
||||
docker-compose -f "%compose_file%" --env-file "%env_file%" up -d
|
||||
|
||||
if errorlevel 1 (
|
||||
echo %ERROR% Docker Compose启动失败
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo %INFO% 等待服务启动...
|
||||
timeout /t 10 /nobreak >nul
|
||||
|
||||
call :check_services %env%
|
||||
|
||||
echo %INFO% %env% 环境部署完成!
|
||||
goto :eof
|
||||
|
||||
REM 停止环境
|
||||
:stop_environment
|
||||
set "env=%1"
|
||||
echo %INFO% 停止 %env% 环境...
|
||||
|
||||
call :get_compose_file %env%
|
||||
call :get_env_file %env%
|
||||
|
||||
cd /d "%DOCKER_DIR%"
|
||||
docker-compose -f "%compose_file%" --env-file "%env_file%" down
|
||||
|
||||
echo %INFO% %env% 环境已停止
|
||||
goto :eof
|
||||
|
||||
REM 重启环境
|
||||
:restart_environment
|
||||
set "env=%1"
|
||||
echo %INFO% 重启 %env% 环境...
|
||||
|
||||
call :stop_environment %env%
|
||||
timeout /t 5 /nobreak >nul
|
||||
call :deploy_environment %env%
|
||||
goto :eof
|
||||
|
||||
REM 查看环境状态
|
||||
:check_services
|
||||
set "env=%1"
|
||||
echo %INFO% 检查 %env% 环境服务状态...
|
||||
|
||||
call :get_compose_file %env%
|
||||
call :get_env_file %env%
|
||||
|
||||
cd /d "%DOCKER_DIR%"
|
||||
docker-compose -f "%compose_file%" --env-file "%env_file%" ps
|
||||
|
||||
echo %INFO% 执行健康检查...
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | findstr anxin-%env%
|
||||
goto :eof
|
||||
|
||||
REM 查看日志
|
||||
:view_logs
|
||||
set "env=%1"
|
||||
set "service=%2"
|
||||
|
||||
call :get_compose_file %env%
|
||||
call :get_env_file %env%
|
||||
|
||||
cd /d "%DOCKER_DIR%"
|
||||
|
||||
if "%service%"=="" (
|
||||
echo %INFO% 查看 %env% 环境所有服务日志...
|
||||
docker-compose -f "%compose_file%" --env-file "%env_file%" logs -f
|
||||
) else (
|
||||
echo %INFO% 查看 %env% 环境 %service% 服务日志...
|
||||
docker-compose -f "%compose_file%" --env-file "%env_file%" logs -f %service%
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM 清理环境
|
||||
:clean_environment
|
||||
set "env=%1"
|
||||
echo %WARN% 即将清理 %env% 环境 (包括数据卷)...
|
||||
set /p "confirm=确认继续? (y/N): "
|
||||
|
||||
if /i "%confirm%"=="y" (
|
||||
echo %INFO% 清理 %env% 环境...
|
||||
call :get_compose_file %env%
|
||||
call :get_env_file %env%
|
||||
cd /d "%DOCKER_DIR%"
|
||||
docker-compose -f "%compose_file%" --env-file "%env_file%" down -v --remove-orphans
|
||||
docker system prune -f
|
||||
echo %INFO% %env% 环境清理完成
|
||||
) else (
|
||||
echo %INFO% 取消清理操作
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM 备份环境数据
|
||||
:backup_environment
|
||||
set "env=%1"
|
||||
echo %INFO% 备份 %env% 环境数据...
|
||||
|
||||
if "%env%"=="production" (
|
||||
docker exec anxin-mysql-prod /backup.sh
|
||||
) else if "%env%"=="staging" (
|
||||
docker exec anxin-mysql-staging /backup.sh
|
||||
) else if "%env%"=="development" (
|
||||
echo %WARN% 开发环境通常不需要备份
|
||||
)
|
||||
|
||||
echo %INFO% %env% 环境数据备份完成
|
||||
goto :eof
|
||||
|
||||
REM 列出所有环境
|
||||
:list_environments
|
||||
echo %INFO% 可用环境:
|
||||
echo development (dev) - 开发环境
|
||||
echo staging (stage) - 测试环境
|
||||
echo production (prod) - 生产环境
|
||||
echo.
|
||||
|
||||
echo %INFO% 当前运行的容器:
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | findstr anxin
|
||||
if errorlevel 1 echo 无运行中的容器
|
||||
goto :eof
|
||||
|
||||
REM 检查Docker是否安装
|
||||
:check_docker
|
||||
docker --version >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo %ERROR% Docker未安装或不在PATH中
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
docker-compose --version >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo %ERROR% Docker Compose未安装或不在PATH中
|
||||
exit /b 1
|
||||
)
|
||||
goto :eof
|
||||
|
||||
REM 主函数
|
||||
:main
|
||||
call :check_docker
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
set "command=%1"
|
||||
set "environment=%2"
|
||||
|
||||
if "%command%"=="deploy" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :deploy_environment !validated_env!
|
||||
) else if "%command%"=="stop" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :stop_environment !validated_env!
|
||||
) else if "%command%"=="restart" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :restart_environment !validated_env!
|
||||
) else if "%command%"=="status" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :check_services !validated_env!
|
||||
) else if "%command%"=="logs" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :view_logs !validated_env! %3
|
||||
) else if "%command%"=="clean" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :clean_environment !validated_env!
|
||||
) else if "%command%"=="backup" (
|
||||
if "%environment%"=="" (
|
||||
echo %ERROR% 请指定环境
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
call :validate_environment %environment%
|
||||
if errorlevel 1 exit /b 1
|
||||
call :backup_environment !validated_env!
|
||||
) else if "%command%"=="list" (
|
||||
call :list_environments
|
||||
) else if "%command%"=="help" (
|
||||
call :show_help
|
||||
) else if "%command%"=="--help" (
|
||||
call :show_help
|
||||
) else if "%command%"=="-h" (
|
||||
call :show_help
|
||||
) else (
|
||||
echo %ERROR% 未知命令: %command%
|
||||
call :show_help
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
goto :eof
|
||||
|
||||
REM 执行主函数
|
||||
call :main %*
|
||||
379
docker/scripts/env-manager.sh
Normal file
379
docker/scripts/env-manager.sh
Normal file
@ -0,0 +1,379 @@
|
||||
#!/bin/bash
|
||||
# 环境管理脚本 - 用于切换不同环境的Docker Compose配置
|
||||
# Requirements: 5.3, 6.5
|
||||
|
||||
set -e
|
||||
|
||||
# 脚本目录
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DOCKER_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
PROJECT_ROOT="$(dirname "$DOCKER_DIR")"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_debug() {
|
||||
echo -e "${BLUE}[DEBUG]${NC} $1"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << EOF
|
||||
环境管理脚本 - 若依框架Docker部署
|
||||
|
||||
用法: $0 [命令] [环境]
|
||||
|
||||
命令:
|
||||
deploy 部署指定环境
|
||||
stop 停止指定环境
|
||||
restart 重启指定环境
|
||||
status 查看指定环境状态
|
||||
logs 查看指定环境日志
|
||||
clean 清理指定环境
|
||||
backup 备份指定环境数据
|
||||
list 列出所有可用环境
|
||||
help 显示此帮助信息
|
||||
|
||||
环境:
|
||||
development (dev) 开发环境
|
||||
staging (stage) 测试环境
|
||||
production (prod) 生产环境
|
||||
|
||||
示例:
|
||||
$0 deploy development # 部署开发环境
|
||||
$0 stop prod # 停止生产环境
|
||||
$0 logs staging # 查看测试环境日志
|
||||
$0 status dev # 查看开发环境状态
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# 验证环境参数
|
||||
validate_environment() {
|
||||
local env=$1
|
||||
case $env in
|
||||
development|dev)
|
||||
echo "development"
|
||||
;;
|
||||
staging|stage)
|
||||
echo "staging"
|
||||
;;
|
||||
production|prod)
|
||||
echo "production"
|
||||
;;
|
||||
*)
|
||||
log_error "无效的环境: $env"
|
||||
log_info "支持的环境: development, staging, production"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 获取compose文件路径
|
||||
get_compose_file() {
|
||||
local env=$1
|
||||
echo "${DOCKER_DIR}/docker-compose.${env}.yml"
|
||||
}
|
||||
|
||||
# 获取环境配置文件路径
|
||||
get_env_file() {
|
||||
local env=$1
|
||||
echo "${DOCKER_DIR}/environments/.env.${env}"
|
||||
}
|
||||
|
||||
# 检查文件是否存在
|
||||
check_files() {
|
||||
local env=$1
|
||||
local compose_file=$(get_compose_file $env)
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
if [ ! -f "$compose_file" ]; then
|
||||
log_error "Compose文件不存在: $compose_file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$env_file" ]; then
|
||||
log_error "环境配置文件不存在: $env_file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_debug "文件检查通过: $compose_file, $env_file"
|
||||
}
|
||||
|
||||
# 部署环境
|
||||
deploy_environment() {
|
||||
local env=$1
|
||||
local compose_file=$(get_compose_file $env)
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
log_info "开始部署 $env 环境..."
|
||||
|
||||
# 检查文件
|
||||
check_files $env
|
||||
|
||||
# 创建必要的目录
|
||||
log_info "创建数据目录..."
|
||||
source "$env_file"
|
||||
mkdir -p "${MYSQL_DATA_PATH:-./data/$env/mysql}"
|
||||
mkdir -p "${MYSQL_LOG_PATH:-./data/$env/mysql-logs}"
|
||||
mkdir -p "${BACKEND_LOG_PATH:-./data/$env/backend-logs}"
|
||||
mkdir -p "${BACKEND_UPLOAD_PATH:-./data/$env/uploads}"
|
||||
mkdir -p "${FRONTEND_LOG_PATH:-./data/$env/nginx-logs}"
|
||||
|
||||
if [ "$env" != "development" ]; then
|
||||
mkdir -p "${BACKUP_DATA_PATH:-./data/$env/backups}"
|
||||
fi
|
||||
|
||||
# 部署服务
|
||||
log_info "启动Docker Compose服务..."
|
||||
cd "$DOCKER_DIR"
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" up -d
|
||||
|
||||
# 等待服务启动
|
||||
log_info "等待服务启动..."
|
||||
sleep 10
|
||||
|
||||
# 检查服务状态
|
||||
check_services $env
|
||||
|
||||
log_info "$env 环境部署完成!"
|
||||
}
|
||||
|
||||
# 停止环境
|
||||
stop_environment() {
|
||||
local env=$1
|
||||
local compose_file=$(get_compose_file $env)
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
log_info "停止 $env 环境..."
|
||||
|
||||
cd "$DOCKER_DIR"
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" down
|
||||
|
||||
log_info "$env 环境已停止"
|
||||
}
|
||||
|
||||
# 重启环境
|
||||
restart_environment() {
|
||||
local env=$1
|
||||
|
||||
log_info "重启 $env 环境..."
|
||||
stop_environment $env
|
||||
sleep 5
|
||||
deploy_environment $env
|
||||
}
|
||||
|
||||
# 查看环境状态
|
||||
check_services() {
|
||||
local env=$1
|
||||
local compose_file=$(get_compose_file $env)
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
log_info "检查 $env 环境服务状态..."
|
||||
|
||||
cd "$DOCKER_DIR"
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" ps
|
||||
|
||||
# 健康检查
|
||||
log_info "执行健康检查..."
|
||||
local services=("anxin-mysql-${env}" "anxin-backend-${env}" "anxin-frontend-${env}")
|
||||
|
||||
for service in "${services[@]}"; do
|
||||
if docker ps --format "table {{.Names}}" | grep -q "$service"; then
|
||||
local health=$(docker inspect --format='{{.State.Health.Status}}' "$service" 2>/dev/null || echo "no-healthcheck")
|
||||
if [ "$health" = "healthy" ] || [ "$health" = "no-healthcheck" ]; then
|
||||
log_info "✓ $service: 运行正常"
|
||||
else
|
||||
log_warn "⚠ $service: 健康检查失败 ($health)"
|
||||
fi
|
||||
else
|
||||
log_error "✗ $service: 未运行"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 查看日志
|
||||
view_logs() {
|
||||
local env=$1
|
||||
local service=$2
|
||||
local compose_file=$(get_compose_file $env)
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
cd "$DOCKER_DIR"
|
||||
|
||||
if [ -n "$service" ]; then
|
||||
log_info "查看 $env 环境 $service 服务日志..."
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" logs -f "$service"
|
||||
else
|
||||
log_info "查看 $env 环境所有服务日志..."
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" logs -f
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理环境
|
||||
clean_environment() {
|
||||
local env=$1
|
||||
local compose_file=$(get_compose_file $env)
|
||||
local env_file=$(get_env_file $env)
|
||||
|
||||
log_warn "即将清理 $env 环境 (包括数据卷)..."
|
||||
read -p "确认继续? (y/N): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "清理 $env 环境..."
|
||||
cd "$DOCKER_DIR"
|
||||
docker-compose -f "$compose_file" --env-file "$env_file" down -v --remove-orphans
|
||||
docker system prune -f
|
||||
log_info "$env 环境清理完成"
|
||||
else
|
||||
log_info "取消清理操作"
|
||||
fi
|
||||
}
|
||||
|
||||
# 备份环境数据
|
||||
backup_environment() {
|
||||
local env=$1
|
||||
|
||||
log_info "备份 $env 环境数据..."
|
||||
|
||||
case $env in
|
||||
production)
|
||||
docker exec anxin-mysql-prod /backup.sh
|
||||
;;
|
||||
staging)
|
||||
docker exec anxin-mysql-staging /backup.sh
|
||||
;;
|
||||
development)
|
||||
log_warn "开发环境通常不需要备份"
|
||||
;;
|
||||
esac
|
||||
|
||||
log_info "$env 环境数据备份完成"
|
||||
}
|
||||
|
||||
# 列出所有环境
|
||||
list_environments() {
|
||||
log_info "可用环境:"
|
||||
echo " development (dev) - 开发环境"
|
||||
echo " staging (stage) - 测试环境"
|
||||
echo " production (prod) - 生产环境"
|
||||
echo
|
||||
|
||||
log_info "当前运行的容器:"
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep anxin || echo " 无运行中的容器"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local command=$1
|
||||
local environment=$2
|
||||
|
||||
case $command in
|
||||
deploy)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
deploy_environment "$env"
|
||||
;;
|
||||
stop)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
stop_environment "$env"
|
||||
;;
|
||||
restart)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
restart_environment "$env"
|
||||
;;
|
||||
status)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
check_services "$env"
|
||||
;;
|
||||
logs)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
view_logs "$env" "$3"
|
||||
;;
|
||||
clean)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
clean_environment "$env"
|
||||
;;
|
||||
backup)
|
||||
if [ -z "$environment" ]; then
|
||||
log_error "请指定环境"
|
||||
show_help
|
||||
exit 1
|
||||
fi
|
||||
env=$(validate_environment "$environment")
|
||||
backup_environment "$env"
|
||||
;;
|
||||
list)
|
||||
list_environments
|
||||
;;
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
log_error "未知命令: $command"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 检查Docker是否安装
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose未安装或不在PATH中"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
10
docker/scripts/set-permissions.bat
Normal file
10
docker/scripts/set-permissions.bat
Normal file
@ -0,0 +1,10 @@
|
||||
@echo off
|
||||
REM 设置脚本文件权限 (Windows环境)
|
||||
REM 在Linux/Unix环境中运行: chmod +x *.sh
|
||||
|
||||
echo Setting executable permissions for backup scripts...
|
||||
echo Note: On Windows, this is for documentation only.
|
||||
echo On Linux/Unix systems, run: chmod +x docker/scripts/*.sh
|
||||
|
||||
echo Backup scripts are ready for use.
|
||||
pause
|
||||
254
docker/scripts/setup-env.bat
Normal file
254
docker/scripts/setup-env.bat
Normal file
@ -0,0 +1,254 @@
|
||||
@echo off
|
||||
REM 环境设置脚本 (Windows版本)
|
||||
REM 用于初始化Docker部署环境和配置文件
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM 设置颜色代码
|
||||
set "RED=[91m"
|
||||
set "GREEN=[92m"
|
||||
set "YELLOW=[93m"
|
||||
set "BLUE=[94m"
|
||||
set "NC=[0m"
|
||||
|
||||
REM 日志函数
|
||||
:log_info
|
||||
echo %BLUE%[INFO]%NC% %~1
|
||||
goto :eof
|
||||
|
||||
:log_success
|
||||
echo %GREEN%[SUCCESS]%NC% %~1
|
||||
goto :eof
|
||||
|
||||
:log_warning
|
||||
echo %YELLOW%[WARNING]%NC% %~1
|
||||
goto :eof
|
||||
|
||||
:log_error
|
||||
echo %RED%[ERROR]%NC% %~1
|
||||
goto :eof
|
||||
|
||||
REM 检查必要的命令
|
||||
:check_requirements
|
||||
call :log_info "检查系统要求..."
|
||||
|
||||
docker --version >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
call :log_error "Docker 未安装,请先安装 Docker Desktop"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
docker-compose --version >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
call :log_error "Docker Compose 未安装,请先安装 Docker Compose"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
call :log_success "系统要求检查通过"
|
||||
goto :eof
|
||||
|
||||
REM 创建必要的目录
|
||||
:create_directories
|
||||
call :log_info "创建必要的目录结构..."
|
||||
|
||||
REM 数据目录
|
||||
if not exist "data" mkdir data
|
||||
if not exist "data\mysql" mkdir data\mysql
|
||||
if not exist "data\logs" mkdir data\logs
|
||||
if not exist "data\configs" mkdir data\configs
|
||||
|
||||
if not exist "data\dev" mkdir data\dev
|
||||
if not exist "data\dev\mysql" mkdir data\dev\mysql
|
||||
if not exist "data\dev\logs" mkdir data\dev\logs
|
||||
if not exist "data\dev\configs" mkdir data\dev\configs
|
||||
|
||||
if not exist "data\staging" mkdir data\staging
|
||||
if not exist "data\staging\mysql" mkdir data\staging\mysql
|
||||
if not exist "data\staging\logs" mkdir data\staging\logs
|
||||
if not exist "data\staging\configs" mkdir data\staging\configs
|
||||
|
||||
if not exist "data\prod" mkdir data\prod
|
||||
if not exist "data\prod\mysql" mkdir data\prod\mysql
|
||||
if not exist "data\prod\logs" mkdir data\prod\logs
|
||||
if not exist "data\prod\configs" mkdir data\prod\configs
|
||||
|
||||
REM 日志目录
|
||||
if not exist "logs" mkdir logs
|
||||
if not exist "logs\dev" mkdir logs\dev
|
||||
if not exist "logs\staging" mkdir logs\staging
|
||||
if not exist "logs\prod" mkdir logs\prod
|
||||
|
||||
call :log_success "目录结构创建完成"
|
||||
goto :eof
|
||||
|
||||
REM 设置环境配置
|
||||
:setup_environment
|
||||
set env=%~1
|
||||
if "%env%"=="" set env=development
|
||||
|
||||
call :log_info "设置 %env% 环境配置..."
|
||||
|
||||
REM 检查环境配置文件是否存在
|
||||
if not exist "environments\.env.%env%" (
|
||||
call :log_error "环境配置文件 .env.%env% 不存在"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 复制环境配置文件
|
||||
copy "environments\.env.%env%" ".env" >nul
|
||||
|
||||
REM 复制Docker Compose配置
|
||||
copy "docker-compose.yml.template" "docker-compose.yml" >nul
|
||||
|
||||
REM 复制配置文件模板
|
||||
copy "configs\nginx.conf.template" "configs\nginx.conf" >nul
|
||||
copy "configs\application-docker.yml.template" "configs\application-docker.yml" >nul
|
||||
copy "configs\my.cnf.template" "configs\my.cnf" >nul
|
||||
|
||||
call :log_success "%env% 环境配置设置完成"
|
||||
goto :eof
|
||||
|
||||
REM 验证配置
|
||||
:validate_config
|
||||
call :log_info "验证配置文件..."
|
||||
|
||||
REM 检查 .env 文件
|
||||
if not exist ".env" (
|
||||
call :log_error ".env 文件不存在,请先运行环境设置"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 检查 docker-compose.yml 文件
|
||||
if not exist "docker-compose.yml" (
|
||||
call :log_error "docker-compose.yml 文件不存在"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 验证 Docker Compose 配置语法
|
||||
docker-compose config >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
call :log_error "Docker Compose 配置文件语法错误"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
call :log_success "配置文件验证通过"
|
||||
goto :eof
|
||||
|
||||
REM 显示帮助信息
|
||||
:show_help
|
||||
echo 用法: %~nx0 [选项] [环境]
|
||||
echo.
|
||||
echo 选项:
|
||||
echo -h, --help 显示此帮助信息
|
||||
echo -c, --check 仅检查系统要求
|
||||
echo -v, --validate 仅验证配置
|
||||
echo.
|
||||
echo 环境:
|
||||
echo development 开发环境 (默认)
|
||||
echo staging 测试环境
|
||||
echo production 生产环境
|
||||
echo.
|
||||
echo 示例:
|
||||
echo %~nx0 # 设置开发环境
|
||||
echo %~nx0 production # 设置生产环境
|
||||
echo %~nx0 --check # 仅检查系统要求
|
||||
goto :eof
|
||||
|
||||
REM 主函数
|
||||
:main
|
||||
set environment=development
|
||||
set check_only=false
|
||||
set validate_only=false
|
||||
|
||||
REM 解析命令行参数
|
||||
:parse_args
|
||||
if "%~1"=="" goto :start_setup
|
||||
if "%~1"=="-h" goto :show_help_and_exit
|
||||
if "%~1"=="--help" goto :show_help_and_exit
|
||||
if "%~1"=="-c" (
|
||||
set check_only=true
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="--check" (
|
||||
set check_only=true
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="-v" (
|
||||
set validate_only=true
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="--validate" (
|
||||
set validate_only=true
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="development" (
|
||||
set environment=%~1
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="staging" (
|
||||
set environment=%~1
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
if "%~1"=="production" (
|
||||
set environment=%~1
|
||||
shift
|
||||
goto :parse_args
|
||||
)
|
||||
|
||||
call :log_error "未知参数: %~1"
|
||||
call :show_help
|
||||
exit /b 1
|
||||
|
||||
:show_help_and_exit
|
||||
call :show_help
|
||||
exit /b 0
|
||||
|
||||
:start_setup
|
||||
REM 切换到docker目录
|
||||
cd /d "%~dp0\.."
|
||||
|
||||
call :log_info "开始设置Docker部署环境..."
|
||||
|
||||
REM 检查系统要求
|
||||
call :check_requirements
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
if "%check_only%"=="true" (
|
||||
call :log_success "系统要求检查完成"
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
if "%validate_only%"=="true" (
|
||||
call :validate_config
|
||||
if errorlevel 1 exit /b 1
|
||||
call :log_success "配置验证完成"
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
REM 创建目录结构
|
||||
call :create_directories
|
||||
|
||||
REM 设置环境配置
|
||||
call :setup_environment "%environment%"
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
REM 验证配置
|
||||
call :validate_config
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
call :log_success "Docker部署环境设置完成!"
|
||||
call :log_info "下一步:"
|
||||
call :log_info "1. 检查并修改 .env 文件中的配置"
|
||||
call :log_info "2. 运行 'scripts\build.bat' 构建镜像"
|
||||
call :log_info "3. 运行 'scripts\deploy.bat start' 启动服务"
|
||||
|
||||
goto :eof
|
||||
|
||||
REM 执行主函数
|
||||
call :main %*
|
||||
220
docker/scripts/setup-env.sh
Normal file
220
docker/scripts/setup-env.sh
Normal file
@ -0,0 +1,220 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 环境设置脚本
|
||||
# 用于初始化Docker部署环境和配置文件
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查必要的命令
|
||||
check_requirements() {
|
||||
log_info "检查系统要求..."
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker 未安装,请先安装 Docker"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose 未安装,请先安装 Docker Compose"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "系统要求检查通过"
|
||||
}
|
||||
|
||||
# 创建必要的目录
|
||||
create_directories() {
|
||||
log_info "创建必要的目录结构..."
|
||||
|
||||
# 数据目录
|
||||
mkdir -p data/{mysql,logs,configs}
|
||||
mkdir -p data/{dev,staging,prod}/{mysql,logs,configs}
|
||||
|
||||
# 日志目录
|
||||
mkdir -p logs/{dev,staging,prod}
|
||||
|
||||
log_success "目录结构创建完成"
|
||||
}
|
||||
|
||||
# 设置环境配置
|
||||
setup_environment() {
|
||||
local env=${1:-development}
|
||||
|
||||
log_info "设置 ${env} 环境配置..."
|
||||
|
||||
# 检查环境配置文件是否存在
|
||||
if [[ ! -f "environments/.env.${env}" ]]; then
|
||||
log_error "环境配置文件 .env.${env} 不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 复制环境配置文件
|
||||
cp "environments/.env.${env}" .env
|
||||
|
||||
# 复制Docker Compose配置
|
||||
cp docker-compose.yml.template docker-compose.yml
|
||||
|
||||
# 复制配置文件模板
|
||||
cp configs/nginx.conf.template configs/nginx.conf
|
||||
cp configs/application-docker.yml.template configs/application-docker.yml
|
||||
cp configs/my.cnf.template configs/my.cnf
|
||||
|
||||
log_success "${env} 环境配置设置完成"
|
||||
}
|
||||
|
||||
# 设置文件权限
|
||||
set_permissions() {
|
||||
log_info "设置文件权限..."
|
||||
|
||||
# 设置脚本执行权限
|
||||
chmod +x scripts/*.sh
|
||||
|
||||
# 设置数据目录权限
|
||||
chmod -R 755 data/
|
||||
chmod -R 755 logs/
|
||||
|
||||
log_success "文件权限设置完成"
|
||||
}
|
||||
|
||||
# 验证配置
|
||||
validate_config() {
|
||||
log_info "验证配置文件..."
|
||||
|
||||
# 检查 .env 文件
|
||||
if [[ ! -f ".env" ]]; then
|
||||
log_error ".env 文件不存在,请先运行环境设置"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查 docker-compose.yml 文件
|
||||
if [[ ! -f "docker-compose.yml" ]]; then
|
||||
log_error "docker-compose.yml 文件不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 验证 Docker Compose 配置语法
|
||||
if ! docker-compose config > /dev/null 2>&1; then
|
||||
log_error "Docker Compose 配置文件语法错误"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "配置文件验证通过"
|
||||
}
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
echo "用法: $0 [选项] [环境]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " -h, --help 显示此帮助信息"
|
||||
echo " -c, --check 仅检查系统要求"
|
||||
echo " -v, --validate 仅验证配置"
|
||||
echo ""
|
||||
echo "环境:"
|
||||
echo " development 开发环境 (默认)"
|
||||
echo " staging 测试环境"
|
||||
echo " production 生产环境"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 # 设置开发环境"
|
||||
echo " $0 production # 设置生产环境"
|
||||
echo " $0 --check # 仅检查系统要求"
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local environment="development"
|
||||
local check_only=false
|
||||
local validate_only=false
|
||||
|
||||
# 解析命令行参数
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
-c|--check)
|
||||
check_only=true
|
||||
shift
|
||||
;;
|
||||
-v|--validate)
|
||||
validate_only=true
|
||||
shift
|
||||
;;
|
||||
development|staging|production)
|
||||
environment=$1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
log_error "未知参数: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# 切换到docker目录
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
log_info "开始设置Docker部署环境..."
|
||||
|
||||
# 检查系统要求
|
||||
check_requirements
|
||||
|
||||
if [[ "$check_only" == true ]]; then
|
||||
log_success "系统要求检查完成"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$validate_only" == true ]]; then
|
||||
validate_config
|
||||
log_success "配置验证完成"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 创建目录结构
|
||||
create_directories
|
||||
|
||||
# 设置环境配置
|
||||
setup_environment "$environment"
|
||||
|
||||
# 设置文件权限
|
||||
set_permissions
|
||||
|
||||
# 验证配置
|
||||
validate_config
|
||||
|
||||
log_success "Docker部署环境设置完成!"
|
||||
log_info "下一步:"
|
||||
log_info "1. 检查并修改 .env 文件中的配置"
|
||||
log_info "2. 运行 'scripts/build.sh' 构建镜像"
|
||||
log_info "3. 运行 'scripts/deploy.sh start' 启动服务"
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
@ -0,0 +1,338 @@
|
||||
package com.ruoyi.credit.domain.dto;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 通过验证的贷款数据传输对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-04
|
||||
*/
|
||||
public class ValidatedLoanDTO
|
||||
{
|
||||
/** 贷款ID */
|
||||
private Long loanId;
|
||||
|
||||
/** 债权凭证ID */
|
||||
private Long creditId;
|
||||
|
||||
/** 债权编号 */
|
||||
private String creditNumber;
|
||||
|
||||
/** 合同编号 */
|
||||
private String contractNumber;
|
||||
|
||||
/** 安保公司 */
|
||||
private String securityCompany;
|
||||
|
||||
/** 债权金额 */
|
||||
private BigDecimal creditAmount;
|
||||
|
||||
/** 贷款编号 */
|
||||
private String loanNumber;
|
||||
|
||||
/** 贷款金额 */
|
||||
private BigDecimal loanAmount;
|
||||
|
||||
/** 利率 */
|
||||
private Double interestRate;
|
||||
|
||||
/** 贷款期限(月) */
|
||||
private Integer loanTermMonths;
|
||||
|
||||
/** 月还款额 */
|
||||
private BigDecimal monthlyPayment;
|
||||
|
||||
/** 贷款用途 */
|
||||
private String loanPurpose;
|
||||
|
||||
/** 贷款状态 */
|
||||
private String loanStatus;
|
||||
|
||||
/** 贷款开始日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date loanStartDate;
|
||||
|
||||
/** 贷款结束日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date loanEndDate;
|
||||
|
||||
/** 银行机构ID */
|
||||
private Long bankInstitutionId;
|
||||
|
||||
/** 银行机构名称 */
|
||||
private String bankInstitutionName;
|
||||
|
||||
/** 审批状态 */
|
||||
private String approvalStatus;
|
||||
|
||||
/** 审批时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date approvalTime;
|
||||
|
||||
/** 审批人 */
|
||||
private String approvedBy;
|
||||
|
||||
/** 申请时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date applicationDate;
|
||||
|
||||
/** 验证状态 */
|
||||
private String validationStatus;
|
||||
|
||||
/** 验证时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date validationTime;
|
||||
|
||||
/** 验证结果 */
|
||||
private String validationResult;
|
||||
|
||||
/** 失败原因 */
|
||||
private String failureReason;
|
||||
|
||||
/** 验证得分 */
|
||||
private Integer validationScore;
|
||||
|
||||
/** 规则版本 */
|
||||
private String ruleVersion;
|
||||
|
||||
/** 债权状态 */
|
||||
private String creditStatus;
|
||||
|
||||
/** 服务周期ID */
|
||||
private Long servicePeriodId;
|
||||
|
||||
public Long getLoanId() {
|
||||
return loanId;
|
||||
}
|
||||
|
||||
public void setLoanId(Long loanId) {
|
||||
this.loanId = loanId;
|
||||
}
|
||||
|
||||
public Long getCreditId() {
|
||||
return creditId;
|
||||
}
|
||||
|
||||
public void setCreditId(Long creditId) {
|
||||
this.creditId = creditId;
|
||||
}
|
||||
|
||||
public String getCreditNumber() {
|
||||
return creditNumber;
|
||||
}
|
||||
|
||||
public void setCreditNumber(String creditNumber) {
|
||||
this.creditNumber = creditNumber;
|
||||
}
|
||||
|
||||
public String getContractNumber() {
|
||||
return contractNumber;
|
||||
}
|
||||
|
||||
public void setContractNumber(String contractNumber) {
|
||||
this.contractNumber = contractNumber;
|
||||
}
|
||||
|
||||
public String getSecurityCompany() {
|
||||
return securityCompany;
|
||||
}
|
||||
|
||||
public void setSecurityCompany(String securityCompany) {
|
||||
this.securityCompany = securityCompany;
|
||||
}
|
||||
|
||||
public BigDecimal getCreditAmount() {
|
||||
return creditAmount;
|
||||
}
|
||||
|
||||
public void setCreditAmount(BigDecimal creditAmount) {
|
||||
this.creditAmount = creditAmount;
|
||||
}
|
||||
|
||||
public String getLoanNumber() {
|
||||
return loanNumber;
|
||||
}
|
||||
|
||||
public void setLoanNumber(String loanNumber) {
|
||||
this.loanNumber = loanNumber;
|
||||
}
|
||||
|
||||
public BigDecimal getLoanAmount() {
|
||||
return loanAmount;
|
||||
}
|
||||
|
||||
public void setLoanAmount(BigDecimal loanAmount) {
|
||||
this.loanAmount = loanAmount;
|
||||
}
|
||||
|
||||
public Double getInterestRate() {
|
||||
return interestRate;
|
||||
}
|
||||
|
||||
public void setInterestRate(Double interestRate) {
|
||||
this.interestRate = interestRate;
|
||||
}
|
||||
|
||||
public Integer getLoanTermMonths() {
|
||||
return loanTermMonths;
|
||||
}
|
||||
|
||||
public void setLoanTermMonths(Integer loanTermMonths) {
|
||||
this.loanTermMonths = loanTermMonths;
|
||||
}
|
||||
|
||||
public BigDecimal getMonthlyPayment() {
|
||||
return monthlyPayment;
|
||||
}
|
||||
|
||||
public void setMonthlyPayment(BigDecimal monthlyPayment) {
|
||||
this.monthlyPayment = monthlyPayment;
|
||||
}
|
||||
|
||||
public String getLoanPurpose() {
|
||||
return loanPurpose;
|
||||
}
|
||||
|
||||
public void setLoanPurpose(String loanPurpose) {
|
||||
this.loanPurpose = loanPurpose;
|
||||
}
|
||||
|
||||
public String getLoanStatus() {
|
||||
return loanStatus;
|
||||
}
|
||||
|
||||
public void setLoanStatus(String loanStatus) {
|
||||
this.loanStatus = loanStatus;
|
||||
}
|
||||
|
||||
public Date getLoanStartDate() {
|
||||
return loanStartDate;
|
||||
}
|
||||
|
||||
public void setLoanStartDate(Date loanStartDate) {
|
||||
this.loanStartDate = loanStartDate;
|
||||
}
|
||||
|
||||
public Date getLoanEndDate() {
|
||||
return loanEndDate;
|
||||
}
|
||||
|
||||
public void setLoanEndDate(Date loanEndDate) {
|
||||
this.loanEndDate = loanEndDate;
|
||||
}
|
||||
|
||||
public Long getBankInstitutionId() {
|
||||
return bankInstitutionId;
|
||||
}
|
||||
|
||||
public void setBankInstitutionId(Long bankInstitutionId) {
|
||||
this.bankInstitutionId = bankInstitutionId;
|
||||
}
|
||||
|
||||
public String getBankInstitutionName() {
|
||||
return bankInstitutionName;
|
||||
}
|
||||
|
||||
public void setBankInstitutionName(String bankInstitutionName) {
|
||||
this.bankInstitutionName = bankInstitutionName;
|
||||
}
|
||||
|
||||
public String getApprovalStatus() {
|
||||
return approvalStatus;
|
||||
}
|
||||
|
||||
public void setApprovalStatus(String approvalStatus) {
|
||||
this.approvalStatus = approvalStatus;
|
||||
}
|
||||
|
||||
public Date getApprovalTime() {
|
||||
return approvalTime;
|
||||
}
|
||||
|
||||
public void setApprovalTime(Date approvalTime) {
|
||||
this.approvalTime = approvalTime;
|
||||
}
|
||||
|
||||
public String getApprovedBy() {
|
||||
return approvedBy;
|
||||
}
|
||||
|
||||
public void setApprovedBy(String approvedBy) {
|
||||
this.approvedBy = approvedBy;
|
||||
}
|
||||
|
||||
public Date getApplicationDate() {
|
||||
return applicationDate;
|
||||
}
|
||||
|
||||
public void setApplicationDate(Date applicationDate) {
|
||||
this.applicationDate = applicationDate;
|
||||
}
|
||||
|
||||
public String getValidationStatus() {
|
||||
return validationStatus;
|
||||
}
|
||||
|
||||
public void setValidationStatus(String validationStatus) {
|
||||
this.validationStatus = validationStatus;
|
||||
}
|
||||
|
||||
public Date getValidationTime() {
|
||||
return validationTime;
|
||||
}
|
||||
|
||||
public void setValidationTime(Date validationTime) {
|
||||
this.validationTime = validationTime;
|
||||
}
|
||||
|
||||
public String getValidationResult() {
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
public void setValidationResult(String validationResult) {
|
||||
this.validationResult = validationResult;
|
||||
}
|
||||
|
||||
public String getFailureReason() {
|
||||
return failureReason;
|
||||
}
|
||||
|
||||
public void setFailureReason(String failureReason) {
|
||||
this.failureReason = failureReason;
|
||||
}
|
||||
|
||||
public Integer getValidationScore() {
|
||||
return validationScore;
|
||||
}
|
||||
|
||||
public void setValidationScore(Integer validationScore) {
|
||||
this.validationScore = validationScore;
|
||||
}
|
||||
|
||||
public String getRuleVersion() {
|
||||
return ruleVersion;
|
||||
}
|
||||
|
||||
public void setRuleVersion(String ruleVersion) {
|
||||
this.ruleVersion = ruleVersion;
|
||||
}
|
||||
|
||||
public String getCreditStatus() {
|
||||
return creditStatus;
|
||||
}
|
||||
|
||||
public void setCreditStatus(String creditStatus) {
|
||||
this.creditStatus = creditStatus;
|
||||
}
|
||||
|
||||
public Long getServicePeriodId() {
|
||||
return servicePeriodId;
|
||||
}
|
||||
|
||||
public void setServicePeriodId(Long servicePeriodId) {
|
||||
this.servicePeriodId = servicePeriodId;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user