12 KiB
12 KiB
QAUP 极简离线部署方案
Spring Boot + Redis + PostgreSQL with PostGIS(一键部署、一键升级)
1. 设计原则
- 极简优先:最少的文件,最少的步骤
- 离线部署:预打包所有依赖,无需联网
- 一键操作:部署和升级都是一条命令
- 配置灵活:关键配置可外部修改
- 自动化迁移:数据库版本自动管理(Flyway)
2. 打包准备(开发环境执行一次)
2.1 打包脚本(package-all.sh)
#!/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(当前实际版本)
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)
# 服务器配置
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 迁移状态查询
# 查看应用日志中的迁移信息
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)
#!/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条命令)
tar -xzf qaup-deploy.tar.gz && cd qaup-deploy && ./deploy-all.sh
8. 一键升级(deploy-update.sh)
#!/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,确认以下配置:
# docker-compose.yml 中必须使用Java 21镜像
services:
qaup-app:
# 正确示例
image: m.daocloud.io/docker.io/library/eclipse-temurin:21-jre
9.3 版本验证命令
# 检查容器中Java版本
docker exec qaup-app java -version
# 检查jar文件编译版本
javap -cp app.jar -version
# 快速健康检查
curl http://localhost:8080/actuator/health
10. 系统维护操作
10.1 日常运维命令
# 查看服务状态
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 监控数据库迁移状态
# 查看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 数据备份和恢复
# 手动备份数据库
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 完全重置(开发测试用)
# 停止所有服务
docker compose down
# 删除数据目录(⚠️ 注意:这会删除所有数据)
rm -rf data/
# 重新部署
./deploy-all.sh
11. 操作总结
开发环境(一次性)
# 在macOS上构建
mvn clean package -DskipTests
./deploy/package-all.sh
# 或在服务器上打包
./deploy/package-all.sh
客户环境
# 首次部署
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运行时,确保版本一致性