# 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运行时,确保版本一致性