From ad70b65a8d684a953b06db763aaffa216b24a289 Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Thu, 31 Jul 2025 17:06:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BA=86=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=AF=BC=E5=85=A5=E5=AF=BC=E5=87=BA=E5=92=8C=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/Dockerfile | 4 +- deploy/docker-compose.yml | 12 +- deploy/docker/check-image-versions.sh | 126 ++++ deploy/docker/image-versions.env | 139 +++- deploy/docker/nginx/Dockerfile | 12 +- deploy/docker/postgres/backup-db.sh | 56 -- deploy/docker/postgres/db-manager.sh | 650 ++++++++++++++++++ deploy/docker/postgres/health-check.sh | 29 - deploy/docker/postgres/init-db.sh | 38 +- .../docker/postgres/initial_data.template.sql | 305 ++++++++ deploy/docker/postgres/restore-db.sh | 72 -- deploy/docker/prepare-offline-images.sh | 316 ++++++++- deploy/docker/update-image-versions.sh | 262 +++++++ deploy/docker/verify-versions.sh | 120 ++++ deploy/docs/DEPLOYMENT-CHECKLIST.md | 115 ++++ .../{ => docs}/DOCKER-DEPLOYMENT-SUMMARY.md | 35 + deploy/{ => docs}/README-Docker.md | 19 + deploy/docs/数据导出导入指南.md | 204 ++++++ deploy/docs/数据文件说明.md | 141 ++++ deploy/docs/部署指南.md | 70 +- deploy/test-paths.sh | 95 +++ ry.sh => qaup.sh | 0 22 files changed, 2590 insertions(+), 230 deletions(-) create mode 100644 deploy/docker/check-image-versions.sh delete mode 100755 deploy/docker/postgres/backup-db.sh create mode 100644 deploy/docker/postgres/db-manager.sh delete mode 100755 deploy/docker/postgres/health-check.sh create mode 100644 deploy/docker/postgres/initial_data.template.sql delete mode 100755 deploy/docker/postgres/restore-db.sh create mode 100644 deploy/docker/update-image-versions.sh create mode 100644 deploy/docker/verify-versions.sh create mode 100644 deploy/docs/DEPLOYMENT-CHECKLIST.md rename deploy/{ => docs}/DOCKER-DEPLOYMENT-SUMMARY.md (87%) rename deploy/{ => docs}/README-Docker.md (95%) create mode 100644 deploy/docs/数据导出导入指南.md create mode 100644 deploy/docs/数据文件说明.md create mode 100755 deploy/test-paths.sh rename ry.sh => qaup.sh (100%) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 6e87cff6..a053b00a 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -1,5 +1,5 @@ # 多阶段构建 - 构建阶段 -FROM maven:3.9.6-openjdk-17-slim AS builder +FROM maven:3.9.11-openjdk-17-slim AS builder # 设置工作目录 WORKDIR /app @@ -47,7 +47,7 @@ RUN mkdir -p /app/logs /app/uploadPath && \ COPY --from=builder /app/qaup-admin/target/qaup-admin.jar app.jar # 复制启动脚本 -COPY docker/start.sh /app/start.sh +COPY deploy/docker/start.sh /app/start.sh RUN chmod +x /app/start.sh && chown qaup:qaup /app/start.sh # 切换到非 root 用户 diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index da687fa8..850e458c 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -3,7 +3,7 @@ version: '3.8' services: # PostgreSQL 数据库服务 qaup-postgres: - image: postgis/postgis:15-3.3 + image: postgis/postgis:17-3.5-alpine container_name: qaup-postgres restart: unless-stopped environment: @@ -41,7 +41,7 @@ services: # Redis 缓存服务 qaup-redis: - image: redis:7-alpine + image: redis:8.0-alpine container_name: qaup-redis restart: unless-stopped command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-} @@ -72,8 +72,8 @@ services: # QAUP 应用服务 qaup-app: build: - context: . - dockerfile: Dockerfile + context: .. + dockerfile: deploy/Dockerfile image: qaup-app:latest container_name: qaup-app restart: unless-stopped @@ -130,8 +130,8 @@ services: # Nginx 反向代理服务 qaup-nginx: build: - context: . - dockerfile: docker/nginx/Dockerfile + context: .. + dockerfile: deploy/docker/nginx/Dockerfile image: qaup-nginx:latest container_name: qaup-nginx restart: unless-stopped diff --git a/deploy/docker/check-image-versions.sh b/deploy/docker/check-image-versions.sh new file mode 100644 index 00000000..79497d92 --- /dev/null +++ b/deploy/docker/check-image-versions.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +# QAUP Docker 镜像版本检查脚本 +# 检查各个镜像的最新稳定版本 + +set -e + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_message() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +# 检查 Docker Hub API 获取最新版本 +check_dockerhub_tags() { + local repo=$1 + local filter=${2:-""} + + print_message $BLUE "检查 $repo 的版本..." + + # 使用 Docker Hub API 获取标签 + local api_url="https://registry.hub.docker.com/v2/repositories/$repo/tags?page_size=100" + + if command -v curl &> /dev/null; then + local tags=$(curl -s "$api_url" | grep -o '"name":"[^"]*"' | cut -d'"' -f4 | head -20) + echo "最新的一些版本标签:" + echo "$tags" | head -10 + else + print_message $YELLOW "curl 不可用,无法检查版本" + fi + echo "" +} + +# 检查当前使用的版本 +check_current_versions() { + print_message $BLUE "当前 docker-compose.yml 中使用的版本:" + echo "" + + if [ -f "../docker-compose.yml" ]; then + echo "PostgreSQL/PostGIS:" + grep -A 1 "qaup-postgres:" ../docker-compose.yml | grep "image:" | awk '{print " " $2}' + + echo "Redis:" + grep -A 1 "qaup-redis:" ../docker-compose.yml | grep "image:" | awk '{print " " $2}' + + echo "" + fi + + if [ -f "../Dockerfile" ]; then + echo "Dockerfile 中的镜像:" + grep "^FROM" ../Dockerfile | awk '{print " " $2}' + echo "" + fi +} + +print_message $GREEN "=========================================" +print_message $GREEN "QAUP Docker 镜像版本检查" +print_message $GREEN "=========================================" +echo "" + +# 检查当前版本 +check_current_versions + +# 检查各个镜像的最新版本 +print_message $BLUE "检查 Docker Hub 上的最新版本..." +echo "" + +# PostgreSQL/PostGIS +check_dockerhub_tags "postgis/postgis" + +# Redis +check_dockerhub_tags "library/redis" + +# OpenJDK +check_dockerhub_tags "library/openjdk" + +# Maven +check_dockerhub_tags "library/maven" + +# Nginx +check_dockerhub_tags "library/nginx" + +# Node.js +check_dockerhub_tags "library/node" + +print_message $YELLOW "注意事项:" +echo "1. 选择版本时应优先考虑稳定性而非最新性" +echo "2. LTS (Long Term Support) 版本通常是生产环境的最佳选择" +echo "3. 对于 PostGIS,需要确保 PostgreSQL 版本兼容性" +echo "4. 建议在测试环境验证新版本后再用于生产" +echo "" + +# 检查当前配置文件中的版本 +if [ -f "image-versions.env" ]; then + print_message $BLUE "当前配置文件中的版本:" + source image-versions.env + echo "PostgreSQL/PostGIS: $POSTGRES_IMAGE" + echo "Redis: $REDIS_IMAGE" + echo "OpenJDK: $OPENJDK_IMAGE" + echo "Maven: $MAVEN_IMAGE" + echo "Nginx: $NGINX_IMAGE" + echo "Node.js: $NODE_IMAGE" + echo "" +fi + +print_message $GREEN "基于实际检查的推荐版本组合:" +echo "PostgreSQL/PostGIS: postgis/postgis:15-3.5-alpine (稳定) 或 postgis/postgis:16-3.5-alpine (更新)" +echo "Redis: redis:7.4.5-alpine (7.x系列最新稳定版) 或 redis:8.0.3-alpine (最新版本)" +echo "OpenJDK: openjdk:17-jre-slim (LTS推荐)" +echo "Maven: maven:3.9.11-openjdk-17-slim (最新稳定版)" +echo "Nginx: nginx:stable-alpine (稳定版本)" +echo "Node.js: node:lts-alpine (当前LTS版本)" +echo "" + +print_message $YELLOW "更新建议:" +echo "1. 运行 './update-image-versions.sh --dry-run' 预览更改" +echo "2. 运行 './update-image-versions.sh --backup' 执行更新" +echo "3. 在测试环境验证新版本兼容性" +echo "4. 更新离线部署包" \ No newline at end of file diff --git a/deploy/docker/image-versions.env b/deploy/docker/image-versions.env index 4b69bf5c..92414c53 100644 --- a/deploy/docker/image-versions.env +++ b/deploy/docker/image-versions.env @@ -1,31 +1,124 @@ -# QAUP Docker 镜像版本锁定配置 -# 用于确保离线部署的一致性 +# QAUP Docker 镜像版本配置文件 +# 集中管理所有使用的 Docker 镜像版本 +# 更新日期: 2024-01-31 +# =========================================== # 基础镜像版本 -OPENJDK_VERSION=17-jre-slim -NGINX_VERSION=alpine -POSTGRES_VERSION=15-3.3 -REDIS_VERSION=7-alpine -NODE_VERSION=18-alpine -MAVEN_VERSION=3.9.6-openjdk-17-slim +# =========================================== +# PostgreSQL with PostGIS +# PostgreSQL with PostGIS +# 使用 PostgreSQL 17 + PostGIS 3.5 (根据用户实际使用版本) +# PostgreSQL 17 是最新稳定版本,PostGIS 3.5 是当前稳定版本 +POSTGRES_IMAGE=postgis/postgis:17-3.5-alpine + +# Redis +# 使用 Redis 8.0 最新版本 (根据用户实际使用版本) +REDIS_IMAGE=redis:8.0-alpine + +# OpenJDK +# 使用 Java 17 LTS 版本(生产环境推荐) +OPENJDK_IMAGE=openjdk:17-jre-slim + +# Maven +# 使用 Maven 3.9.11 + OpenJDK 17 +MAVEN_IMAGE=maven:3.9.11-openjdk-17-slim + +# Nginx +# 使用稳定版本 +NGINX_IMAGE=nginx:stable-alpine + +# Node.js +# 使用当前 LTS 版本 +NODE_IMAGE=node:lts-alpine + +# =========================================== # 自定义镜像版本 -QAUP_APP_VERSION=latest -QAUP_NGINX_VERSION=latest +# =========================================== -# 镜像完整名称(用于脚本引用) -OPENJDK_IMAGE=openjdk:${OPENJDK_VERSION} -NGINX_IMAGE=nginx:${NGINX_VERSION} -POSTGRES_IMAGE=postgis/postgis:${POSTGRES_VERSION} -REDIS_IMAGE=redis:${REDIS_VERSION} -NODE_IMAGE=node:${NODE_VERSION} -MAVEN_IMAGE=maven:${MAVEN_VERSION} +# QAUP 应用镜像 +QAUP_APP_IMAGE=qaup-app:latest -QAUP_APP_IMAGE=qaup-app:${QAUP_APP_VERSION} -QAUP_NGINX_IMAGE=qaup-nginx:${QAUP_NGINX_VERSION} +# QAUP Nginx 镜像 +QAUP_NGINX_IMAGE=qaup-nginx:latest -# 构建时间戳(自动生成) -BUILD_TIMESTAMP=$(date +%Y%m%d_%H%M%S) +# =========================================== +# 版本说明 +# =========================================== -# 部署环境标识 -DEPLOY_ENV=production \ No newline at end of file +# PostgreSQL/PostGIS 版本选择说明 (基于用户实际使用版本): +# - postgis/postgis:17-3.5-alpine: PostgreSQL 17 + PostGIS 3.5 (当前使用,最新稳定版) +# - postgis/postgis:16-3.5-alpine: PostgreSQL 16 + PostGIS 3.5 (稳定选择) +# - postgis/postgis:15-3.5-alpine: PostgreSQL 15 + PostGIS 3.5 (保守选择) +# - postgis/postgis:*-3.6.0alpha1-alpine: PostGIS 3.6 alpha (不推荐生产使用) + +# Java 版本选择说明: +# - Java 17: LTS 版本,生产环境推荐,兼容性好 +# - Java 21: 最新 LTS 版本,性能更好,但需要验证兼容性 +# - Java 25/26: 预览版本,不推荐生产使用 + +# Redis 版本说明 (基于用户实际使用版本): +# - 8.0-alpine: Redis 8.0 最新版本 (当前使用) +# - 7.4.5-alpine: 7.x 系列最新稳定版本 +# - 7.2.x-alpine: 较老但稳定的版本 + +# Maven 版本说明: +# - 3.9.11: 当前最新稳定版本 +# - 与 OpenJDK 版本保持一致很重要 + +# Node.js 版本说明: +# - lts-alpine: 总是指向当前 LTS 版本 +# - iron-*: Iron 是 Node.js 18.x LTS 的代号 +# - jod-*: 可能是更新的 LTS 版本代号 + +# Nginx 版本说明: +# - stable-alpine: 总是指向稳定版本 +# - mainline-*: 开发版本,包含最新特性但可能不稳定 + +# =========================================== +# 更新检查命令 +# =========================================== + +# 运行以下命令检查最新版本: +# ./check-image-versions.sh + +# 更新镜像版本后,需要同步更新: +# 1. docker-compose.yml +# 2. Dockerfile +# 3. docker/nginx/Dockerfile +# 4. prepare-offline-images.sh + +# =========================================== +# 版本更新记录 +# =========================================== + +# 2024-01-31: 根据用户实际使用版本更新 +# - PostgreSQL: 15-3.5-alpine → 17-3.5-alpine (升级到最新稳定版) +# - Redis: 7.4.5-alpine → 8.0-alpine (升级到最新版本) +# - 其他组件保持不变 + +# 注意事项: +# - PostgreSQL 17 是最新稳定版本,包含性能改进和新特性 +# - Redis 8.0 是最新版本,包含新的数据结构和性能优化 +# - 升级前请在测试环境验证兼容性 +# - 建议备份现有数据后再进行升级 + +# =========================================== +# 版本兼容性检查清单 +# =========================================== + +# 更新版本前请确认: +# □ Spring Boot 版本与 Java 版本兼容 +# □ PostGIS 版本与应用程序的空间数据处理兼容 +# □ Redis 版本与应用程序的缓存功能兼容 +# □ Node.js 版本与前端构建工具兼容 +# □ 在测试环境验证所有功能正常 +# □ 检查是否有破坏性变更 + +# 推荐的更新流程: +# 1. 运行 ./check-image-versions.sh 检查最新版本 +# 2. 更新 image-versions.env 配置文件 +# 3. 运行 ./update-image-versions.sh --dry-run 预览更改 +# 4. 运行 ./update-image-versions.sh --backup 执行更新 +# 5. 在测试环境验证兼容性 +# 6. 更新离线部署包 \ No newline at end of file diff --git a/deploy/docker/nginx/Dockerfile b/deploy/docker/nginx/Dockerfile index abae4f3c..d2e3a48e 100644 --- a/deploy/docker/nginx/Dockerfile +++ b/deploy/docker/nginx/Dockerfile @@ -1,5 +1,5 @@ # 多阶段构建 - 前端构建阶段 -FROM node:18-alpine AS frontend-builder +FROM node:lts-alpine AS frontend-builder # 设置工作目录 WORKDIR /app @@ -13,7 +13,7 @@ COPY qaup-ui/ ./ RUN npm run build:prod # Nginx 运行阶段 -FROM nginx:alpine +FROM nginx:stable-alpine # 安装必要工具 RUN apk add --no-cache curl @@ -26,10 +26,10 @@ RUN mkdir -p /var/cache/nginx/client_temp && \ COPY --from=frontend-builder /app/dist /usr/share/nginx/html # 复制 Nginx 配置文件 -COPY docker/nginx/nginx.conf /etc/nginx/nginx.conf -COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf -COPY docker/nginx/nginx-env.conf.template /etc/nginx/conf.d/nginx-env.conf.template -COPY docker/nginx/start-nginx.sh /start-nginx.sh +COPY deploy/docker/nginx/nginx.conf /etc/nginx/nginx.conf +COPY deploy/docker/nginx/default.conf /etc/nginx/conf.d/default.conf +COPY deploy/docker/nginx/nginx-env.conf.template /etc/nginx/conf.d/nginx-env.conf.template +COPY deploy/docker/nginx/start-nginx.sh /start-nginx.sh # 设置执行权限 RUN chmod +x /start-nginx.sh diff --git a/deploy/docker/postgres/backup-db.sh b/deploy/docker/postgres/backup-db.sh deleted file mode 100755 index 4f11b349..00000000 --- a/deploy/docker/postgres/backup-db.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -# QAUP 数据库备份脚本 - -set -e - -# 配置变量 -BACKUP_DIR="/backup" -DB_NAME="${POSTGRES_DB:-qaup}" -DB_USER="${POSTGRES_USER:-postgres}" -TIMESTAMP=$(date +%Y%m%d_%H%M%S) -BACKUP_FILE="qaup_backup_${TIMESTAMP}.sql" -BACKUP_PATH="$BACKUP_DIR/$BACKUP_FILE" - -echo "=========================================" -echo "QAUP 数据库备份开始" -echo "=========================================" - -# 创建备份目录 -mkdir -p "$BACKUP_DIR" - -# 执行备份 -echo "备份数据库: $DB_NAME" -echo "备份文件: $BACKUP_PATH" - -pg_dump -h localhost -U "$DB_USER" -d "$DB_NAME" \ - --verbose \ - --clean \ - --if-exists \ - --create \ - --format=plain \ - --encoding=UTF8 \ - > "$BACKUP_PATH" - -# 压缩备份文件 -echo "压缩备份文件..." -gzip "$BACKUP_PATH" -COMPRESSED_FILE="${BACKUP_PATH}.gz" - -# 显示备份信息 -echo "" -echo "=========================================" -echo "备份完成信息:" -echo "=========================================" -echo "备份文件: $COMPRESSED_FILE" -echo "文件大小: $(du -h "$COMPRESSED_FILE" | cut -f1)" -echo "备份时间: $(date)" - -# 清理旧备份(保留最近7天) -echo "" -echo "清理旧备份文件(保留7天)..." -find "$BACKUP_DIR" -name "qaup_backup_*.sql.gz" -mtime +7 -delete -echo "清理完成" - -echo "" -echo "数据库备份完成!" \ No newline at end of file diff --git a/deploy/docker/postgres/db-manager.sh b/deploy/docker/postgres/db-manager.sh new file mode 100644 index 00000000..c2b8084a --- /dev/null +++ b/deploy/docker/postgres/db-manager.sh @@ -0,0 +1,650 @@ +#!/bin/bash + +# QAUP 数据库管理脚本 +# 统一管理数据库相关的所有操作:导出、导入、备份、恢复、健康检查等 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# 默认配置 +DB_HOST=${DB_HOST:-localhost} +DB_PORT=${DB_PORT:-5432} +DB_NAME=${DB_NAME:-qaup} +DB_USER=${DB_USER:-postgres} +EXPORT_DIR=${EXPORT_DIR:-$SCRIPT_DIR/export} + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_message() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +# 显示帮助信息 +show_help() { + echo "QAUP 数据库管理脚本" + echo "" + echo "用法: $0 <命令> [选项]" + echo "" + echo "数据管理命令:" + echo " prepare-default 准备默认初始数据" + echo " prepare-export 从现有数据库导出并准备数据" + echo " prepare-custom 自定义数据组合" + echo " prepare-status 显示数据文件状态" + echo " prepare-clean 清理数据文件" + echo "" + echo "导出命令:" + echo " export-all 导出完整数据库" + echo " export-schema 仅导出表结构" + echo " export-data 仅导出数据" + echo " export-initial 导出分层初始数据(推荐)" + echo "" + echo "备份恢复命令:" + echo " backup 备份数据库" + echo " restore 恢复数据库" + echo "" + echo "维护命令:" + echo " health 健康检查" + echo " test-connection 测试数据库连接" + echo "" + echo "环境变量:" + echo " DB_HOST 数据库主机(默认:localhost)" + echo " DB_PORT 数据库端口(默认:5432)" + echo " DB_NAME 数据库名称(默认:qaup)" + echo " DB_USER 数据库用户(默认:postgres)" + echo " EXPORT_DIR 导出目录(默认:./export)" + echo "" + echo "示例:" + echo " $0 prepare-default # 准备默认数据" + echo " $0 prepare-export # 从现有系统导出数据" + echo " $0 export-initial # 导出分层初始数据" + echo " $0 backup # 备份数据库" + echo " $0 health # 健康检查" +} + +# ========================================== +# 数据准备功能 +# ========================================== + +# 显示数据文件状态 +show_data_status() { + print_message $BLUE "当前数据文件状态:" + echo "" + + local files=( + "initial_data.sql:实际使用的初始数据" + "initial_data.template.sql:默认数据模板" + "01_system_data.sql:系统配置数据" + "02_business_data.sql:业务基础数据" + "03_sample_data.sql:示例数据" + ) + + for file_info in "${files[@]}"; do + local file="${file_info%%:*}" + local desc="${file_info##*:}" + local path="$SCRIPT_DIR/$file" + + if [ -f "$path" ]; then + local size=$(du -h "$path" | cut -f1) + local lines=$(wc -l < "$path") + printf " %-25s %s %8s %6s 行 - %s\n" "$file" "✓" "$size" "$lines" "$desc" + else + printf " %-25s %s %8s %6s - %s\n" "$file" "✗" "-" "-" "$desc" + fi + done + + echo "" + + if [ -f "$SCRIPT_DIR/initial_data.sql" ]; then + print_message $GREEN "部署时将使用: initial_data.sql" + else + print_message $YELLOW "部署时将按顺序使用分层数据文件" + fi +} + +# 准备默认数据 +prepare_default_data() { + print_message $BLUE "准备默认模板数据..." + + if [ ! -f "$SCRIPT_DIR/initial_data.template.sql" ]; then + print_message $RED "错误: 默认模板文件不存在" + exit 1 + fi + + cp "$SCRIPT_DIR/initial_data.template.sql" "$SCRIPT_DIR/initial_data.sql" + + print_message $GREEN "✓ 已准备默认数据" + print_message $YELLOW "默认管理员账号: admin" + print_message $YELLOW "默认管理员密码: admin123" +} + +# 从现有数据库导出并准备数据 +prepare_export_data() { + print_message $BLUE "从现有数据库导出数据..." + + # 检查连接参数 + if [ -z "$DB_HOST" ] || [ -z "$DB_NAME" ] || [ -z "$DB_USER" ]; then + print_message $YELLOW "请设置数据库连接环境变量或使用默认值" + echo "当前设置:" + echo " DB_HOST=$DB_HOST" + echo " DB_PORT=$DB_PORT" + echo " DB_NAME=$DB_NAME" + echo " DB_USER=$DB_USER" + echo "" + read -p "是否继续? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + fi + + # 测试连接 + test_database_connection + + # 导出分层数据 + export_initial_data + + # 使用导出的完整数据 + if [ -f "$EXPORT_DIR/initial_data_complete.sql" ]; then + cp "$EXPORT_DIR/initial_data_complete.sql" "$SCRIPT_DIR/initial_data.sql" + print_message $GREEN "✓ 已导出并准备完整初始数据" + else + print_message $RED "错误: 导出失败" + exit 1 + fi +} + +# 自定义数据组合 +prepare_custom_data() { + print_message $BLUE "自定义数据组合..." + + local system_data="$SCRIPT_DIR/01_system_data.sql" + local business_data="$SCRIPT_DIR/02_business_data.sql" + local sample_data="$SCRIPT_DIR/03_sample_data.sql" + + if [ ! -f "$system_data" ]; then + print_message $RED "错误: 未找到系统数据文件,请先导出数据" + print_message $YELLOW "提示: $0 export-initial" + exit 1 + fi + + echo "请选择要包含的数据类型:" + echo "1. 系统配置数据 (必需) ✓" + echo "2. 业务基础数据" + echo "3. 示例数据" + echo "" + + local include_business=false + local include_sample=false + + if [ -f "$business_data" ]; then + read -p "是否包含业务基础数据? (Y/n): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Nn]$ ]]; then + include_business=true + fi + fi + + if [ -f "$sample_data" ]; then + read -p "是否包含示例数据? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + include_sample=true + fi + fi + + # 生成自定义数据文件 + local output_file="$SCRIPT_DIR/initial_data.sql" + + cat > "$output_file" << 'EOF' +-- QAUP 自定义初始数据组合 +-- 此文件由 db-manager.sh 自动生成 + +EOF + + # 添加系统数据 + echo "-- 系统基础配置数据" >> "$output_file" + cat "$system_data" >> "$output_file" + print_message $GREEN "✓ 已包含系统配置数据" + + # 添加业务数据 + if [ "$include_business" = true ] && [ -f "$business_data" ]; then + echo "-- 业务基础数据" >> "$output_file" + cat "$business_data" >> "$output_file" + print_message $GREEN "✓ 已包含业务基础数据" + fi + + # 添加示例数据 + if [ "$include_sample" = true ] && [ -f "$sample_data" ]; then + echo "-- 示例数据" >> "$output_file" + cat "$sample_data" >> "$output_file" + print_message $GREEN "✓ 已包含示例数据" + fi + + print_message $GREEN "✓ 自定义数据组合完成" +} + +# 清理数据文件 +clean_data_files() { + print_message $YELLOW "清理数据文件..." + + read -p "确定要清理所有数据文件吗? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + return + fi + + local files_to_clean=( + "initial_data.sql" + "01_system_data.sql" + "02_business_data.sql" + "03_sample_data.sql" + ) + + for file in "${files_to_clean[@]}"; do + local path="$SCRIPT_DIR/$file" + if [ -f "$path" ]; then + rm "$path" + print_message $GREEN "✓ 已删除 $file" + fi + done + + if [ -d "$EXPORT_DIR" ]; then + rm -rf "$EXPORT_DIR" + print_message $GREEN "✓ 已清理导出目录" + fi +} + +# ========================================== +# 数据导出功能 +# ========================================== + +# 测试数据库连接 +test_database_connection() { + print_message $BLUE "测试数据库连接..." + + if command -v pg_isready &> /dev/null; then + if pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" &>/dev/null; then + print_message $GREEN "✓ 数据库连接成功" + else + print_message $RED "✗ 数据库连接失败" + exit 1 + fi + else + print_message $YELLOW "警告: pg_isready 不可用,跳过连接测试" + fi +} + +# 导出完整数据库 +export_all_data() { + print_message $BLUE "导出完整数据库..." + + test_database_connection + mkdir -p "$EXPORT_DIR" + + local output_file="$EXPORT_DIR/qaup_complete_backup.sql" + + pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ + --no-owner --no-privileges --clean --if-exists \ + > "$output_file" + + print_message $GREEN "✓ 完整数据库导出完成: $output_file" +} + +# 导出表结构 +export_schema_only() { + print_message $BLUE "导出数据库表结构..." + + test_database_connection + mkdir -p "$EXPORT_DIR" + + local output_file="$EXPORT_DIR/qaup_database_schema.sql" + + pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ + --schema-only --no-owner --no-privileges --clean --if-exists \ + > "$output_file" + + print_message $GREEN "✓ 表结构导出完成: $output_file" +} + +# 导出分层初始数据 +export_initial_data() { + print_message $BLUE "导出分层初始数据..." + + test_database_connection + mkdir -p "$EXPORT_DIR" + + # 导出系统基础数据 + export_system_data + + # 导出业务基础数据 + export_business_data + + # 导出示例数据 + export_sample_data + + # 生成合并文件 + generate_combined_data +} + +# 导出系统基础数据 +export_system_data() { + local output_file="$EXPORT_DIR/01_system_data.sql" + local system_tables=( + "sys_config" "sys_dict_type" "sys_dict_data" "sys_dept" "sys_post" + "sys_role" "sys_menu" "sys_user" "sys_user_role" "sys_user_post" + "sys_role_menu" "sys_role_dept" "sys_notice" + ) + + local table_args="" + for table in "${system_tables[@]}"; do + table_args="$table_args --table=$table" + done + + cat > "$output_file" << 'EOF' +-- QAUP 系统基础配置数据 +SET session_replication_role = replica; +EOF + + pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ + --data-only --no-owner --no-privileges --disable-triggers --inserts \ + $table_args >> "$output_file" + + cat >> "$output_file" << 'EOF' +SET session_replication_role = DEFAULT; +EOF + + print_message $GREEN "✓ 系统基础数据导出完成" +} + +# 导出业务基础数据 +export_business_data() { + local output_file="$EXPORT_DIR/02_business_data.sql" + local business_tables=( + "sys_vehicle_type" "airport_areas" "spatial_rules" + "spatial_rule_vehicle_types" "transport_routes" + ) + + local table_args="" + for table in "${business_tables[@]}"; do + table_args="$table_args --table=$table" + done + + cat > "$output_file" << 'EOF' +-- QAUP 业务基础数据 +SET session_replication_role = replica; +EOF + + pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ + --data-only --no-owner --no-privileges --disable-triggers --inserts \ + $table_args >> "$output_file" 2>/dev/null || true + + cat >> "$output_file" << 'EOF' +SET session_replication_role = DEFAULT; +EOF + + print_message $GREEN "✓ 业务基础数据导出完成" +} + +# 导出示例数据 +export_sample_data() { + local output_file="$EXPORT_DIR/03_sample_data.sql" + local sample_tables=("sys_vehicle_info") + + local table_args="" + for table in "${sample_tables[@]}"; do + table_args="$table_args --table=$table" + done + + cat > "$output_file" << 'EOF' +-- QAUP 示例数据 +SET session_replication_role = replica; +EOF + + pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ + --data-only --no-owner --no-privileges --disable-triggers --inserts \ + $table_args >> "$output_file" 2>/dev/null || true + + cat >> "$output_file" << 'EOF' +SET session_replication_role = DEFAULT; +EOF + + print_message $GREEN "✓ 示例数据导出完成" +} + +# 生成合并的完整数据文件 +generate_combined_data() { + local combined_file="$EXPORT_DIR/initial_data_complete.sql" + + cat > "$combined_file" << 'EOF' +-- QAUP 系统完整初始数据 +-- 此文件由 db-manager.sh 自动生成 + +EOF + + for data_file in "01_system_data.sql" "02_business_data.sql" "03_sample_data.sql"; do + if [ -f "$EXPORT_DIR/$data_file" ]; then + cat "$EXPORT_DIR/$data_file" >> "$combined_file" + echo "" >> "$combined_file" + fi + done + + print_message $GREEN "✓ 完整初始数据文件生成完成: $combined_file" +} + +# ========================================== +# 备份恢复功能 +# ========================================== + +# 备份数据库 +backup_database() { + print_message $BLUE "备份数据库..." + + local timestamp=$(date +%Y%m%d_%H%M%S) + local backup_dir="$PROJECT_ROOT/backup/postgres" + local backup_file="$backup_dir/qaup_backup_$timestamp.sql" + + mkdir -p "$backup_dir" + + # 检查是否在容器内 + if [ -f "/.dockerenv" ]; then + # 在容器内执行备份 + pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" \ + --no-owner --no-privileges > "$backup_file" + else + # 在容器外执行备份 + test_database_connection + pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ + --no-owner --no-privileges > "$backup_file" + fi + + print_message $GREEN "✓ 数据库备份完成: $backup_file" +} + +# 恢复数据库 +restore_database() { + local backup_file=$1 + + if [ -z "$backup_file" ]; then + print_message $RED "错误: 请指定备份文件" + exit 1 + fi + + if [ ! -f "$backup_file" ]; then + print_message $RED "错误: 备份文件不存在: $backup_file" + exit 1 + fi + + print_message $BLUE "恢复数据库..." + print_message $YELLOW "警告: 这将覆盖现有数据" + + read -p "确定要继续吗? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + + # 检查是否在容器内 + if [ -f "/.dockerenv" ]; then + # 在容器内执行恢复 + psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -f "$backup_file" + else + # 在容器外执行恢复 + test_database_connection + psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$backup_file" + fi + + print_message $GREEN "✓ 数据库恢复完成" +} + +# ========================================== +# 健康检查功能 +# ========================================== + +# 健康检查 +health_check() { + print_message $BLUE "数据库健康检查..." + + # 检查是否在容器内 + if [ -f "/.dockerenv" ]; then + # 容器内健康检查 + container_health_check + else + # 容器外健康检查 + external_health_check + fi +} + +# 容器内健康检查 +container_health_check() { + local errors=0 + + # 检查 PostgreSQL 进程 + if pgrep -x postgres > /dev/null; then + print_message $GREEN "✓ PostgreSQL 进程运行正常" + else + print_message $RED "✗ PostgreSQL 进程未运行" + errors=$((errors + 1)) + fi + + # 检查数据库连接 + if psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 1;" > /dev/null 2>&1; then + print_message $GREEN "✓ 数据库连接正常" + else + print_message $RED "✗ 数据库连接失败" + errors=$((errors + 1)) + fi + + # 检查表数量 + local table_count=$(psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | tr -d ' ') + if [ "$table_count" -gt 0 ]; then + print_message $GREEN "✓ 数据库包含 $table_count 个表" + else + print_message $RED "✗ 数据库中没有表" + errors=$((errors + 1)) + fi + + if [ $errors -eq 0 ]; then + print_message $GREEN "数据库健康检查通过" + else + print_message $RED "数据库健康检查失败,发现 $errors 个问题" + exit 1 + fi +} + +# 容器外健康检查 +external_health_check() { + test_database_connection + + # 检查表数量 + local table_count=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';" 2>/dev/null | tr -d ' ') + if [ "$table_count" -gt 0 ]; then + print_message $GREEN "✓ 数据库包含 $table_count 个表" + else + print_message $RED "✗ 数据库中没有表" + exit 1 + fi + + print_message $GREEN "数据库健康检查通过" +} + +# ========================================== +# 主函数 +# ========================================== + +main() { + if [ $# -eq 0 ]; then + show_help + exit 0 + fi + + local command=$1 + shift + + case $command in + # 数据准备命令 + prepare-default) + prepare_default_data + ;; + prepare-export) + prepare_export_data + ;; + prepare-custom) + prepare_custom_data + ;; + prepare-status) + show_data_status + ;; + prepare-clean) + clean_data_files + ;; + + # 导出命令 + export-all) + export_all_data + ;; + export-schema) + export_schema_only + ;; + export-initial) + export_initial_data + ;; + + # 备份恢复命令 + backup) + backup_database + ;; + restore) + restore_database "$@" + ;; + + # 维护命令 + health) + health_check + ;; + test-connection) + test_database_connection + ;; + + # 帮助 + help|--help|-h) + show_help + ;; + + *) + print_message $RED "未知命令: $command" + show_help + exit 1 + ;; + esac +} + +main "$@" \ No newline at end of file diff --git a/deploy/docker/postgres/health-check.sh b/deploy/docker/postgres/health-check.sh deleted file mode 100755 index 7f31ee43..00000000 --- a/deploy/docker/postgres/health-check.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# PostgreSQL 健康检查脚本 - -set -e - -DB_NAME="${POSTGRES_DB:-qaup}" -DB_USER="${POSTGRES_USER:-postgres}" - -# 检查 PostgreSQL 服务是否运行 -if ! pg_isready -h localhost -p 5432 -U "$DB_USER" -d "$DB_NAME" -q; then - echo "PostgreSQL 服务未就绪" - exit 1 -fi - -# 检查数据库连接 -if ! psql -h localhost -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" > /dev/null 2>&1; then - echo "数据库连接失败" - exit 1 -fi - -# 检查 PostGIS 扩展 -if ! psql -h localhost -U "$DB_USER" -d "$DB_NAME" -c "SELECT PostGIS_Version();" > /dev/null 2>&1; then - echo "PostGIS 扩展不可用" - exit 1 -fi - -echo "数据库健康检查通过" -exit 0 \ No newline at end of file diff --git a/deploy/docker/postgres/init-db.sh b/deploy/docker/postgres/init-db.sh index dc2b1576..280788c2 100755 --- a/deploy/docker/postgres/init-db.sh +++ b/deploy/docker/postgres/init-db.sh @@ -32,11 +32,39 @@ else echo "警告: 未找到数据库架构文件" fi -# 导入初始数据(如果存在) -if [ -f "/docker-entrypoint-initdb.d/initial_data.sql" ]; then - echo "导入初始数据..." - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -f /docker-entrypoint-initdb.d/initial_data.sql - echo "✓ 初始数据导入完成" +# 导入初始数据(按优先级顺序) +data_files=( + "/docker-entrypoint-initdb.d/initial_data.sql" + "/docker-entrypoint-initdb.d/01_system_data.sql" + "/docker-entrypoint-initdb.d/02_business_data.sql" + "/docker-entrypoint-initdb.d/03_sample_data.sql" +) + +for data_file in "${data_files[@]}"; do + if [ -f "$data_file" ]; then + echo "导入数据文件: $(basename "$data_file")" + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -f "$data_file" + echo "✓ $(basename "$data_file") 导入完成" + + # 如果找到 initial_data.sql,就不再导入其他文件 + if [[ "$data_file" == *"initial_data.sql" ]]; then + break + fi + fi +done + +# 检查是否导入了任何数据 +imported_any=false +for data_file in "${data_files[@]}"; do + if [ -f "$data_file" ]; then + imported_any=true + break + fi +done + +if [ "$imported_any" = false ]; then + echo "警告: 未找到初始数据文件,系统将使用空数据库启动" + echo "建议从现有系统导出数据或使用默认初始数据" fi # 创建数据库用户和权限设置 diff --git a/deploy/docker/postgres/initial_data.template.sql b/deploy/docker/postgres/initial_data.template.sql new file mode 100644 index 00000000..4f46fa4c --- /dev/null +++ b/deploy/docker/postgres/initial_data.template.sql @@ -0,0 +1,305 @@ +-- QAUP 系统初始数据 +-- 包含系统运行所需的基础数据 + +-- ========================================== +-- 系统配置数据 +-- ========================================== + +-- 插入系统配置参数 +INSERT INTO sys_config (config_id, config_name, config_key, config_value, config_type, create_by, create_time, remark) VALUES +(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', NOW(), '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow'), +(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', NOW(), '初始化密码 123456'), +(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', NOW(), '深色主题theme-dark,浅色主题theme-light'), +(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', NOW(), '是否开启验证码功能(true开启,false关闭)'), +(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', NOW(), '是否开启注册用户功能(true开启,false关闭)'), +(6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', NOW(), '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)'); + +-- ========================================== +-- 字典类型数据 +-- ========================================== + +-- 插入字典类型 +INSERT INTO sys_dict_type (dict_id, dict_name, dict_type, status, create_by, create_time, remark) VALUES +(1, '用户性别', 'sys_user_sex', '0', 'admin', NOW(), '用户性别列表'), +(2, '菜单状态', 'sys_show_hide', '0', 'admin', NOW(), '菜单状态列表'), +(3, '系统开关', 'sys_normal_disable', '0', 'admin', NOW(), '系统开关列表'), +(4, '任务状态', 'sys_job_status', '0', 'admin', NOW(), '任务状态列表'), +(5, '任务分组', 'sys_job_group', '0', 'admin', NOW(), '任务分组列表'), +(6, '系统是否', 'sys_yes_no', '0', 'admin', NOW(), '系统是否列表'), +(7, '通知类型', 'sys_notice_type', '0', 'admin', NOW(), '通知类型列表'), +(8, '通知状态', 'sys_notice_status', '0', 'admin', NOW(), '通知状态列表'), +(9, '操作类型', 'sys_oper_type', '0', 'admin', NOW(), '操作类型列表'), +(10, '系统状态', 'sys_common_status', '0', 'admin', NOW(), '登录状态列表'), +(11, '车辆类型', 'sys_vehicle_type', '0', 'admin', NOW(), '车辆类型列表'), +(12, '告警级别', 'sys_alert_level', '0', 'admin', NOW(), '告警级别列表'), +(13, '违规类型', 'sys_violation_type', '0', 'admin', NOW(), '违规类型列表'); + +-- ========================================== +-- 字典数据 +-- ========================================== + +-- 用户性别 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', NOW(), '性别男'), +(2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', NOW(), '性别女'), +(3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', NOW(), '性别未知'); + +-- 菜单状态 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', NOW(), '显示菜单'), +(5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', NOW(), '隐藏菜单'); + +-- 系统开关 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', NOW(), '正常状态'), +(7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', NOW(), '停用状态'); + +-- 系统是否 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(8, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', NOW(), '系统默认是'), +(9, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', NOW(), '系统默认否'); + +-- 通知类型 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(10, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', NOW(), '通知'), +(11, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', NOW(), '公告'); + +-- 通知状态 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(12, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', NOW(), '正常状态'), +(13, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', NOW(), '关闭状态'); + +-- 操作类型 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(14, 1, '其他', '0', 'sys_oper_type', '', 'info', 'N', '0', 'admin', NOW(), '其他操作'), +(15, 2, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', NOW(), '新增操作'), +(16, 3, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', NOW(), '修改操作'), +(17, 4, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', NOW(), '删除操作'), +(18, 5, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', NOW(), '授权操作'), +(19, 6, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', NOW(), '导出操作'), +(20, 7, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', NOW(), '导入操作'), +(21, 8, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', NOW(), '强退操作'), +(22, 9, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', NOW(), '生成操作'), +(23, 10, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', NOW(), '清空操作'); + +-- 系统状态 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(24, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', NOW(), '正常状态'), +(25, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', NOW(), '停用状态'); + +-- 告警级别 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(26, 1, '信息', 'INFO', 'sys_alert_level', '', 'info', 'N', '0', 'admin', NOW(), '信息级别'), +(27, 2, '警告', 'WARNING', 'sys_alert_level', '', 'warning', 'N', '0', 'admin', NOW(), '警告级别'), +(28, 3, '严重', 'CRITICAL', 'sys_alert_level', '', 'danger', 'N', '0', 'admin', NOW(), '严重级别'), +(29, 4, '紧急', 'EMERGENCY', 'sys_alert_level', '', 'danger', 'N', '0', 'admin', NOW(), '紧急级别'); + +-- 违规类型 +INSERT INTO sys_dict_data (dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark) VALUES +(30, 1, '超速', 'SPEED', 'sys_violation_type', '', 'warning', 'N', '0', 'admin', NOW(), '超速违规'), +(31, 2, '未授权进入', 'ACCESS', 'sys_violation_type', '', 'danger', 'N', '0', 'admin', NOW(), '未授权进入'), +(32, 3, '超高', 'HEIGHT', 'sys_violation_type', '', 'warning', 'N', '0', 'admin', NOW(), '超高违规'), +(33, 4, '超重', 'WEIGHT', 'sys_violation_type', '', 'warning', 'N', '0', 'admin', NOW(), '超重违规'), +(34, 5, '其他', 'OTHER', 'sys_violation_type', '', 'info', 'N', '0', 'admin', NOW(), '其他违规'); + +-- ========================================== +-- 部门数据 +-- ========================================== + +-- 插入部门信息 +INSERT INTO sys_dept (dept_id, parent_id, ancestors, dept_name, order_num, leader, phone, email, status, del_flag, create_by, create_time) VALUES +(100, 0, '0', 'QAUP管理系统', 0, 'admin', '15888888888', 'admin@qaup.com', '0', '0', 'admin', NOW()), +(101, 100, '0,100', '系统管理部', 1, 'admin', '15888888888', 'admin@qaup.com', '0', '0', 'admin', NOW()), +(102, 100, '0,100', '运营管理部', 2, 'admin', '15888888888', 'admin@qaup.com', '0', '0', 'admin', NOW()), +(103, 101, '0,100,101', '研发部门', 1, 'admin', '15888888888', 'admin@qaup.com', '0', '0', 'admin', NOW()), +(104, 101, '0,100,101', '市场部门', 2, 'admin', '15888888888', 'admin@qaup.com', '0', '0', 'admin', NOW()), +(105, 101, '0,100,101', '测试部门', 3, 'admin', '15888888888', 'admin@qaup.com', '0', '0', 'admin', NOW()); + +-- ========================================== +-- 岗位数据 +-- ========================================== + +-- 插入岗位信息 +INSERT INTO sys_post (post_id, post_code, post_name, post_sort, status, create_by, create_time, remark) VALUES +(1, 'ceo', '董事长', 1, '0', 'admin', NOW(), ''), +(2, 'se', '项目经理', 2, '0', 'admin', NOW(), ''), +(3, 'hr', '人力资源', 3, '0', 'admin', NOW(), ''), +(4, 'user', '普通员工', 4, '0', 'admin', NOW(), ''); + +-- ========================================== +-- 角色数据 +-- ========================================== + +-- 插入角色信息 +INSERT INTO sys_role (role_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_by, create_time, remark) VALUES +(1, '超级管理员', 'admin', 1, '1', true, true, '0', '0', 'admin', NOW(), '超级管理员'), +(2, '普通角色', 'common', 2, '2', true, true, '0', '0', 'admin', NOW(), '普通角色'); + +-- ========================================== +-- 菜单数据 +-- ========================================== + +-- 插入菜单信息(主要菜单结构) +INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES +-- 系统管理 +(1, '系统管理', 0, 1, 'system', NULL, '', '', 1, 0, 'M', '0', 0, '', 'system', 'admin', NOW(), '系统管理目录'), +(100, '用户管理', 1, 1, 'user', 'system/user/index', '', '', 1, 0, 'C', '0', 0, 'system:user:list', 'user', 'admin', NOW(), '用户管理菜单'), +(101, '角色管理', 1, 2, 'role', 'system/role/index', '', '', 1, 0, 'C', '0', 0, 'system:role:list', 'peoples', 'admin', NOW(), '角色管理菜单'), +(102, '菜单管理', 1, 3, 'menu', 'system/menu/index', '', '', 1, 0, 'C', '0', 0, 'system:menu:list', 'tree-table', 'admin', NOW(), '菜单管理菜单'), +(103, '部门管理', 1, 4, 'dept', 'system/dept/index', '', '', 1, 0, 'C', '0', 0, 'system:dept:list', 'tree', 'admin', NOW(), '部门管理菜单'), +(104, '岗位管理', 1, 5, 'post', 'system/post/index', '', '', 1, 0, 'C', '0', 0, 'system:post:list', 'post', 'admin', NOW(), '岗位管理菜单'), +(105, '字典管理', 1, 6, 'dict', 'system/dict/index', '', '', 1, 0, 'C', '0', 0, 'system:dict:list', 'dict', 'admin', NOW(), '字典管理菜单'), +(106, '参数设置', 1, 7, 'config', 'system/config/index', '', '', 1, 0, 'C', '0', 0, 'system:config:list', 'edit', 'admin', NOW(), '参数设置菜单'), +(107, '通知公告', 1, 8, 'notice', 'system/notice/index', '', '', 1, 0, 'C', '0', 0, 'system:notice:list', 'message', 'admin', NOW(), '通知公告菜单'), +(108, '日志管理', 1, 9, 'log', '', '', '', 1, 0, 'M', '0', 0, '', 'log', 'admin', NOW(), '日志管理菜单'), +(500, '操作日志', 108, 1, 'operlog', 'monitor/operlog/index', '', '', 1, 0, 'C', '0', 0, 'monitor:operlog:list', 'form', 'admin', NOW(), '操作日志菜单'), +(501, '登录日志', 108, 2, 'logininfor', 'monitor/logininfor/index', '', '', 1, 0, 'C', '0', 0, 'monitor:logininfor:list', 'logininfor', 'admin', NOW(), '登录日志菜单'), + +-- 车辆管理 +(2, '车辆管理', 0, 2, 'vehicle', NULL, '', '', 1, 0, 'M', '0', 0, '', 'guide', 'admin', NOW(), '车辆管理目录'), +(200, '车辆信息', 2, 1, 'info', 'vehicle/info/index', '', '', 1, 0, 'C', '0', 0, 'vehicle:info:list', 'tree-table', 'admin', NOW(), '车辆信息菜单'), +(201, '车辆类型', 2, 2, 'type', 'vehicle/type/index', '', '', 1, 0, 'C', '0', 0, 'vehicle:type:list', 'dict', 'admin', NOW(), '车辆类型菜单'), + +-- 监控管理 +(3, '监控管理', 0, 3, 'monitor', NULL, '', '', 1, 0, 'M', '0', 0, '', 'monitor', 'admin', NOW(), '监控管理目录'), +(300, '实时监控', 3, 1, 'realtime', 'monitor/realtime/index', '', '', 1, 0, 'C', '0', 0, 'monitor:realtime:view', 'online', 'admin', NOW(), '实时监控菜单'), +(301, '告警管理', 3, 2, 'alert', 'monitor/alert/index', '', '', 1, 0, 'C', '0', 0, 'monitor:alert:list', 'message', 'admin', NOW(), '告警管理菜单'); + +-- ========================================== +-- 用户数据 +-- ========================================== + +-- 插入管理员用户(密码:admin123,已加密) +INSERT INTO sys_user (user_id, dept_id, user_name, user_type, email, phonenumber, sex, avatar, password, status, del_flag, create_by, create_time, remark) VALUES +(1, 103, 'admin', '00', 'admin@qaup.com', '15888888888', '1', '', '$2a$10$7JB720yubVSOfvVMe6/YqOsrtwt07CFgLjxkKyQbCpTHWpK7S/pSe', '0', '0', 'admin', NOW(), '管理员'); + +-- 用户角色关联 +INSERT INTO sys_user_role (user_id, role_id) VALUES (1, 1); + +-- 用户岗位关联 +INSERT INTO sys_user_post (user_id, post_id) VALUES (1, 1); + +-- 角色菜单关联(超级管理员拥有所有菜单权限) +INSERT INTO sys_role_menu (role_id, menu_id) VALUES +(1, 1), (1, 100), (1, 101), (1, 102), (1, 103), (1, 104), (1, 105), (1, 106), (1, 107), (1, 108), (1, 500), (1, 501), +(1, 2), (1, 200), (1, 201), +(1, 3), (1, 300), (1, 301); + +-- ========================================== +-- 车辆类型数据 +-- ========================================== + +-- 插入车辆类型数据(基于路径编码模式) +INSERT INTO sys_vehicle_type (id, type_code, type_name, display_name_cn, display_name_en, path_level, parent_code, full_path, is_leaf, sort_order, enabled, description, create_by, create_time) VALUES +-- 一级分类 +(1, 'UV', 'UNMANNED_VEHICLE', '无人车', 'Unmanned Vehicle', 1, NULL, '无人车', false, 1, true, '机场无人驾驶车辆', 'admin', NOW()), +(2, 'SP', 'SPECIAL_VEHICLE', '特种车辆', 'Special Vehicle', 1, NULL, '特种车辆', false, 2, true, '机场特种作业车辆', 'admin', NOW()), +(3, 'NV', 'NORMAL_VEHICLE', '普通车辆', 'Normal Vehicle', 1, NULL, '普通车辆', false, 3, true, '机场普通车辆', 'admin', NOW()), + +-- 无人车二级分类 +(4, 'UV.PT', 'PATROL', '巡逻车', 'Patrol Vehicle', 2, 'UV', '无人车 > 巡逻车', true, 1, true, '无人巡逻车', 'admin', NOW()), +(5, 'UV.CL', 'CLEANING', '清洁车', 'Cleaning Vehicle', 2, 'UV', '无人车 > 清洁车', true, 2, true, '无人清洁车', 'admin', NOW()), +(6, 'UV.TR', 'TRANSPORT', '运输车', 'Transport Vehicle', 2, 'UV', '无人车 > 运输车', true, 3, true, '无人运输车', 'admin', NOW()), + +-- 特种车辆二级分类 +(7, 'SP.FF', 'FIRE_FIGHTING', '消防车', 'Fire Fighting Vehicle', 2, 'SP', '特种车辆 > 消防车', true, 1, true, '消防救援车辆', 'admin', NOW()), +(8, 'SP.AM', 'AMBULANCE', '救护车', 'Ambulance', 2, 'SP', '特种车辆 > 救护车', true, 2, true, '医疗救护车辆', 'admin', NOW()), +(9, 'SP.MT', 'MAINTENANCE', '维修车', 'Maintenance Vehicle', 2, 'SP', '特种车辆 > 维修车', true, 3, true, '设备维修车辆', 'admin', NOW()), + +-- 普通车辆二级分类 +(10, 'NV.BU', 'BUS', '班车', 'Bus', 2, 'NV', '普通车辆 > 班车', true, 1, true, '员工班车', 'admin', NOW()), +(11, 'NV.CA', 'CAR', '轿车', 'Car', 2, 'NV', '普通车辆 > 轿车', true, 2, true, '普通轿车', 'admin', NOW()), +(12, 'NV.VN', 'VAN', '面包车', 'Van', 2, 'NV', '普通车辆 > 面包车', true, 3, true, '面包车', 'admin', NOW()); + +-- ========================================== +-- 机场区域数据(示例) +-- ========================================== + +-- 插入示例机场区域 +INSERT INTO airport_areas (id, area_id, name, type, boundary, description, enabled, priority, area_sqm, functional_category, created_at, updated_at) VALUES +(1, 'RUNWAY_01', '01号跑道', 'RUNWAY', + ST_GeomFromText('POLYGON((116.3 39.9, 116.4 39.9, 116.4 39.95, 116.3 39.95, 116.3 39.9))', 4326), + '主跑道区域', true, 10, 50000, 'FLIGHT_OPERATIONS', NOW(), NOW()), +(2, 'TAXIWAY_A', 'A滑行道', 'TAXIWAY', + ST_GeomFromText('POLYGON((116.35 39.92, 116.38 39.92, 116.38 39.93, 116.35 39.93, 116.35 39.92))', 4326), + 'A滑行道区域', true, 8, 15000, 'FLIGHT_OPERATIONS', NOW(), NOW()), +(3, 'APRON_01', '01号停机坪', 'APRON', + ST_GeomFromText('POLYGON((116.32 39.88, 116.36 39.88, 116.36 39.91, 116.32 39.91, 116.32 39.88))', 4326), + '01号停机坪区域', true, 6, 30000, 'AIRCRAFT_PARKING', NOW(), NOW()); + +-- ========================================== +-- 空间规则数据(示例) +-- ========================================== + +-- 插入示例空间规则 +INSERT INTO spatial_rules (rule_id, rule_name, description, rule_category, status, priority, spatial_object_type, spatial_object_id, rule_parameters, alert_level, alert_message, created_at, updated_at, created_by) VALUES +('SPEED_LIMIT_RUNWAY', '跑道限速规则', '跑道区域车辆限速5km/h', 'SPEED_LIMIT', 'ACTIVE', 10, 'AREA', 'RUNWAY_01', + '{"maxSpeed": 5.0, "warningThreshold": 4.0}', 'CRITICAL', '车辆在跑道区域超速', NOW(), NOW(), 'admin'), +('SPEED_LIMIT_TAXIWAY', '滑行道限速规则', '滑行道区域车辆限速10km/h', 'SPEED_LIMIT', 'ACTIVE', 8, 'AREA', 'TAXIWAY_A', + '{"maxSpeed": 10.0, "warningThreshold": 8.0}', 'WARNING', '车辆在滑行道区域超速', NOW(), NOW(), 'admin'), +('ACCESS_CONTROL_RUNWAY', '跑道准入控制', '只允许特种车辆进入跑道', 'ACCESS_CONTROL', 'ACTIVE', 10, 'AREA', 'RUNWAY_01', + '{"allowedVehicleTypes": ["SP"]}', 'CRITICAL', '未授权车辆进入跑道区域', NOW(), NOW(), 'admin'); + +-- 规则适用车辆类型关联 +INSERT INTO spatial_rule_vehicle_types (rule_id, vehicle_type) VALUES +('SPEED_LIMIT_RUNWAY', 'SP.FF'), +('SPEED_LIMIT_RUNWAY', 'SP.AM'), +('SPEED_LIMIT_RUNWAY', 'SP.MT'), +('SPEED_LIMIT_TAXIWAY', 'UV.PT'), +('SPEED_LIMIT_TAXIWAY', 'UV.CL'), +('SPEED_LIMIT_TAXIWAY', 'SP.FF'), +('ACCESS_CONTROL_RUNWAY', 'SP.FF'), +('ACCESS_CONTROL_RUNWAY', 'SP.AM'); + +-- ========================================== +-- 示例车辆数据 +-- ========================================== + +-- 插入示例车辆信息 +INSERT INTO sys_vehicle_info (vehicle_id, license_plate, vin_number, brand, owning_unit, contact_person, phone_number, type_code, create_by, create_time, remark) VALUES +(1, '京A12345', 'WVWZZZ1JZ3W386752', '大众', '机场运营部', '张三', '13800138001', 'UV.PT', 'admin', NOW(), '无人巡逻车001'), +(2, '京A12346', 'WVWZZZ1JZ3W386753', '比亚迪', '机场运营部', '李四', '13800138002', 'UV.CL', 'admin', NOW(), '无人清洁车001'), +(3, '京A12347', 'WVWZZZ1JZ3W386754', '奔驰', '机场消防队', '王五', '13800138003', 'SP.FF', 'admin', NOW(), '消防车001'), +(4, '京A12348', 'WVWZZZ1JZ3W386755', '福特', '机场医疗中心', '赵六', '13800138004', 'SP.AM', 'admin', NOW(), '救护车001'); + +-- ========================================== +-- 系统通知数据 +-- ========================================== + +-- 插入系统通知 +INSERT INTO sys_notice (notice_id, notice_title, notice_type, notice_content, status, create_by, create_time, remark) VALUES +(1, '温馨提醒:2024-01-01 QAUP系统上线', '2', '各位用户,QAUP机场无人车管理系统已正式上线,请及时登录系统进行相关操作。', '0', 'admin', NOW(), '管理员'), +(2, '维护通知:系统将于本周日凌晨进行维护', '1', '为了更好地为您提供服务,QAUP系统将于本周日凌晨2:00-4:00进行系统维护,届时系统将暂停服务,请您合理安排时间。给您带来的不便,敬请谅解!', '0', 'admin', NOW(), '管理员'); + +-- ========================================== +-- 更新序列值 +-- ========================================== + +-- 更新所有序列的当前值,确保后续插入不会冲突 +SELECT setval('sys_config_config_id_seq', (SELECT MAX(config_id) FROM sys_config)); +SELECT setval('sys_dict_type_dict_id_seq', (SELECT MAX(dict_id) FROM sys_dict_type)); +SELECT setval('sys_dict_data_dict_code_seq', (SELECT MAX(dict_code) FROM sys_dict_data)); +SELECT setval('sys_dept_dept_id_seq', (SELECT MAX(dept_id) FROM sys_dept)); +SELECT setval('sys_post_post_id_seq', (SELECT MAX(post_id) FROM sys_post)); +SELECT setval('sys_role_role_id_seq', (SELECT MAX(role_id) FROM sys_role)); +SELECT setval('sys_menu_menu_id_seq', (SELECT MAX(menu_id) FROM sys_menu)); +SELECT setval('sys_user_user_id_seq', (SELECT MAX(user_id) FROM sys_user)); +SELECT setval('sys_vehicle_type_new_id_seq', (SELECT MAX(id) FROM sys_vehicle_type)); +SELECT setval('sys_vehicle_info_vehicle_id_seq', (SELECT MAX(vehicle_id) FROM sys_vehicle_info)); +SELECT setval('airport_areas_id_seq', (SELECT MAX(id) FROM airport_areas)); +SELECT setval('sys_notice_notice_id_seq', (SELECT MAX(notice_id) FROM sys_notice)); + +-- ========================================== +-- 完成提示 +-- ========================================== + +-- 显示初始化完成信息 +DO $$ +BEGIN + RAISE NOTICE '========================================'; + RAISE NOTICE 'QAUP 系统初始数据导入完成!'; + RAISE NOTICE '========================================'; + RAISE NOTICE '默认管理员账号:admin'; + RAISE NOTICE '默认管理员密码:admin123'; + RAISE NOTICE '========================================'; +END $$; \ No newline at end of file diff --git a/deploy/docker/postgres/restore-db.sh b/deploy/docker/postgres/restore-db.sh deleted file mode 100755 index 270a7d6c..00000000 --- a/deploy/docker/postgres/restore-db.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash - -# QAUP 数据库恢复脚本 - -set -e - -# 检查参数 -if [ $# -eq 0 ]; then - echo "用法: $0 <备份文件路径>" - echo "示例: $0 /backup/qaup_backup_20241231_120000.sql.gz" - exit 1 -fi - -BACKUP_FILE="$1" -DB_NAME="${POSTGRES_DB:-qaup}" -DB_USER="${POSTGRES_USER:-postgres}" - -echo "=========================================" -echo "QAUP 数据库恢复开始" -echo "=========================================" - -# 检查备份文件是否存在 -if [ ! -f "$BACKUP_FILE" ]; then - echo "错误: 备份文件不存在: $BACKUP_FILE" - exit 1 -fi - -echo "恢复文件: $BACKUP_FILE" -echo "目标数据库: $DB_NAME" - -# 确认操作 -read -p "警告: 此操作将覆盖现有数据库。是否继续? (y/N): " -n 1 -r -echo -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "操作已取消" - exit 1 -fi - -# 停止应用连接(可选) -echo "建议在恢复前停止应用服务以避免数据冲突" - -# 解压备份文件(如果是压缩的) -TEMP_FILE="" -if [[ "$BACKUP_FILE" == *.gz ]]; then - echo "解压备份文件..." - TEMP_FILE="/tmp/restore_$(basename "$BACKUP_FILE" .gz)" - gunzip -c "$BACKUP_FILE" > "$TEMP_FILE" - RESTORE_FILE="$TEMP_FILE" -else - RESTORE_FILE="$BACKUP_FILE" -fi - -# 执行恢复 -echo "开始恢复数据库..." -psql -h localhost -U "$DB_USER" -d postgres -f "$RESTORE_FILE" - -# 清理临时文件 -if [ -n "$TEMP_FILE" ] && [ -f "$TEMP_FILE" ]; then - rm -f "$TEMP_FILE" -fi - -# 验证恢复结果 -echo "" -echo "验证恢复结果..." -TABLE_COUNT=$(psql -h localhost -U "$DB_USER" -d "$DB_NAME" -t -c "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';") -echo "恢复后表数量: $TABLE_COUNT" - -echo "" -echo "=========================================" -echo "数据库恢复完成!" -echo "=========================================" -echo "请重启应用服务以确保正常连接" \ No newline at end of file diff --git a/deploy/docker/prepare-offline-images.sh b/deploy/docker/prepare-offline-images.sh index 8e1a8613..65ea4834 100755 --- a/deploy/docker/prepare-offline-images.sh +++ b/deploy/docker/prepare-offline-images.sh @@ -1,10 +1,72 @@ #!/bin/bash # QAUP 离线部署镜像准备脚本 -# 此脚本需要在有网络连接的环境中运行 +# 此脚本需要在有网络连接的环境中运行,用于准备离线部署所需的所有镜像 set -e +# 显示帮助信息 +show_help() { + echo "QAUP 离线部署镜像准备脚本" + echo "" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " -h, --help 显示帮助信息" + echo " --no-build 跳过自定义镜像构建(仅拉取基础镜像)" + echo " --clean 清理现有的离线部署目录" + echo "" + echo "功能:" + echo " - 自动检测 docker-compose.yml 中的镜像版本" + echo " - 拉取所有必需的基础镜像" + echo " - 构建 QAUP 自定义镜像" + echo " - 导出所有镜像为 tar.gz 文件" + echo " - 生成校验和文件" + echo " - 创建导入脚本和部署包" + echo "" + echo "系统要求:" + echo " - Docker 已安装并运行" + echo " - 网络连接正常" + echo " - 足够的磁盘空间(建议 10GB+)" +} + +# 检查参数 +NO_BUILD=false +CLEAN=false + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + --no-build) + NO_BUILD=true + shift + ;; + --clean) + CLEAN=true + shift + ;; + *) + echo "未知选项: $1" + show_help + exit 1 + ;; + esac +done + +# 检查 Docker 是否可用 +if ! command -v docker &> /dev/null; then + echo "错误: Docker 未安装或不在 PATH 中" + exit 1 +fi + +if ! docker info &> /dev/null; then + echo "错误: Docker 服务未运行" + exit 1 +fi + # 配置变量 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" @@ -12,13 +74,49 @@ IMAGES_DIR="$PROJECT_ROOT/offline-deploy/images" CONFIG_DIR="$PROJECT_ROOT/offline-deploy/config" SCRIPTS_DIR="$PROJECT_ROOT/offline-deploy/scripts" -# 镜像版本配置 -OPENJDK_IMAGE="openjdk:17-jre-slim" -NGINX_IMAGE="nginx:alpine" -POSTGRES_IMAGE="postgis/postgis:15-3.3" -REDIS_IMAGE="redis:7-alpine" -NODE_IMAGE="node:18-alpine" -MAVEN_IMAGE="maven:3.9.6-openjdk-17-slim" +# 加载镜像版本配置 +IMAGE_VERSIONS_FILE="$SCRIPT_DIR/image-versions.env" + +if [ -f "$IMAGE_VERSIONS_FILE" ]; then + echo "从配置文件加载镜像版本: $IMAGE_VERSIONS_FILE" + source "$IMAGE_VERSIONS_FILE" +else + echo "警告: 镜像版本配置文件不存在,使用默认版本" + # 默认版本(如果配置文件不存在) + POSTGRES_IMAGE="postgis/postgis:16-3.4" + REDIS_IMAGE="redis:7.2-alpine" + OPENJDK_IMAGE="openjdk:21-jre-slim" + MAVEN_IMAGE="maven:3.9-openjdk-21-slim" + NGINX_IMAGE="nginx:1.25-alpine" + NODE_IMAGE="node:20-alpine" + QAUP_APP_IMAGE="qaup-app:latest" + QAUP_NGINX_IMAGE="qaup-nginx:latest" +fi + +echo "使用的镜像版本:" +echo " PostgreSQL/PostGIS: $POSTGRES_IMAGE" +echo " Redis: $REDIS_IMAGE" +echo " Maven: $MAVEN_IMAGE" +echo " OpenJDK: $OPENJDK_IMAGE" +echo " Nginx: $NGINX_IMAGE" +echo " Node.js: $NODE_IMAGE" +echo " QAUP App: $QAUP_APP_IMAGE" +echo " QAUP Nginx: $QAUP_NGINX_IMAGE" +echo "" + +# 检查是否需要更新 docker-compose.yml 和 Dockerfile +echo "检查配置文件同步状态..." +COMPOSE_POSTGRES=$(grep -A 1 "qaup-postgres:" "$PROJECT_ROOT/docker-compose.yml" | grep "image:" | awk '{print $2}' | head -1) +COMPOSE_REDIS=$(grep -A 1 "qaup-redis:" "$PROJECT_ROOT/docker-compose.yml" | grep "image:" | awk '{print $2}' | head -1) + +if [ "$COMPOSE_POSTGRES" != "$POSTGRES_IMAGE" ]; then + echo "警告: docker-compose.yml 中的 PostgreSQL 版本 ($COMPOSE_POSTGRES) 与配置文件不一致 ($POSTGRES_IMAGE)" +fi + +if [ "$COMPOSE_REDIS" != "$REDIS_IMAGE" ]; then + echo "警告: docker-compose.yml 中的 Redis 版本 ($COMPOSE_REDIS) 与配置文件不一致 ($REDIS_IMAGE)" +fi +echo "" # 自定义镜像名称 QAUP_APP_IMAGE="qaup-app:latest" @@ -28,53 +126,165 @@ echo "=========================================" echo "QAUP 离线部署镜像准备开始" echo "=========================================" +# 清理现有目录(如果需要) +if [ "$CLEAN" = true ] && [ -d "$PROJECT_ROOT/offline-deploy" ]; then + echo "清理现有离线部署目录..." + rm -rf "$PROJECT_ROOT/offline-deploy" +fi + # 创建目录结构 echo "创建离线部署目录结构..." mkdir -p "$IMAGES_DIR" "$CONFIG_DIR" "$SCRIPTS_DIR" +# 拉取基础镜像函数 +pull_image() { + local image=$1 + echo "拉取镜像: $image" + if docker pull "$image"; then + echo "✓ $image 拉取成功" + else + echo "✗ $image 拉取失败" + exit 1 + fi +} + # 拉取基础镜像 echo "拉取基础镜像..." -docker pull $OPENJDK_IMAGE -docker pull $NGINX_IMAGE -docker pull $POSTGRES_IMAGE -docker pull $REDIS_IMAGE -docker pull $NODE_IMAGE -docker pull $MAVEN_IMAGE +pull_image "$OPENJDK_IMAGE" +pull_image "$NGINX_IMAGE" +pull_image "$POSTGRES_IMAGE" +pull_image "$REDIS_IMAGE" +pull_image "$NODE_IMAGE" +pull_image "$MAVEN_IMAGE" # 构建自定义镜像 echo "构建 QAUP 应用镜像..." cd "$PROJECT_ROOT" -docker build -t $QAUP_APP_IMAGE . +if docker build -t $QAUP_APP_IMAGE .; then + echo "✓ QAUP 应用镜像构建成功" +else + echo "✗ QAUP 应用镜像构建失败" + exit 1 +fi echo "构建 QAUP Nginx 镜像..." -docker build -f docker/nginx/Dockerfile -t $QAUP_NGINX_IMAGE . +if docker build -f deploy/docker/nginx/Dockerfile -t $QAUP_NGINX_IMAGE .; then + echo "✓ QAUP Nginx 镜像构建成功" +else + echo "✗ QAUP Nginx 镜像构建失败" + exit 1 +fi -# 导出镜像 +# 导出镜像函数 +export_image() { + local image=$1 + local filename=$2 + echo "导出镜像: $image -> $filename" + if docker save "$image" | gzip > "$IMAGES_DIR/$filename"; then + echo "✓ $filename 导出成功" + else + echo "✗ $filename 导出失败" + exit 1 + fi +} + +# 导出镜像文件 echo "导出镜像文件..." -docker save $OPENJDK_IMAGE | gzip > "$IMAGES_DIR/openjdk-17-jre-slim.tar.gz" -docker save $NGINX_IMAGE | gzip > "$IMAGES_DIR/nginx-alpine.tar.gz" -docker save $POSTGRES_IMAGE | gzip > "$IMAGES_DIR/postgis-15-3.3.tar.gz" -docker save $REDIS_IMAGE | gzip > "$IMAGES_DIR/redis-7-alpine.tar.gz" -docker save $QAUP_APP_IMAGE | gzip > "$IMAGES_DIR/qaup-app.tar.gz" -docker save $QAUP_NGINX_IMAGE | gzip > "$IMAGES_DIR/qaup-nginx.tar.gz" +export_image "$OPENJDK_IMAGE" "openjdk-17-jre-slim.tar.gz" +export_image "$NGINX_IMAGE" "nginx-alpine.tar.gz" +export_image "$POSTGRES_IMAGE" "postgis.tar.gz" +export_image "$REDIS_IMAGE" "redis-alpine.tar.gz" +export_image "$NODE_IMAGE" "node-alpine.tar.gz" +export_image "$MAVEN_IMAGE" "maven-openjdk.tar.gz" +export_image "$QAUP_APP_IMAGE" "qaup-app.tar.gz" +export_image "$QAUP_NGINX_IMAGE" "qaup-nginx.tar.gz" # 创建镜像清单文件 echo "创建镜像清单..." cat > "$IMAGES_DIR/images-list.txt" << EOF # QAUP 离线部署镜像清单 # 生成时间: $(date) +# 生成主机: $(hostname) # 基础镜像 openjdk-17-jre-slim.tar.gz -> $OPENJDK_IMAGE nginx-alpine.tar.gz -> $NGINX_IMAGE -postgis-15-3.3.tar.gz -> $POSTGRES_IMAGE -redis-7-alpine.tar.gz -> $REDIS_IMAGE +postgis.tar.gz -> $POSTGRES_IMAGE +redis-alpine.tar.gz -> $REDIS_IMAGE +node-alpine.tar.gz -> $NODE_IMAGE +maven-openjdk.tar.gz -> $MAVEN_IMAGE # 自定义镜像 qaup-app.tar.gz -> $QAUP_APP_IMAGE qaup-nginx.tar.gz -> $QAUP_NGINX_IMAGE + +# 使用说明 +# 1. 将所有 .tar.gz 文件复制到目标服务器 +# 2. 运行 load-images.sh 脚本导入镜像 +# 3. 验证校验和: sha256sum -c checksums.sha256 EOF +# 创建镜像导入脚本 +echo "创建镜像导入脚本..." +cat > "$SCRIPTS_DIR/load-images.sh" << 'EOF' +#!/bin/bash + +# QAUP 离线镜像导入脚本 +# 在目标服务器上运行此脚本导入镜像 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +IMAGES_DIR="$SCRIPT_DIR/../images" + +echo "=========================================" +echo "QAUP 离线镜像导入开始" +echo "=========================================" + +# 检查镜像文件 +if [ ! -d "$IMAGES_DIR" ]; then + echo "错误: 镜像目录不存在: $IMAGES_DIR" + exit 1 +fi + +# 验证校验和 +if [ -f "$IMAGES_DIR/checksums.sha256" ]; then + echo "验证文件校验和..." + cd "$IMAGES_DIR" + if sha256sum -c checksums.sha256; then + echo "✓ 文件校验和验证通过" + else + echo "✗ 文件校验和验证失败" + exit 1 + fi + cd - > /dev/null +fi + +# 导入镜像 +echo "导入镜像文件..." +for image_file in "$IMAGES_DIR"/*.tar.gz; do + if [ -f "$image_file" ]; then + echo "导入: $(basename "$image_file")" + if gunzip -c "$image_file" | docker load; then + echo "✓ $(basename "$image_file") 导入成功" + else + echo "✗ $(basename "$image_file") 导入失败" + exit 1 + fi + fi +done + +echo "" +echo "=========================================" +echo "镜像导入完成!" +echo "=========================================" +echo "已导入的镜像:" +docker images | grep -E "(qaup|postgres|redis|nginx|openjdk|node|maven)" +EOF + +# 设置执行权限 +chmod +x "$SCRIPTS_DIR/load-images.sh" + # 计算文件大小和校验和 echo "计算文件校验和..." cd "$IMAGES_DIR" @@ -92,6 +302,58 @@ echo "镜像文件列表:" ls -lh *.tar.gz echo "" echo "校验和文件已生成: checksums.sha256" +# 复制必要的配置文件 +echo "复制配置文件..." +cp "$PROJECT_ROOT/docker-compose.yml" "$CONFIG_DIR/" +cp "$PROJECT_ROOT/docker-compose.prod.yml" "$CONFIG_DIR/" +cp "$PROJECT_ROOT/.env.template" "$CONFIG_DIR/" + +# 复制部署脚本 +cp "$PROJECT_ROOT/deploy.sh" "$SCRIPTS_DIR/" + +# 创建离线部署说明 +cat > "$PROJECT_ROOT/offline-deploy/README-离线部署.md" << 'EOF' +# QAUP 离线部署包 + +## 包含内容 + +- `images/` - Docker 镜像文件 +- `config/` - 配置文件 +- `scripts/` - 部署脚本 + +## 部署步骤 + +1. 将整个 `offline-deploy` 目录复制到目标服务器 +2. 导入镜像:`./scripts/load-images.sh` +3. 配置环境:`cp config/.env.template .env` 并编辑 +4. 启动服务:`./scripts/deploy.sh install` + +## 系统要求 + +- Docker 20.10+ +- Docker Compose 1.29+ +- 至少 4GB 内存 +- 至少 20GB 磁盘空间 +EOF + +# 创建离线部署包 +echo "创建离线部署包..." +cd "$PROJECT_ROOT" +PACKAGE_NAME="qaup-offline-deploy-$(date +%Y%m%d_%H%M%S).tar.gz" +tar -czf "$PACKAGE_NAME" offline-deploy/ + echo "" -echo "离线部署镜像准备完成!" -echo "镜像文件位置: $IMAGES_DIR" \ No newline at end of file +echo "=========================================" +echo "离线部署准备完成!" +echo "=========================================" +echo "镜像文件位置: $IMAGES_DIR" +echo "配置文件位置: $CONFIG_DIR" +echo "脚本文件位置: $SCRIPTS_DIR" +echo "离线部署包: $PROJECT_ROOT/$PACKAGE_NAME" +echo "" +echo "部署包大小: $(du -sh "$PROJECT_ROOT/$PACKAGE_NAME" | cut -f1)" +echo "" +echo "使用方法:" +echo "1. 将 $PACKAGE_NAME 传输到目标服务器" +echo "2. 解压: tar -xzf $PACKAGE_NAME" +echo "3. 按照 offline-deploy/README-离线部署.md 中的说明进行部署" \ No newline at end of file diff --git a/deploy/docker/update-image-versions.sh b/deploy/docker/update-image-versions.sh new file mode 100644 index 00000000..8acfec54 --- /dev/null +++ b/deploy/docker/update-image-versions.sh @@ -0,0 +1,262 @@ +#!/bin/bash + +# QAUP Docker 镜像版本同步更新脚本 +# 根据 image-versions.env 配置文件更新所有相关文件中的镜像版本 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +IMAGE_VERSIONS_FILE="$SCRIPT_DIR/image-versions.env" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_message() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +# 显示帮助信息 +show_help() { + echo "QAUP Docker 镜像版本同步更新脚本" + echo "" + echo "用法: $0 [选项]" + echo "" + echo "选项:" + echo " -h, --help 显示帮助信息" + echo " --dry-run 仅显示将要进行的更改,不实际修改文件" + echo " --backup 更新前备份原文件" + echo "" + echo "功能:" + echo " - 从 image-versions.env 读取最新版本配置" + echo " - 更新 docker-compose.yml 中的镜像版本" + echo " - 更新 Dockerfile 中的基础镜像版本" + echo " - 生成版本更新报告" +} + +# 检查参数 +DRY_RUN=false +BACKUP=false + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + --dry-run) + DRY_RUN=true + shift + ;; + --backup) + BACKUP=true + shift + ;; + *) + echo "未知选项: $1" + show_help + exit 1 + ;; + esac +done + +# 检查配置文件 +if [ ! -f "$IMAGE_VERSIONS_FILE" ]; then + print_message $RED "错误: 镜像版本配置文件不存在: $IMAGE_VERSIONS_FILE" + exit 1 +fi + +# 加载配置 +source "$IMAGE_VERSIONS_FILE" + +print_message $BLUE "=========================================" +print_message $BLUE "QAUP Docker 镜像版本同步更新" +print_message $BLUE "=========================================" +echo "" + +if [ "$DRY_RUN" = true ]; then + print_message $YELLOW "运行模式: 预览模式(不会实际修改文件)" +else + print_message $GREEN "运行模式: 更新模式" +fi +echo "" + +# 备份函数 +backup_file() { + local file=$1 + if [ "$BACKUP" = true ] && [ -f "$file" ]; then + local backup_file="${file}.backup.$(date +%Y%m%d_%H%M%S)" + cp "$file" "$backup_file" + print_message $GREEN "已备份: $file -> $backup_file" + fi +} + +# 更新 docker-compose.yml +update_docker_compose() { + local compose_file="$PROJECT_ROOT/docker-compose.yml" + + if [ ! -f "$compose_file" ]; then + print_message $YELLOW "警告: docker-compose.yml 不存在,跳过更新" + return + fi + + print_message $BLUE "更新 docker-compose.yml..." + + # 检查当前版本 + local current_postgres=$(grep -A 1 "qaup-postgres:" "$compose_file" | grep "image:" | awk '{print $2}' | head -1) + local current_redis=$(grep -A 1 "qaup-redis:" "$compose_file" | grep "image:" | awk '{print $2}' | head -1) + + echo "PostgreSQL: $current_postgres -> $POSTGRES_IMAGE" + echo "Redis: $current_redis -> $REDIS_IMAGE" + + if [ "$DRY_RUN" = false ]; then + backup_file "$compose_file" + + # 更新 PostgreSQL 镜像 + sed -i.tmp "s|image: postgis/postgis:.*|image: $POSTGRES_IMAGE|g" "$compose_file" + + # 更新 Redis 镜像 + sed -i.tmp "s|image: redis:.*|image: $REDIS_IMAGE|g" "$compose_file" + + # 清理临时文件 + rm -f "${compose_file}.tmp" + + print_message $GREEN "✓ docker-compose.yml 更新完成" + fi + echo "" +} + +# 更新 Dockerfile +update_dockerfile() { + local dockerfile="$PROJECT_ROOT/Dockerfile" + + if [ ! -f "$dockerfile" ]; then + print_message $YELLOW "警告: Dockerfile 不存在,跳过更新" + return + fi + + print_message $BLUE "更新 Dockerfile..." + + # 检查当前版本 + local current_maven=$(grep "^FROM maven:" "$dockerfile" | awk '{print $2}' | head -1) + local current_openjdk=$(grep "^FROM openjdk:" "$dockerfile" | awk '{print $2}' | head -1) + + echo "Maven: $current_maven -> $MAVEN_IMAGE" + echo "OpenJDK: $current_openjdk -> $OPENJDK_IMAGE" + + if [ "$DRY_RUN" = false ]; then + backup_file "$dockerfile" + + # 更新 Maven 镜像 + sed -i.tmp "s|FROM maven:.*AS builder|FROM $MAVEN_IMAGE AS builder|g" "$dockerfile" + + # 更新 OpenJDK 镜像 + sed -i.tmp "s|FROM openjdk:.*|FROM $OPENJDK_IMAGE|g" "$dockerfile" + + # 清理临时文件 + rm -f "${dockerfile}.tmp" + + print_message $GREEN "✓ Dockerfile 更新完成" + fi + echo "" +} + +# 更新 Nginx Dockerfile +update_nginx_dockerfile() { + local nginx_dockerfile="$PROJECT_ROOT/docker/nginx/Dockerfile" + + if [ ! -f "$nginx_dockerfile" ]; then + print_message $YELLOW "警告: Nginx Dockerfile 不存在,跳过更新" + return + fi + + print_message $BLUE "更新 Nginx Dockerfile..." + + # 检查当前版本 + local current_node=$(grep "^FROM node:" "$nginx_dockerfile" | awk '{print $2}' | head -1) + local current_nginx=$(grep "^FROM nginx:" "$nginx_dockerfile" | awk '{print $2}' | head -1) + + echo "Node.js: $current_node -> $NODE_IMAGE" + echo "Nginx: $current_nginx -> $NGINX_IMAGE" + + if [ "$DRY_RUN" = false ]; then + backup_file "$nginx_dockerfile" + + # 更新 Node.js 镜像 + sed -i.tmp "s|FROM node:.*AS frontend-builder|FROM $NODE_IMAGE AS frontend-builder|g" "$nginx_dockerfile" + + # 更新 Nginx 镜像 + sed -i.tmp "s|FROM nginx:.*|FROM $NGINX_IMAGE|g" "$nginx_dockerfile" + + # 清理临时文件 + rm -f "${nginx_dockerfile}.tmp" + + print_message $GREEN "✓ Nginx Dockerfile 更新完成" + fi + echo "" +} + +# 生成更新报告 +generate_report() { + local report_file="$PROJECT_ROOT/image-version-update-report.txt" + + cat > "$report_file" << EOF +QAUP Docker 镜像版本更新报告 +生成时间: $(date) +更新模式: $([ "$DRY_RUN" = true ] && echo "预览模式" || echo "实际更新") + +更新的镜像版本: +- PostgreSQL/PostGIS: $POSTGRES_IMAGE +- Redis: $REDIS_IMAGE +- Maven: $MAVEN_IMAGE +- OpenJDK: $OPENJDK_IMAGE +- Nginx: $NGINX_IMAGE +- Node.js: $NODE_IMAGE + +更新的文件: +- docker-compose.yml +- Dockerfile +- docker/nginx/Dockerfile + +后续操作建议: +1. 测试新版本的兼容性 +2. 更新离线部署镜像包 +3. 更新部署文档中的版本信息 +4. 在测试环境验证后再部署到生产环境 +EOF + + print_message $GREEN "更新报告已生成: $report_file" +} + +# 执行更新 +print_message $BLUE "开始更新镜像版本..." +echo "" + +update_docker_compose +update_dockerfile +update_nginx_dockerfile + +if [ "$DRY_RUN" = false ]; then + print_message $GREEN "=========================================" + print_message $GREEN "镜像版本更新完成!" + print_message $GREEN "=========================================" + echo "" + print_message $YELLOW "重要提醒:" + echo "1. 请在测试环境验证新版本的兼容性" + echo "2. 运行 ./prepare-offline-images.sh 更新离线部署包" + echo "3. 考虑更新相关文档中的版本信息" +else + print_message $BLUE "=========================================" + print_message $BLUE "预览完成(未实际修改文件)" + print_message $BLUE "=========================================" + echo "" + print_message $YELLOW "如需实际更新,请运行: $0" +fi + +generate_report \ No newline at end of file diff --git a/deploy/docker/verify-versions.sh b/deploy/docker/verify-versions.sh new file mode 100644 index 00000000..30865f6e --- /dev/null +++ b/deploy/docker/verify-versions.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +# QAUP Docker 镜像版本验证脚本 +# 验证配置文件中的版本与实际使用的版本是否一致 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_message() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +print_message $BLUE "=========================================" +print_message $BLUE "QAUP Docker 镜像版本验证" +print_message $BLUE "=========================================" +echo "" + +# 加载配置文件 +if [ -f "$SCRIPT_DIR/image-versions.env" ]; then + source "$SCRIPT_DIR/image-versions.env" + print_message $GREEN "✓ 已加载镜像版本配置文件" +else + print_message $RED "✗ 镜像版本配置文件不存在" + exit 1 +fi + +echo "" +print_message $BLUE "配置文件中的版本:" +echo "PostgreSQL/PostGIS: $POSTGRES_IMAGE" +echo "Redis: $REDIS_IMAGE" +echo "OpenJDK: $OPENJDK_IMAGE" +echo "Maven: $MAVEN_IMAGE" +echo "Nginx: $NGINX_IMAGE" +echo "Node.js: $NODE_IMAGE" +echo "" + +# 检查 docker-compose.yml 中的版本 +print_message $BLUE "docker-compose.yml 中的版本:" +if [ -f "$PROJECT_ROOT/docker-compose.yml" ]; then + compose_postgres=$(grep -A 1 "qaup-postgres:" "$PROJECT_ROOT/docker-compose.yml" | grep "image:" | awk '{print $2}') + compose_redis=$(grep -A 1 "qaup-redis:" "$PROJECT_ROOT/docker-compose.yml" | grep "image:" | awk '{print $2}') + + echo "PostgreSQL/PostGIS: $compose_postgres" + echo "Redis: $compose_redis" + + # 验证一致性 + if [ "$compose_postgres" = "$POSTGRES_IMAGE" ]; then + print_message $GREEN "✓ PostgreSQL 版本一致" + else + print_message $RED "✗ PostgreSQL 版本不一致" + echo " 配置文件: $POSTGRES_IMAGE" + echo " docker-compose.yml: $compose_postgres" + fi + + if [ "$compose_redis" = "$REDIS_IMAGE" ]; then + print_message $GREEN "✓ Redis 版本一致" + else + print_message $RED "✗ Redis 版本不一致" + echo " 配置文件: $REDIS_IMAGE" + echo " docker-compose.yml: $compose_redis" + fi +else + print_message $YELLOW "警告: docker-compose.yml 文件不存在" +fi + +echo "" + +# 检查 Dockerfile 中的版本 +print_message $BLUE "Dockerfile 中的版本:" +if [ -f "$PROJECT_ROOT/Dockerfile" ]; then + dockerfile_maven=$(grep "^FROM maven:" "$PROJECT_ROOT/Dockerfile" | awk '{print $2}' | head -1) + dockerfile_openjdk=$(grep "^FROM openjdk:" "$PROJECT_ROOT/Dockerfile" | awk '{print $2}' | head -1) + + echo "Maven: $dockerfile_maven" + echo "OpenJDK: $dockerfile_openjdk" + + # 验证一致性 + if [ "$dockerfile_maven" = "$MAVEN_IMAGE" ]; then + print_message $GREEN "✓ Maven 版本一致" + else + print_message $RED "✗ Maven 版本不一致" + echo " 配置文件: $MAVEN_IMAGE" + echo " Dockerfile: $dockerfile_maven" + fi + + if [ "$dockerfile_openjdk" = "$OPENJDK_IMAGE" ]; then + print_message $GREEN "✓ OpenJDK 版本一致" + else + print_message $RED "✗ OpenJDK 版本不一致" + echo " 配置文件: $OPENJDK_IMAGE" + echo " Dockerfile: $dockerfile_openjdk" + fi +else + print_message $YELLOW "警告: Dockerfile 文件不存在" +fi + +echo "" +print_message $BLUE "当前使用的版本总结:" +echo "✓ PostgreSQL 17 + PostGIS 3.5 (最新稳定版)" +echo "✓ Redis 8.0 (最新版本)" +echo "✓ OpenJDK 17 (LTS 版本)" +echo "✓ Maven 3.9.11 (最新稳定版)" +echo "" + +print_message $YELLOW "升级注意事项:" +echo "1. PostgreSQL 17 包含性能改进和新特性" +echo "2. Redis 8.0 引入了新的数据结构和命令" +echo "3. 升级前请备份数据并在测试环境验证" +echo "4. 检查应用程序与新版本的兼容性" \ No newline at end of file diff --git a/deploy/docs/DEPLOYMENT-CHECKLIST.md b/deploy/docs/DEPLOYMENT-CHECKLIST.md new file mode 100644 index 00000000..055f9400 --- /dev/null +++ b/deploy/docs/DEPLOYMENT-CHECKLIST.md @@ -0,0 +1,115 @@ +# QAUP Docker 部署检查清单 + +## 部署前检查 + +### ✅ 环境准备 +- [ ] 确认操作系统版本 (Ubuntu 18.04+ 推荐) +- [ ] 安装 Docker (20.10+) +- [ ] 安装 Docker Compose (1.29+) +- [ ] 确认用户在 docker 组中 +- [ ] 确认网络连接正常 + +### ✅ 文件准备 +- [ ] 项目文件完整下载/解压 +- [ ] 进入 deploy 目录 (`cd QAUP-Management/deploy`) +- [ ] 运行路径验证 (`./test-paths.sh`) +- [ ] 所有脚本具有执行权限 + +### ✅ 数据准备 +- [ ] 查看数据文件状态 (`./docker/postgres/db-manager.sh prepare-status`) +- [ ] 选择数据准备方式: + - [ ] 全新部署:`./docker/postgres/db-manager.sh prepare-default` + - [ ] 现有系统迁移:`./docker/postgres/db-manager.sh prepare-export` + - [ ] 自定义组合:`./docker/postgres/db-manager.sh prepare-custom` +- [ ] 验证数据文件已准备完成 + +### ✅ 配置检查 +- [ ] 复制 `.env.template` 为 `.env` +- [ ] 修改数据库密码 (POSTGRES_PASSWORD, APP_DB_PASSWORD) +- [ ] 设置 Redis 密码 (REDIS_PASSWORD) +- [ ] 配置服务器域名 (SERVER_NAME) +- [ ] 调整 JVM 参数 (根据服务器配置) + +## 部署过程检查 + +### ✅ 系统验证 +- [ ] 运行环境验证 (`./docker/validate-environment.sh`) +- [ ] 检查端口占用情况 +- [ ] 确认磁盘空间充足 (至少 20GB) +- [ ] 确认内存充足 (至少 4GB) + +### ✅ 部署执行 +- [ ] 运行完整部署 (`./deploy.sh install`) +- [ ] 等待所有服务启动完成 +- [ ] 检查容器状态 (`docker ps`) +- [ ] 验证服务健康检查 + +### ✅ 功能验证 +- [ ] 访问前端页面 (`http://localhost`) +- [ ] 测试 API 接口 (`http://localhost/prod-api`) +- [ ] 检查健康检查端点 (`http://localhost/health`) +- [ ] 验证数据库连接 +- [ ] 测试文件上传功能 + +## 部署后检查 + +### ✅ 监控配置 +- [ ] 查看系统监控 (`./docker/monitor.sh watch`) +- [ ] 检查日志输出 (`./deploy.sh logs`) +- [ ] 验证告警配置 +- [ ] 测试备份功能 + +### ✅ 安全检查 +- [ ] 修改默认密码 +- [ ] 检查防火墙配置 +- [ ] 验证网络隔离 +- [ ] 确认敏感信息保护 + +### ✅ 性能优化 +- [ ] 监控资源使用情况 +- [ ] 调整 JVM 参数 +- [ ] 优化数据库配置 +- [ ] 配置日志轮转 + +## 常用命令参考 + +```bash +# 系统状态 +./docker/ops-manager.sh overview + +# 查看日志 +./deploy.sh logs [服务名] + +# 重启服务 +./deploy.sh restart + +# 备份数据 +./docker/backup-restore.sh backup + +# 系统监控 +./docker/monitor.sh watch + +# 性能分析 +./docker/ops-manager.sh performance +``` + +## 故障排除 + +如果遇到问题,请按以下顺序检查: + +1. **路径配置**: 运行 `./test-paths.sh` 验证 +2. **环境验证**: 运行 `./docker/validate-environment.sh` +3. **容器状态**: 运行 `docker ps -a` 查看容器状态 +4. **日志分析**: 运行 `./deploy.sh logs` 查看详细日志 +5. **资源检查**: 运行 `./docker/monitor.sh health` 检查资源 + +更多故障排除信息请参考 `docs/故障排除.md`。 + +## 联系支持 + +如果遇到无法解决的问题,请提供以下信息: +- 操作系统版本 +- Docker 版本信息 +- 错误日志内容 +- 系统资源状态 +- 部署步骤记录 \ No newline at end of file diff --git a/deploy/DOCKER-DEPLOYMENT-SUMMARY.md b/deploy/docs/DOCKER-DEPLOYMENT-SUMMARY.md similarity index 87% rename from deploy/DOCKER-DEPLOYMENT-SUMMARY.md rename to deploy/docs/DOCKER-DEPLOYMENT-SUMMARY.md index bbfba503..32f451d6 100644 --- a/deploy/DOCKER-DEPLOYMENT-SUMMARY.md +++ b/deploy/docs/DOCKER-DEPLOYMENT-SUMMARY.md @@ -48,6 +48,12 @@ - **详细文档**: 部署指南、故障排除和离线部署指南 - **Docker Compose 管理器**: 服务管理和操作脚本 +### ✅ 8. 路径配置优化 +- **统一部署目录**: 所有部署文件集中在 deploy 目录 +- **构建上下文优化**: Docker 构建上下文指向项目根目录 +- **路径自动处理**: 脚本自动处理相对路径和绝对路径 +- **路径验证工具**: test-paths.sh 脚本验证路径配置正确性 + ### ✅ 8. 生产环境优化 - **性能调优脚本**: JVM、数据库、Nginx 性能优化 - **零停机更新**: 滚动更新和蓝绿部署 @@ -138,6 +144,35 @@ QAUP-Management/ └── README-Docker.md # Docker 部署说明 ``` +## 路径配置技术说明 + +### 部署目录结构优化 +为了提高部署的便利性和可维护性,我们将所有部署相关文件集中在 `deploy` 目录下: + +- **工作目录**: 所有部署操作都在 `deploy` 目录下进行 +- **构建上下文**: Docker 构建上下文指向项目根目录 (`context: ..`) +- **路径映射**: 脚本自动处理相对路径和绝对路径的转换 + +### 关键路径配置 +```yaml +# docker-compose.yml 中的构建配置 +qaup-app: + build: + context: .. # 指向项目根目录 + dockerfile: deploy/Dockerfile # Dockerfile 相对于根目录的路径 + +qaup-nginx: + build: + context: .. # 指向项目根目录 + dockerfile: deploy/docker/nginx/Dockerfile # Nginx Dockerfile 路径 +``` + +### 路径验证工具 +提供了 `test-paths.sh` 脚本来验证路径配置的正确性: +- 检查关键文件和目录是否存在 +- 验证 Docker Compose 构建上下文配置 +- 确认 Dockerfile 中的路径引用正确 + ## 核心特性 ### 🚀 生产就绪 diff --git a/deploy/README-Docker.md b/deploy/docs/README-Docker.md similarity index 95% rename from deploy/README-Docker.md rename to deploy/docs/README-Docker.md index a3886c5b..bf7ed686 100644 --- a/deploy/README-Docker.md +++ b/deploy/docs/README-Docker.md @@ -1,7 +1,26 @@ # QAUP 系统 Docker 部署 +## 重要说明 + +**工作目录**: 请确保在 `deploy` 目录下执行所有部署命令。 + +```bash +cd QAUP-Management/deploy # 进入部署目录 +./test-paths.sh # 验证路径配置(推荐) +``` + ## 快速开始 +### 数据准备(首次部署必需) + +```bash +# 全新部署(使用默认数据) +./docker/postgres/db-manager.sh prepare-default + +# 或从现有系统迁移 +./docker/postgres/db-manager.sh prepare-export +``` + ### 一键部署 ```bash diff --git a/deploy/docs/数据导出导入指南.md b/deploy/docs/数据导出导入指南.md new file mode 100644 index 00000000..efb6b437 --- /dev/null +++ b/deploy/docs/数据导出导入指南.md @@ -0,0 +1,204 @@ +# QAUP 数据导出导入指南 + +## 概述 + +本指南介绍如何从现有 QAUP 数据库导出数据,并在新环境中导入这些数据。我们采用分层数据管理策略,将数据分为不同类别,以便灵活管理。 + +## 数据分类 + +### 1. 系统基础配置数据(必需) +- **包含表**: `sys_config`, `sys_dict_type`, `sys_dict_data`, `sys_dept`, `sys_post`, `sys_role`, `sys_menu`, `sys_user`, `sys_user_role`, `sys_user_post`, `sys_role_menu`, `sys_role_dept`, `sys_notice` +- **用途**: 系统运行的基础配置,包括菜单、角色、权限等 +- **特点**: 必须导入,否则系统无法正常运行 + +### 2. 业务基础数据(推荐) +- **包含表**: `sys_vehicle_type`, `airport_areas`, `spatial_rules`, `spatial_rule_vehicle_types`, `transport_routes` +- **用途**: 业务配置数据,如车辆类型、机场区域、空间规则等 +- **特点**: 建议导入,包含实际业务配置 + +### 3. 示例数据(可选) +- **包含表**: `sys_vehicle_info` +- **用途**: 示例车辆信息,用于演示和测试 +- **特点**: 可选导入,生产环境可能不需要 + +### 4. 实时数据(不导出) +- **包含表**: `vehicle_locations`, `vehicle_trajectories`, `vehicle_commands`, `geofence_events`, `uv_violation_events`, `sys_logininfor`, `sys_oper_log`, `sys_job_log` 等 +- **用途**: 实时运行数据、日志等 +- **特点**: 不导出,新环境启动后自动生成 + +## 数据导出 + +### 前提条件 +- 安装 PostgreSQL 客户端工具(包含 `pg_dump`) +- 能够连接到现有的 QAUP 数据库 +- 有足够的磁盘空间存储导出文件 + +### 导出步骤 + +#### 1. 设置环境变量 +```bash +export DB_HOST=localhost # 数据库主机 +export DB_PORT=5432 # 数据库端口 +export DB_NAME=qaup # 数据库名称 +export DB_USER=postgres # 数据库用户 +export EXPORT_DIR=./export # 导出目录 +``` + +#### 2. 执行导出(推荐方式) +```bash +cd deploy/docker/postgres +./db-manager.sh export-initial +``` + +这将生成以下文件: +- `01_system_data.sql` - 系统基础配置数据 +- `02_business_data.sql` - 业务基础数据 +- `03_sample_data.sql` - 示例数据 +- `initial_data_complete.sql` - 合并的完整初始数据文件 + +#### 3. 其他导出选项 +```bash +# 导出分层初始数据(推荐) +./db-manager.sh export-initial + +# 导出完整数据库 +./db-manager.sh export-all + +# 仅导出表结构 +./db-manager.sh export-schema + +# 数据库备份 +./db-manager.sh backup +``` + +## 数据导入 + +### 方法一:使用合并文件(推荐) +1. 将 `initial_data_complete.sql` 复制到 `deploy/docker/postgres/initial_data.sql` +2. 启动 Docker 容器,数据会自动导入 + +```bash +cp export/initial_data_complete.sql deploy/docker/postgres/initial_data.sql +./deploy.sh install +``` + +### 方法二:分层导入 +如果需要选择性导入,可以分别处理各层数据: + +```bash +# 1. 复制系统基础数据(必需) +cp export/01_system_data.sql deploy/docker/postgres/initial_data.sql + +# 2. 可选:追加业务数据 +cat export/02_business_data.sql >> deploy/docker/postgres/initial_data.sql + +# 3. 可选:追加示例数据 +cat export/03_sample_data.sql >> deploy/docker/postgres/initial_data.sql + +# 4. 启动容器 +./deploy.sh install +``` + +### 方法三:手动导入 +如果容器已经运行,可以手动导入数据: + +```bash +# 进入数据库容器 +docker exec -it qaup-postgres psql -U postgres -d qaup + +# 在容器内执行 +\i /docker-entrypoint-initdb.d/initial_data.sql +``` + +## 验证导入 + +### 1. 检查表数据 +```sql +-- 检查用户表 +SELECT COUNT(*) FROM sys_user; + +-- 检查菜单表 +SELECT COUNT(*) FROM sys_menu; + +-- 检查车辆类型表 +SELECT COUNT(*) FROM sys_vehicle_type; + +-- 检查机场区域表 +SELECT COUNT(*) FROM airport_areas; +``` + +### 2. 测试登录 +- 使用导出的管理员账号登录系统 +- 检查菜单和权限是否正确显示 +- 验证业务功能是否正常 + +## 注意事项 + +### 1. 密码处理 +- 导出的用户密码是加密的,可以直接使用 +- 如果需要重置密码,请在系统中操作 + +### 2. 序列值 +- 导出脚本会自动更新序列值 +- 确保新插入的数据不会产生主键冲突 + +### 3. 外键约束 +- 导入时会临时禁用触发器 +- 导入完成后会重新启用 + +### 4. 数据一致性 +- 建议在业务低峰期进行导出 +- 确保导出过程中数据不被修改 + +## 故障排除 + +### 1. 连接失败 +```bash +# 检查数据库连接 +pg_isready -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME +``` + +### 2. 权限问题 +```bash +# 确保用户有足够权限 +GRANT SELECT ON ALL TABLES IN SCHEMA public TO your_user; +``` + +### 3. 导入失败 +- 检查 SQL 文件语法 +- 查看 PostgreSQL 日志 +- 确认表结构已正确创建 + +### 4. 数据不完整 +- 检查导出日志 +- 验证源数据库数据完整性 +- 重新执行导出过程 + +## 最佳实践 + +1. **定期备份**: 建议定期导出数据作为备份 +2. **版本控制**: 将初始数据文件纳入版本控制 +3. **环境隔离**: 不同环境使用不同的数据集 +4. **测试验证**: 在测试环境先验证导入过程 +5. **文档更新**: 及时更新数据结构变更文档 + +## 自动化脚本 + +可以创建自动化脚本定期导出数据: + +```bash +#!/bin/bash +# auto-export.sh + +DATE=$(date +%Y%m%d_%H%M%S) +BACKUP_DIR="./backups/$DATE" + +mkdir -p "$BACKUP_DIR" +export EXPORT_DIR="$BACKUP_DIR" + +./export-data.sh -i + +echo "数据导出完成: $BACKUP_DIR" +``` + +这样可以确保始终有最新的数据备份可用于新环境部署。 \ No newline at end of file diff --git a/deploy/docs/数据文件说明.md b/deploy/docs/数据文件说明.md new file mode 100644 index 00000000..36a5c7b4 --- /dev/null +++ b/deploy/docs/数据文件说明.md @@ -0,0 +1,141 @@ +# QAUP 数据库初始数据文件说明 + +## 文件结构 + +``` +deploy/docker/postgres/ +├── qaup_database_schema.sql # 数据库表结构(必需) +├── initial_data.template.sql # 默认初始数据模板 +├── initial_data.sql # 实际使用的初始数据(优先级最高) +├── 01_system_data.sql # 系统配置数据(导出生成) +├── 02_business_data.sql # 业务基础数据(导出生成) +├── 03_sample_data.sql # 示例数据(导出生成) +├── db-manager.sh # 统一数据库管理工具 +├── init-db.sh # 数据库初始化脚本 +└── postgresql.conf # PostgreSQL 配置文件 +``` + +## 数据文件优先级 + +数据库初始化脚本 `init-db.sh` 按以下优先级加载数据: + +1. **`initial_data.sql`** - 如果存在,优先使用(通常是从现有系统导出的完整数据) +2. **分层数据文件** - 如果 `initial_data.sql` 不存在,按顺序加载: + - `01_system_data.sql` - 系统基础配置 + - `02_business_data.sql` - 业务基础数据 + - `03_sample_data.sql` - 示例数据 + +## 使用场景 + +### 场景1:全新部署(使用默认数据) +```bash +# 复制模板文件 +cp initial_data.template.sql initial_data.sql + +# 启动部署 +./deploy.sh install +``` + +### 场景2:从现有系统迁移 +```bash +# 1. 从现有数据库导出并准备数据(一步完成) +./db-manager.sh prepare-export + +# 2. 启动部署 +./deploy.sh install +``` + +### 场景3:选择性数据导入 +```bash +# 1. 从现有数据库导出分层数据 +./db-manager.sh export-initial + +# 2. 自定义数据组合 +./db-manager.sh prepare-custom + +# 3. 启动部署 +./deploy.sh install +``` + +### 场景4:自定义数据组合 +```bash +# 1. 创建自定义的 initial_data.sql +cat > initial_data.sql << 'EOF' +-- 自定义初始数据组合 +EOF + +# 2. 添加系统基础数据 +cat export/01_system_data.sql >> initial_data.sql + +# 3. 可选:添加业务数据 +cat export/02_business_data.sql >> initial_data.sql + +# 4. 启动部署 +./deploy.sh install +``` + +## 数据文件内容说明 + +### `initial_data.template.sql` +- **用途**: 默认初始数据模板 +- **内容**: 系统运行的最小数据集 +- **特点**: 包含默认管理员账号、基础菜单、示例配置 +- **适用**: 全新部署、演示环境 + +### `01_system_data.sql`(导出生成) +- **用途**: 系统基础配置数据 +- **内容**: 配置、字典、菜单、角色、用户等 +- **特点**: 从现有系统导出的实际配置 +- **适用**: 生产环境迁移 + +### `02_business_data.sql`(导出生成) +- **用途**: 业务基础数据 +- **内容**: 车辆类型、机场区域、空间规则等 +- **特点**: 业务相关的配置数据 +- **适用**: 保留业务配置的迁移 + +### `03_sample_data.sql`(导出生成) +- **用途**: 示例数据 +- **内容**: 示例车辆信息等 +- **特点**: 用于测试和演示 +- **适用**: 开发、测试环境 + +## 注意事项 + +1. **文件优先级**: `initial_data.sql` 存在时,分层文件会被忽略 +2. **数据冲突**: 确保导入的数据不会产生主键冲突 +3. **序列更新**: 所有数据文件都包含序列值更新语句 +4. **备份建议**: 导入前备份现有数据 +5. **权限检查**: 确保数据库用户有足够的导入权限 + +## 故障排除 + +### 问题1:数据导入失败 +```bash +# 检查数据文件语法 +psql -U postgres -d qaup --dry-run -f initial_data.sql + +# 查看详细错误信息 +docker logs qaup-postgres +``` + +### 问题2:序列值错误 +```sql +-- 手动更新序列值 +SELECT setval('table_id_seq', (SELECT MAX(id) FROM table_name)); +``` + +### 问题3:权限不足 +```sql +-- 授予必要权限 +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO qaup_app; +GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO qaup_app; +``` + +## 最佳实践 + +1. **版本控制**: 将使用的 `initial_data.sql` 纳入版本控制 +2. **环境隔离**: 不同环境使用不同的数据文件 +3. **定期导出**: 定期从生产环境导出最新配置 +4. **测试验证**: 在测试环境验证数据导入过程 +5. **文档更新**: 及时更新数据结构变更文档 \ No newline at end of file diff --git a/deploy/docs/部署指南.md b/deploy/docs/部署指南.md index a2c05f26..8a54f8b6 100644 --- a/deploy/docs/部署指南.md +++ b/deploy/docs/部署指南.md @@ -59,6 +59,34 @@ sudo chmod +x /usr/local/bin/docker-compose docker-compose --version ``` +## 项目结构说明 + +QAUP 系统采用了优化的部署结构,所有部署相关文件都集中在 `deploy` 目录下: + +``` +QAUP-Management/ +├── deploy/ # 部署目录(工作目录) +│ ├── deploy.sh # 主部署脚本 +│ ├── docker-compose.yml # Docker Compose 配置 +│ ├── docker-compose.prod.yml # 生产环境配置 +│ ├── Dockerfile # 应用镜像构建文件 +│ ├── .env.template # 环境变量模板 +│ ├── docker/ # Docker 相关脚本和配置 +│ │ ├── config-manager.sh # 配置管理脚本 +│ │ ├── monitor.sh # 监控脚本 +│ │ ├── nginx/ # Nginx 配置 +│ │ └── postgres/ # PostgreSQL 配置 +│ └── docs/ # 部署文档 +├── qaup-admin/ # 后端主模块 +├── qaup-ui/ # 前端模块 +└── 其他项目文件... +``` + +**重要说明:** +- 所有部署操作都在 `deploy` 目录下进行 +- Docker 构建上下文指向项目根目录,确保能正确访问所有源码文件 +- 部署脚本会自动处理路径映射,无需手动调整 + ## 部署步骤 ### 1. 获取部署包 @@ -67,20 +95,27 @@ docker-compose --version ```bash # 克隆项目(如果有 Git 访问权限) git clone <项目地址> -cd QAUP-Management +cd QAUP-Management/deploy ``` #### 离线部署 ```bash # 解压离线部署包 tar -xzf qaup-offline-deploy.tar.gz -cd QAUP-Management +cd QAUP-Management/deploy # 导入 Docker 镜像 ./docker/load-images.sh ``` -### 2. 环境验证 +### 2. 路径配置验证 + +```bash +# 运行路径配置测试(推荐) +./test-paths.sh +``` + +### 3. 环境验证 ```bash # 运行环境验证脚本 @@ -89,7 +124,34 @@ cd QAUP-Management 如果验证失败,请根据提示修复问题。 -### 3. 配置系统 +### 4. 数据准备 + +根据部署场景选择合适的数据准备方式: + +#### 场景1:全新部署(推荐新用户) +```bash +# 使用默认模板数据 +./docker/postgres/db-manager.sh prepare-default +``` + +#### 场景2:从现有系统迁移 +```bash +# 设置数据库连接信息 +export DB_HOST=your_db_host +export DB_USER=postgres +export DB_NAME=qaup + +# 从现有数据库导出并准备数据 +./docker/postgres/db-manager.sh prepare-export +``` + +#### 场景3:查看当前数据状态 +```bash +# 查看当前数据文件状态 +./docker/postgres/db-manager.sh prepare-status +``` + +### 6. 配置系统 ```bash # 初始化配置 diff --git a/deploy/test-paths.sh b/deploy/test-paths.sh new file mode 100755 index 00000000..5f8d071f --- /dev/null +++ b/deploy/test-paths.sh @@ -0,0 +1,95 @@ +#!/bin/bash + +# 路径配置测试脚本 +# 用于验证部署目录结构和路径配置是否正确 + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_message() { + local color=$1 + local message=$2 + echo -e "${color}${message}${NC}" +} + +print_message $BLUE "QAUP 部署路径配置测试" +print_message $BLUE "======================" +echo "" + +print_message $BLUE "当前目录: $SCRIPT_DIR" +print_message $BLUE "项目根目录: $PROJECT_ROOT" +echo "" + +# 检查关键文件和目录 +print_message $BLUE "检查关键文件和目录..." + +# 检查项目根目录文件 +files_to_check=( + "$PROJECT_ROOT/pom.xml" + "$PROJECT_ROOT/qaup-admin/pom.xml" + "$PROJECT_ROOT/qaup-ui/package.json" +) + +for file in "${files_to_check[@]}"; do + if [ -f "$file" ]; then + print_message $GREEN "✓ $file" + else + print_message $RED "✗ $file (缺失)" + fi +done + +# 检查部署目录文件 +deploy_files_to_check=( + "$SCRIPT_DIR/deploy.sh" + "$SCRIPT_DIR/docker-compose.yml" + "$SCRIPT_DIR/Dockerfile" + "$SCRIPT_DIR/docker/config-manager.sh" + "$SCRIPT_DIR/docker/nginx/Dockerfile" +) + +for file in "${deploy_files_to_check[@]}"; do + if [ -f "$file" ]; then + print_message $GREEN "✓ $file" + else + print_message $RED "✗ $file (缺失)" + fi +done + +echo "" +print_message $BLUE "检查 Docker Compose 构建上下文..." + +# 验证 Docker Compose 配置 +if grep -q "context: \.\." "$SCRIPT_DIR/docker-compose.yml"; then + print_message $GREEN "✓ Docker Compose 构建上下文配置正确" +else + print_message $RED "✗ Docker Compose 构建上下文配置错误" +fi + +if grep -q "dockerfile: deploy/Dockerfile" "$SCRIPT_DIR/docker-compose.yml"; then + print_message $GREEN "✓ Dockerfile 路径配置正确" +else + print_message $RED "✗ Dockerfile 路径配置错误" +fi + +echo "" +print_message $BLUE "检查 Dockerfile 路径引用..." + +# 检查 Dockerfile 中的路径 +if grep -q "COPY deploy/docker/start.sh" "$SCRIPT_DIR/Dockerfile"; then + print_message $GREEN "✓ Dockerfile 启动脚本路径正确" +else + print_message $RED "✗ Dockerfile 启动脚本路径错误" +fi + +echo "" +print_message $GREEN "路径配置检查完成!" +print_message $YELLOW "如果发现错误,请根据提示修复后重新测试" \ No newline at end of file diff --git a/ry.sh b/qaup.sh similarity index 100% rename from ry.sh rename to qaup.sh