I第一次提交

This commit is contained in:
zhangzf1119
2025-12-13 23:00:09 +08:00
commit ac08a0b6ff
180 changed files with 28023 additions and 0 deletions

279
build-docker-bundle.sh Normal file
View File

@@ -0,0 +1,279 @@
#!/usr/bin/env bash
#
# 构建离线 Docker 交付包包含应用镜像、pgvector(PostgreSQL)、Redis 及统一的 docker-compose
# 使用方式:
# chmod +x build-docker-bundle.sh
# ./build-docker-bundle.sh # 使用默认版本号(时间戳)
# VERSION=v1.2.3 ./build-docker-bundle.sh # 指定版本号
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
APP_NAME="gdyd-zhpb-zgf"
VERSION="${VERSION:-${TIMESTAMP}}"
OUTPUT_DIR="${ROOT_DIR}/docker-bundle-${VERSION}"
IMAGES_DIR="${OUTPUT_DIR}/images"
CONFIG_DIR="${OUTPUT_DIR}/config"
INIT_DIR="${OUTPUT_DIR}/pgvector-init"
APP_IMAGE="${APP_NAME}-app:${VERSION}"
PGVECTOR_IMAGE="${PGVECTOR_IMAGE:-pgvector/pgvector:pg16-trixie}"
REDIS_IMAGE="${REDIS_IMAGE:-redis:7-alpine}"
# 默认账号密码,可在执行脚本前通过环境变量覆盖
POSTGRES_DB="${POSTGRES_DB:-vector_db}"
POSTGRES_USER="${POSTGRES_USER:-vectoruser}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-vectorpass}"
POSTGRES_PORT="${POSTGRES_PORT:-5433}"
REDIS_PASSWORD="${REDIS_PASSWORD:-TNh8jiy8WpEweGLZ}"
REDIS_PORT="${REDIS_PORT:-26739}"
APP_PORT="${APP_PORT:-8000}"
print_step() {
printf '\n\033[1;34m==> %s\033[0m\n' "$1"
}
print_info() {
printf ' %s\n' "$1"
}
abort() {
printf '\033[1;31m[错误]\033[0m %s\n' "$1" >&2
exit 1
}
check_command() {
command -v "$1" >/dev/null 2>&1 || abort "未找到命令:$1,请先安装。"
}
APT_UPDATED=0
SUDO_CMD=""
if command -v sudo >/dev/null 2>&1 && [[ ${EUID:-0} -ne 0 ]]; then
SUDO_CMD="sudo"
fi
update_apt_once() {
if [[ ${APT_UPDATED} -eq 0 ]]; then
print_step "更新 apt 软件源"
${SUDO_CMD} env DEBIAN_FRONTEND=noninteractive apt-get update -y
APT_UPDATED=1
fi
}
install_with_apt() {
local package="$1"
local friendly="$2"
if ! command -v apt-get >/dev/null 2>&1; then
abort "缺少 ${friendly},但当前环境不支持自动安装(未检测到 apt-get"
fi
update_apt_once
print_step "安装 ${friendly}"
${SUDO_CMD} env DEBIAN_FRONTEND=noninteractive apt-get install -y "${package}"
}
ensure_maven() {
if ! command -v mvn >/dev/null 2>&1; then
install_with_apt "maven" "Maven"
fi
}
ensure_java21() {
local major=""
if command -v java >/dev/null 2>&1; then
local version_line
version_line="$(java -version 2>&1 | head -n 1 | cut -d'"' -f2)"
major="${version_line%%.*}"
if [[ "${major}" == "1" ]]; then
major="$(echo "${version_line}" | cut -d'.' -f2)"
fi
if [[ -n "${major}" && "${major}" -ge 21 ]]; then
return
fi
print_info "检测到 Java 版本 ${major:-unknown},低于 21准备自动安装 OpenJDK 21。"
else
print_info "未检测到 Java准备自动安装 OpenJDK 21。"
fi
install_with_apt "openjdk-21-jdk" "OpenJDK 21"
}
ensure_clean_dir() {
if [[ -d "$1" ]]; then
rm -rf "$1"
fi
mkdir -p "$1"
}
ensure_java21
ensure_maven
check_command docker
print_step "编译 Spring Boot 应用"
mvn -q -U -DskipTests clean package
JAR_FILE="$(find "${ROOT_DIR}/target" -maxdepth 1 -type f -name "*.jar" ! -name "*-sources.jar" ! -name "*-javadoc.jar" | head -n 1)"
[[ -n "${JAR_FILE}" ]] || abort "未找到可用的 JAR 文件,请检查 Maven 构建结果。"
print_info "找到 JAR${JAR_FILE}"
print_step "构建应用镜像 ${APP_IMAGE}"
docker build \
--build-arg VERSION="${VERSION}" \
--build-arg BUILD_TIME="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
-t "${APP_IMAGE}" \
"${ROOT_DIR}"
print_step "拉取依赖镜像"
docker pull "${PGVECTOR_IMAGE}"
docker pull "${REDIS_IMAGE}"
print_step "生成离线交付包目录 ${OUTPUT_DIR}"
ensure_clean_dir "${OUTPUT_DIR}"
mkdir -p "${IMAGES_DIR}" "${CONFIG_DIR}" "${INIT_DIR}"
if [[ -f "${ROOT_DIR}/src/main/resources/application.yml" ]]; then
cp "${ROOT_DIR}/src/main/resources/application.yml" "${CONFIG_DIR}/application.yml"
print_info "已复制默认 application.yml 到 ${CONFIG_DIR}/application.yml"
else
print_info "未找到 src/main/resources/application.yml可手动放置到 ${CONFIG_DIR}/application.yml"
fi
cat > "${OUTPUT_DIR}/.env" <<EOF
# PostgreSQL (pgvector)
POSTGRES_DB=${POSTGRES_DB}
POSTGRES_USER=${POSTGRES_USER}
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
POSTGRES_PORT=${POSTGRES_PORT}
# Redis
REDIS_PASSWORD=${REDIS_PASSWORD}
REDIS_PORT=${REDIS_PORT}
# 应用
APP_PORT=${APP_PORT}
EOF
cat > "${INIT_DIR}/001-create-vector-extension.sql" <<'EOF'
CREATE EXTENSION IF NOT EXISTS vector;
EOF
cat > "${OUTPUT_DIR}/docker-compose.yml" <<EOF
version: "3.8"
services:
pgvector:
image: ${PGVECTOR_IMAGE}
container_name: ${APP_NAME}-pgvector
restart: unless-stopped
environment:
POSTGRES_DB: \${POSTGRES_DB}
POSTGRES_USER: \${POSTGRES_USER}
POSTGRES_PASSWORD: \${POSTGRES_PASSWORD}
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- "\${POSTGRES_PORT}:5432"
volumes:
- pgvector_data:/var/lib/postgresql/data
- ./pgvector-init:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U \${POSTGRES_USER} -d \${POSTGRES_DB}"]
interval: 20s
timeout: 5s
retries: 5
redis:
image: ${REDIS_IMAGE}
container_name: ${APP_NAME}-redis
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--requirepass", "\${REDIS_PASSWORD}"]
ports:
- "\${REDIS_PORT}:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "\${REDIS_PASSWORD}", "ping"]
interval: 20s
timeout: 5s
retries: 5
app:
image: ${APP_IMAGE}
container_name: ${APP_NAME}-app
restart: unless-stopped
depends_on:
pgvector:
condition: service_healthy
redis:
condition: service_healthy
ports:
- "\${APP_PORT}:8000"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://pgvector:5432/\${POSTGRES_DB}
SPRING_DATASOURCE_USERNAME: \${POSTGRES_USER}
SPRING_DATASOURCE_PASSWORD: \${POSTGRES_PASSWORD}
SPRING_DATA_REDIS_HOST: redis
SPRING_DATA_REDIS_PORT: 6379
SPRING_DATA_REDIS_PASSWORD: \${REDIS_PASSWORD}
SERVER_PORT: 8000
volumes:
- ./config/application.yml:/app/config/application.yml:ro
- app_uploads:/app/uploads
- app_extracts:/app/extracts
- app_logs:/app/logs
volumes:
pgvector_data:
redis_data:
app_uploads:
app_extracts:
app_logs:
EOF
cat > "${OUTPUT_DIR}/README.md" <<EOF
# Docker 离线部署包(${APP_NAME} ${VERSION}
## 包含内容
- 应用镜像:${APP_IMAGE}
- pgvector 数据库镜像:${PGVECTOR_IMAGE}
- Redis 缓存镜像:${REDIS_IMAGE}
- docker-compose.yml / .env / config / pgvector-init 目录
## 使用步骤
1. 将整个目录拷贝到目标服务器并进入该目录:
\`\`\`
cd $(basename "${OUTPUT_DIR}")
\`\`\`
2. 导入离线镜像:
\`\`\`
docker load -i images/app-${VERSION}.tar
docker load -i images/pgvector.tar
docker load -i images/redis.tar
\`\`\`
3. 根据需要修改 \`.env\`、\`config/application.yml\`。
4. 启动:
\`\`\`
docker compose up -d
\`\`\`
5. 查看状态:
\`\`\`
docker compose ps
docker compose logs -f app
\`\`\`
缺省账号密码可通过执行脚本前设置环境变量覆盖,如:
\`\`\`
POSTGRES_PASSWORD=StrongPass REDIS_PASSWORD=Secret ./build-docker-bundle.sh
\`\`\`
EOF
print_step "保存离线镜像到 ${IMAGES_DIR}"
docker save "${APP_IMAGE}" -o "${IMAGES_DIR}/app-${VERSION}.tar"
docker save "${PGVECTOR_IMAGE}" -o "${IMAGES_DIR}/pgvector.tar"
docker save "${REDIS_IMAGE}" -o "${IMAGES_DIR}/redis.tar"
print_step "打包完成"
print_info "输出目录:${OUTPUT_DIR}"
print_info "镜像文件:${IMAGES_DIR}"
print_info "可根据需要编辑 ${OUTPUT_DIR}/.env 与 ${CONFIG_DIR}/application.yml 后,执行 docker compose up -d 启动。"