455 lines
13 KiB
Bash
Executable File
455 lines
13 KiB
Bash
Executable File
#!/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 "$0")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
IMAGES_DIR="$PROJECT_ROOT/offline-deploy/images"
|
||
CONFIG_DIR="$PROJECT_ROOT/offline-deploy/config"
|
||
SCRIPTS_DIR="$PROJECT_ROOT/offline-deploy/scripts"
|
||
|
||
# 加载镜像版本配置
|
||
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"
|
||
QAUP_NGINX_IMAGE="qaup-nginx:latest"
|
||
|
||
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 "拉取基础镜像..."
|
||
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"
|
||
if docker build -f deploy/Dockerfile -t $QAUP_APP_IMAGE .; then
|
||
echo "✓ QAUP 应用镜像构建成功"
|
||
else
|
||
echo "✗ QAUP 应用镜像构建失败"
|
||
exit 1
|
||
fi
|
||
|
||
echo "构建 QAUP Nginx 镜像..."
|
||
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 "导出镜像文件..."
|
||
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.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 "$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"
|
||
sha256sum *.tar.gz > checksums.sha256
|
||
|
||
# 显示统计信息
|
||
echo ""
|
||
echo "========================================="
|
||
echo "镜像准备完成统计信息:"
|
||
echo "========================================="
|
||
echo "镜像文件数量: $(ls -1 *.tar.gz | wc -l)"
|
||
echo "总大小: $(du -sh . | cut -f1)"
|
||
echo ""
|
||
echo "镜像文件列表:"
|
||
ls -lh *.tar.gz
|
||
echo ""
|
||
echo "校验和文件已生成: checksums.sha256"
|
||
# 复制必要的配置文件到根目录
|
||
echo "复制配置文件..."
|
||
cp "$PROJECT_ROOT/deploy/docker-compose.yml" "$PROJECT_ROOT/offline-deploy/"
|
||
cp "$PROJECT_ROOT/deploy/docker-compose.prod.yml" "$PROJECT_ROOT/offline-deploy/"
|
||
cp "$PROJECT_ROOT/deploy/.env.template" "$PROJECT_ROOT/offline-deploy/"
|
||
|
||
# 创建config目录并复制application-prod.yml
|
||
echo "复制应用配置文件..."
|
||
mkdir -p "$PROJECT_ROOT/offline-deploy/config"
|
||
cp "$PROJECT_ROOT/deploy/config/application-prod.yml" "$PROJECT_ROOT/offline-deploy/config/"
|
||
|
||
# 复制部署脚本
|
||
cp "$PROJECT_ROOT/deploy/deploy.sh" "$SCRIPTS_DIR/"
|
||
|
||
# 复制docker配置目录
|
||
echo "复制Docker配置..."
|
||
mkdir -p "$PROJECT_ROOT/offline-deploy/docker"
|
||
cp -r "$PROJECT_ROOT/deploy/docker"/* "$PROJECT_ROOT/offline-deploy/docker/" 2>/dev/null || true
|
||
|
||
# 复制文档
|
||
echo "复制文档..."
|
||
mkdir -p "$PROJECT_ROOT/offline-deploy/docs"
|
||
cp -r "$PROJECT_ROOT/deploy/docs"/* "$PROJECT_ROOT/offline-deploy/docs/" 2>/dev/null || true
|
||
|
||
# 复制数据库脚本(如果存在)
|
||
if [ -d "$PROJECT_ROOT/sql" ]; then
|
||
echo "复制数据库脚本..."
|
||
cp -r "$PROJECT_ROOT/sql" "$PROJECT_ROOT/offline-deploy/"
|
||
fi
|
||
|
||
# 创建离线部署说明
|
||
cat > "$PROJECT_ROOT/offline-deploy/README-离线部署.md" << 'EOF'
|
||
# QAUP 离线部署包
|
||
|
||
## 包含内容
|
||
|
||
- `images/` - Docker 镜像文件
|
||
- `scripts/` - 部署脚本
|
||
- `docker/` - Docker配置和数据库初始化脚本
|
||
- `docs/` - 部署文档
|
||
- `sql/` - 数据库架构文件(如果存在)
|
||
- `docker-compose.yml` - Docker Compose 主配置文件
|
||
- `docker-compose.prod.yml` - 生产环境配置文件
|
||
- `.env.template` - 环境变量模板文件
|
||
|
||
## 重要文件说明
|
||
|
||
### 配置文件
|
||
- `docker-compose.yml` - Docker Compose 主配置文件
|
||
- `docker-compose.prod.yml` - 生产环境特定配置
|
||
- `.env.template` - 环境变量配置模板
|
||
|
||
### 数据库初始化数据
|
||
- `docker/postgres/export/01_system_data.sql` - 系统基础数据
|
||
- `docker/postgres/export/02_business_data.sql` - 业务数据
|
||
- `docker/postgres/export/03_sample_data.sql` - 示例数据
|
||
- `docker/postgres/export/initial_data_complete.sql` - 完整初始化数据
|
||
|
||
## 部署步骤
|
||
|
||
1. 将整个 `offline-deploy` 目录复制到目标服务器
|
||
2. 进入部署目录:`cd offline-deploy`
|
||
3. 导入镜像:`./scripts/load-images.sh`
|
||
4. 配置环境:`cp .env.template .env` 并根据实际情况编辑 `.env` 文件
|
||
5. 启动服务:`./scripts/deploy.sh install`
|
||
|
||
## 手动部署方式
|
||
|
||
如果使用部署脚本遇到问题,可以手动执行:
|
||
|
||
```bash
|
||
# 1. 导入镜像
|
||
./scripts/load-images.sh
|
||
|
||
# 2. 配置环境变量
|
||
cp .env.template .env
|
||
# 编辑 .env 文件,设置数据库密码、端口等配置
|
||
|
||
# 3. 启动服务
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml --env-file .env up -d
|
||
|
||
# 4. 查看服务状态
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml ps
|
||
|
||
# 5. 查看日志
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml logs -f
|
||
```
|
||
|
||
## 系统要求
|
||
|
||
- Docker 20.10+
|
||
- Docker Compose 1.29+
|
||
- 至少 4GB 内存
|
||
- 至少 20GB 磁盘空间
|
||
|
||
## 数据库初始化
|
||
|
||
系统启动时会自动执行数据库初始化脚本,按以下顺序:
|
||
1. 系统数据(用户、角色、权限等)
|
||
2. 业务数据(机场配置、区域设置等)
|
||
3. 示例数据(测试用途,可选)
|
||
|
||
## 常见问题
|
||
|
||
### 端口冲突
|
||
如果遇到端口被占用的问题,请修改 `.env` 文件中的端口配置:
|
||
- `NGINX_PORT` - Nginx HTTP 端口(默认 80)
|
||
- `NGINX_HTTPS_PORT` - Nginx HTTPS 端口(默认 443)
|
||
- `APP_PORT` - 应用端口(默认 8080)
|
||
|
||
### 权限问题
|
||
如果遇到数据目录权限问题,请执行:
|
||
```bash
|
||
sudo chown -R $USER:$USER data/
|
||
sudo chmod -R 755 data/
|
||
```
|
||
|
||
### 服务管理
|
||
```bash
|
||
# 停止服务
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml down
|
||
|
||
# 重启服务
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml restart
|
||
|
||
# 查看特定服务日志
|
||
docker-compose -f docker-compose.yml -f docker-compose.prod.yml logs -f qaup-app
|
||
```
|
||
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 "离线部署准备完成!"
|
||
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 中的说明进行部署" |