QAUP_Management/deploy/docker/prepare-offline-images.sh

455 lines
13 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 中的说明进行部署"