462 lines
12 KiB
Markdown
462 lines
12 KiB
Markdown
# QAUP 极简离线部署方案
|
||
|
||
Spring Boot + Redis + PostgreSQL with PostGIS(一键部署、一键升级)
|
||
|
||
## 1. 设计原则
|
||
|
||
- **极简优先**:最少的文件,最少的步骤
|
||
- **离线部署**:预打包所有依赖,无需联网
|
||
- **一键操作**:部署和升级都是一条命令
|
||
- **配置灵活**:关键配置可外部修改
|
||
- **自动化迁移**:数据库版本自动管理(Flyway)
|
||
|
||
## 2. 打包准备(开发环境执行一次)
|
||
|
||
### 2.1 打包脚本(package-all.sh)
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
echo "=== QAUP 打包脚本 ==="
|
||
|
||
# 1. 构建应用(在macOS上)
|
||
mvn clean package -DskipTests
|
||
|
||
# 2. 拉取并导出镜像(在服务器上)
|
||
docker pull m.daocloud.io/docker.io/postgis/postgis:17-3.5-alpine
|
||
docker pull m.daocloud.io/docker.io/library/redis:8.0-alpine
|
||
docker pull m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
|
||
|
||
# 导出镜像
|
||
docker save m.daocloud.io/docker.io/postgis/postgis:17-3.5-alpine \
|
||
m.daocloud.io/docker.io/library/redis:8.0-alpine \
|
||
m.daocloud.io/docker.io/library/eclipse-temurin:21-jre | gzip > images.tar.gz
|
||
|
||
# 3. 准备部署包
|
||
mkdir -p qaup-deploy
|
||
cp qaup-admin/target/qaup-admin.jar qaup-deploy/app.jar
|
||
cp deploy/docker-compose.yml qaup-deploy/
|
||
cp deploy/config.yml qaup-deploy/
|
||
cp images.tar.gz qaup-deploy/
|
||
|
||
# 4. 打包
|
||
tar -czf qaup-deploy-$(date +%Y%m%d-%H%M%S).tar.gz -C qaup-deploy .
|
||
echo "打包完成: qaup-deploy-$(date +%Y%m%d-%H%M%S).tar.gz"
|
||
```
|
||
|
||
### 2.2 部署包结构
|
||
|
||
```
|
||
qaup-deploy.tar.gz
|
||
├── images.tar.gz # Docker镜像包(PostGIS + Redis + Java21)
|
||
├── docker-compose.yml # 服务编排(包含健康检查)
|
||
├── app.jar # 应用程序
|
||
├── config.yml # 外部配置(可修改)
|
||
├── deploy-all.sh # 一键部署脚本
|
||
├── deploy-update.sh # 一键升级脚本
|
||
├── DeployGuide.md # 详细部署指南
|
||
└── qaup_database_export.sql # 完整数据库备份(可选)
|
||
```
|
||
|
||
## 3. docker-compose.yml(当前实际版本)
|
||
|
||
```yaml
|
||
services:
|
||
# PostgreSQL + PostGIS 数据库服务
|
||
qaup-postgres:
|
||
image: m.daocloud.io/docker.io/postgis/postgis:17-3.5-alpine
|
||
container_name: qaup-postgres
|
||
restart: unless-stopped
|
||
environment:
|
||
POSTGRES_DB: qaup
|
||
POSTGRES_USER: qaup
|
||
POSTGRES_PASSWORD: qaup123
|
||
volumes:
|
||
- ./data/postgres:/var/lib/postgresql/data
|
||
ports:
|
||
- "5432:5432"
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U qaup"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 3
|
||
|
||
# Redis 缓存服务
|
||
qaup-redis:
|
||
image: m.daocloud.io/docker.io/library/redis:8.0-alpine
|
||
container_name: qaup-redis
|
||
restart: unless-stopped
|
||
command: ["redis-server", "--maxmemory", "256mb", "--maxmemory-policy", "allkeys-lru"]
|
||
volumes:
|
||
- ./data/redis:/data
|
||
ports:
|
||
- "6379:6379"
|
||
healthcheck:
|
||
test: ["CMD", "redis-cli", "ping"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 3
|
||
|
||
# QAUP 应用服务(Java 21)
|
||
qaup-app:
|
||
image: m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
|
||
container_name: qaup-app
|
||
restart: unless-stopped
|
||
environment:
|
||
SPRING_PROFILES_ACTIVE: prod
|
||
LOG_PATH: /app/logs
|
||
# 数据库连接配置
|
||
DB_HOST: qaup-postgres
|
||
DB_PORT: 5432
|
||
DB_NAME: qaup
|
||
DB_USER: qaup
|
||
DB_PASSWORD: qaup123
|
||
# Flyway配置(自动化数据库迁移)
|
||
SPRING_FLYWAY_ENABLED: true
|
||
SPRING_FLYWAY_BASELINE_ON_MIGRATE: true
|
||
SPRING_FLYWAY_VALIDATE_ON_MIGRATE: true
|
||
SPRING_FLYWAY_CLEAN_DISABLED: true
|
||
volumes:
|
||
- ./app.jar:/app/app.jar
|
||
- ./config.yml:/app/config.yml
|
||
- ./logs:/app/logs
|
||
- ./backup:/app/backup
|
||
ports:
|
||
- "8080:8080"
|
||
depends_on:
|
||
qaup-postgres:
|
||
condition: service_healthy
|
||
qaup-redis:
|
||
condition: service_healthy
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 5
|
||
start_period: 120s
|
||
command: [
|
||
"sh", "-c",
|
||
"echo 'Waiting for database to be ready...' &&
|
||
sleep 10 &&
|
||
echo 'Starting QAUP application with Flyway migration...' &&
|
||
java -jar /app/app.jar --spring.config.location=/app/config.yml"
|
||
]
|
||
|
||
networks:
|
||
default:
|
||
name: qaup-network
|
||
```
|
||
|
||
## 4. 外部配置文件(config.yml)
|
||
|
||
```yaml
|
||
# 服务器配置
|
||
server:
|
||
port: 8080
|
||
|
||
# 应用配置
|
||
qaup:
|
||
# 文件上传路径
|
||
profile: /tmp/uploads
|
||
# 外部接口配置(客户可修改)
|
||
external:
|
||
api-host: 192.168.1.100
|
||
api-port: 8090
|
||
|
||
# 日志配置
|
||
logging:
|
||
level:
|
||
com.qaup: INFO
|
||
pattern:
|
||
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||
file:
|
||
name: /app/logs/qaup.log
|
||
|
||
# 注意:数据库和Redis配置通过环境变量设置
|
||
```
|
||
|
||
## 5. 自动化数据库迁移(Flyway)
|
||
|
||
### 5.1 迁移脚本位置
|
||
|
||
```
|
||
qaup-admin/src/main/resources/db/migration/
|
||
├── V1.0.0__Initial_baseline.sql # 数据库基线结构(86KB)
|
||
├── V1.0.1__Initial_data.sql # 初始数据(50KB)
|
||
└── README.md # 迁移脚本编写规范
|
||
```
|
||
|
||
### 5.2 自动迁移机制
|
||
|
||
- **应用启动时自动执行**:无需手动运行SQL脚本
|
||
- **版本控制**:所有迁移按版本顺序执行
|
||
- **幂等性**:安全重复执行,不会重复创建对象
|
||
- **健康检查**:依赖数据库健康状态启动应用
|
||
|
||
### 5.3 迁移状态查询
|
||
|
||
```bash
|
||
# 查看应用日志中的迁移信息
|
||
docker compose logs qaup-app | grep -i flyway
|
||
|
||
# 直接查询数据库
|
||
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
|
||
```
|
||
|
||
## 6. 一键部署(deploy-all.sh)
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
echo "=== QAUP 一键部署 ==="
|
||
|
||
# 检查Docker
|
||
if ! command -v docker &> /dev/null; then
|
||
echo "❌ Docker 未安装"
|
||
exit 1
|
||
fi
|
||
|
||
# 载入镜像
|
||
echo "载入Docker镜像..."
|
||
docker load -i images.tar.gz
|
||
|
||
# 创建数据目录
|
||
echo "创建数据目录..."
|
||
mkdir -p data/postgres data/redis logs
|
||
|
||
# 启动服务
|
||
echo "启动服务..."
|
||
docker compose up -d
|
||
|
||
# 等待服务启动
|
||
echo "等待服务启动(60秒)..."
|
||
sleep 60
|
||
|
||
# 检查服务状态
|
||
if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then
|
||
echo "✅ 部署成功!"
|
||
echo ""
|
||
echo "访问地址: http://localhost:8080"
|
||
echo "数据库: localhost:5432 (qaup/qaup123)"
|
||
echo "Redis: localhost:6379"
|
||
echo ""
|
||
echo "管理命令:"
|
||
echo " 查看状态: docker compose ps"
|
||
echo " 查看日志: docker compose logs -f qaup-app"
|
||
echo " 停止服务: docker compose down"
|
||
echo " 升级应用: ./deploy-update.sh"
|
||
else
|
||
echo "❌ 服务启动失败,请检查日志:"
|
||
docker compose logs
|
||
fi
|
||
```
|
||
|
||
## 7. 客户部署(1条命令)
|
||
|
||
```bash
|
||
tar -xzf qaup-deploy.tar.gz && cd qaup-deploy && ./deploy-all.sh
|
||
```
|
||
|
||
## 8. 一键升级(deploy-update.sh)
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
echo "=== QAUP 一键升级 ==="
|
||
|
||
# 检查新版本文件
|
||
if [ ! -f "new-app.jar" ]; then
|
||
echo "❌ 请先将新版本文件重命名为 new-app.jar"
|
||
exit 1
|
||
fi
|
||
|
||
# 验证Java版本兼容性(重要:确保jar与容器Java版本匹配)
|
||
echo "验证Java版本兼容性..."
|
||
if command -v java &> /dev/null; then
|
||
LOCAL_JAVA_VERSION=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')
|
||
echo "本地Java版本: $LOCAL_JAVA_VERSION"
|
||
echo "容器Java版本: eclipse-temurin:21-jre"
|
||
fi
|
||
|
||
# 备份当前版本
|
||
echo "备份当前版本..."
|
||
cp app.jar app.jar.backup.$(date +%Y%m%d_%H%M%S)
|
||
|
||
# 数据库备份(重要)
|
||
echo "备份数据库..."
|
||
docker exec qaup-postgres pg_dump -U qaup qaup > backup/qaup-backup-$(date +%Y%m%d_%H%M%S).sql
|
||
|
||
# 停止应用(不影响数据库)
|
||
echo "停止应用服务..."
|
||
docker compose stop qaup-app
|
||
|
||
# 替换应用
|
||
cp new-app.jar app.jar
|
||
echo "已更新应用文件"
|
||
|
||
# 启动应用(Flyway自动处理数据库迁移)
|
||
echo "启动应用服务..."
|
||
docker compose start qaup-app
|
||
|
||
# 等待启动和迁移完成
|
||
echo "等待应用启动和数据库迁移(120秒)..."
|
||
sleep 120
|
||
|
||
# 检查升级结果
|
||
if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then
|
||
echo "✅ 升级成功!"
|
||
echo ""
|
||
echo "Flyway迁移状态:"
|
||
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_rank FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 5;"
|
||
else
|
||
echo "❌ 升级失败,开始回滚..."
|
||
# 恢复jar文件
|
||
LATEST_BACKUP=$(ls -t app.jar.backup.* 2>/dev/null | head -1)
|
||
if [ -n "$LATEST_BACKUP" ]; then
|
||
cp "$LATEST_BACKUP" app.jar
|
||
docker compose restart qaup-app
|
||
echo "✅ 已回滚到版本: $LATEST_BACKUP"
|
||
else
|
||
echo "❌ 未找到备份文件,请手动处理"
|
||
fi
|
||
fi
|
||
```
|
||
|
||
## 9. Java版本兼容性注意事项
|
||
|
||
### 9.1 编译与运行环境匹配
|
||
|
||
- **编译环境**: 确保项目在Java 21环境下编译
|
||
- **运行环境**: Docker镜像使用 `eclipse-temurin:21-jre`
|
||
|
||
### 9.2 常见版本错误
|
||
|
||
如果遇到 `UnsupportedClassVersionError`,确认以下配置:
|
||
|
||
```yaml
|
||
# docker-compose.yml 中必须使用Java 21镜像
|
||
services:
|
||
qaup-app:
|
||
# 正确示例
|
||
image: m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
|
||
```
|
||
|
||
### 9.3 版本验证命令
|
||
|
||
```bash
|
||
# 检查容器中Java版本
|
||
docker exec qaup-app java -version
|
||
|
||
# 检查jar文件编译版本
|
||
javap -cp app.jar -version
|
||
|
||
# 快速健康检查
|
||
curl http://localhost:8080/actuator/health
|
||
```
|
||
|
||
## 10. 系统维护操作
|
||
|
||
### 10.1 日常运维命令
|
||
|
||
```bash
|
||
# 查看服务状态
|
||
docker compose ps
|
||
|
||
# 查看应用日志
|
||
docker compose logs -f qaup-app
|
||
|
||
# 查看数据库日志
|
||
docker compose logs qaup-postgres
|
||
|
||
# 查看Redis日志
|
||
docker compose logs qaup-redis
|
||
|
||
# 查看系统资源使用
|
||
docker stats
|
||
|
||
# 数据库连接测试
|
||
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version();"
|
||
|
||
# Redis连接测试
|
||
docker exec -it qaup-redis redis-cli ping
|
||
```
|
||
|
||
### 10.2 监控数据库迁移状态
|
||
|
||
```bash
|
||
# 查看Flyway迁移历史
|
||
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
|
||
|
||
# 查看应用日志中的迁移信息
|
||
docker compose logs qaup-app | grep -i flyway
|
||
|
||
# 查看最近的迁移记录
|
||
docker exec -it qaup-postgres psql -U qaup -d qaup -c "SELECT version, description, installed_on FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 3;"
|
||
```
|
||
|
||
### 10.3 数据备份和恢复
|
||
|
||
```bash
|
||
# 手动备份数据库
|
||
docker exec qaup-postgres pg_dump -U qaup qaup > backup/manual-backup-$(date +%Y%m%d_%H%M%S).sql
|
||
|
||
# 恢复数据库(需要停止应用)
|
||
docker compose stop qaup-app
|
||
docker exec -i qaup-postgres psql -U qaup qaup < backup/qaup-backup-20250120_143000.sql
|
||
docker compose start qaup-app
|
||
```
|
||
|
||
### 10.4 完全重置(开发测试用)
|
||
|
||
```bash
|
||
# 停止所有服务
|
||
docker compose down
|
||
|
||
# 删除数据目录(⚠️ 注意:这会删除所有数据)
|
||
rm -rf data/
|
||
|
||
# 重新部署
|
||
./deploy-all.sh
|
||
```
|
||
|
||
## 11. 操作总结
|
||
|
||
### 开发环境(一次性)
|
||
|
||
```bash
|
||
# 在macOS上构建
|
||
mvn clean package -DskipTests
|
||
./deploy/package-all.sh
|
||
|
||
# 或在服务器上打包
|
||
./deploy/package-all.sh
|
||
```
|
||
|
||
### 客户环境
|
||
|
||
```bash
|
||
# 首次部署
|
||
tar -xzf qaup-deploy.tar.gz && cd qaup-deploy && ./deploy-all.sh
|
||
|
||
# 程序更新
|
||
# 1. 复制新jar文件并重命名为 new-app.jar
|
||
# 2. 执行更新
|
||
./deploy-update.sh
|
||
|
||
# 查看状态
|
||
docker compose ps
|
||
|
||
# 查看日志
|
||
docker compose logs -f qaup-app
|
||
```
|
||
|
||
## 12. 现代化优势总结
|
||
|
||
✅ **极简部署**:解压 → 运行脚本,2步完成
|
||
✅ **极简升级**:替换jar → 运行脚本,自动完成
|
||
✅ **离线友好**:所有依赖预打包,无需联网
|
||
✅ **配置灵活**:关键配置外部文件,可随时修改
|
||
✅ **自动化迁移**:Flyway自动处理数据库版本管理
|
||
✅ **健康检查**:服务依赖和健康状态监控
|
||
✅ **PostGIS支持**:内置地理空间数据库能力
|
||
✅ **一键回滚**:升级失败可快速回滚到上一版本
|
||
✅ **零停机升级**:只重启应用服务,数据库保持运行
|
||
✅ **版本兼容**:Java 21运行时,确保版本一致性
|