diff --git a/README.md b/README.md index c8c0f71..cff7e19 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ - 仅支持本地模型(无网络下载功能) - 多模型配置支持 - **提供标准的 OpenAI API 服务** +- **智能部署(自动检测 Git 更新)** ## 快速开始 @@ -237,22 +238,36 @@ server: ## 启动 vLLM 服务器 -### 使用构建和部署脚本(推荐) +### 使用智能部署脚本(推荐) -项目提供了 `build_and_run.sh` 脚本,用于一键构建镜像并部署运行: +项目提供了 `build_and_run.sh` 脚本,具有智能检测和自动部署功能: + +**智能部署逻辑:** + +1. **检测 Git 代码更新**: + - 自动拉取远程仓库最新代码 + - 比较本地和远程代码版本 + - 检测本地未提交的更改 + +2. **智能构建决策**: + - ✅ 代码有更新 → 重新构建镜像 + - ✅ 本地有更改 → 重新构建镜像 + - ✅ 镜像不存在 → 构建镜像 + - ⏭️ 代码无更新且镜像存在 → 跳过构建,直接部署 + +3. **自动部署**: + - 停止并删除旧容器 + - 使用新镜像(或现有镜像)启动新容器 ```bash # 赋予执行权限 chmod +x build_and_run.sh -# 构建并运行(默认后台运行) +# 智能部署(自动检测 Git 更新) ./build_and_run.sh -# 仅构建镜像 -./build_and_run.sh -b - -# 重新构建镜像(不使用缓存) -./build_and_run.sh -r +# 强制重新构建(忽略 Git 状态) +./build_and_run.sh -f # 仅停止并删除容器 ./build_and_run.sh -s @@ -265,20 +280,30 @@ chmod +x build_and_run.sh # 交互式运行(前台运行) ./build_and_run.sh -i + +# 指定 Git 分支 +./build_and_run.sh -b master ``` **脚本选项:** -- `-b, --build-only`:仅构建镜像,不运行容器 -- `-r, --rebuild`:重新构建镜像(不使用缓存) +- `-f, --force`:强制重新构建镜像(忽略 Git 状态) - `-s, --stop`:仅停止并删除容器 - `-d, --detach`:后台运行容器(默认) - `-i, --interactive`:交互式运行容器 - `-c, --config FILE`:指定配置文件路径 - `-m, --models DIR`:指定模型目录路径 - `-p, --port PORT`:指定服务端口 +- `-b, --branch NAME`:指定 Git 分支(默认:main) - `-h, --help`:显示帮助信息 +**使用场景:** + +- **首次部署**:直接运行 `./build_and_run.sh`,自动构建并部署 +- **日常更新**:运行 `./build_and_run.sh`,自动检测代码更新并重新部署 +- **快速重启**:代码无更新时,跳过构建,直接重启容器 +- **强制更新**:使用 `-f` 参数强制重新构建 + ### 手动部署 ```bash @@ -440,5 +465,5 @@ print(response.choices[0].text) - `README.md` - 项目说明文档 - `model_config.yaml.example` - 配置文件示例 - `params_config.yaml` - 参数配置文件(定义各类参数的类型和验证规则) -- `build_and_run.sh` - 构建和部署脚本 +- `build_and_run.sh` - 智能部署脚本(自动检测 Git 更新) - `scripts/start_vllm.py` - vLLM 启动脚本 diff --git a/build_and_run.sh b/build_and_run.sh index cd205cf..6c1a0b0 100644 --- a/build_and_run.sh +++ b/build_and_run.sh @@ -1,7 +1,7 @@ #!/bin/bash -# vLLM R9700 Container 构建和部署脚本 -# 用于一键构建镜像并部署运行 +# vLLM R9700 Container 智能部署脚本 +# 自动检测 Git 代码更新,智能构建和部署 set -e @@ -9,15 +9,18 @@ set -e IMAGE_NAME="custom-vllm-r9700" IMAGE_TAG="latest" CONTAINER_NAME="custom-vllm-r9700" +PROJECT_DIR="/opt/project/vllm-r9700-container" MODEL_DIR="${MODEL_DIR:-/opt/models}" CONFIG_FILE="${CONFIG_FILE:-/opt/model_config.yaml}" LOCAL_MODEL_DIR="${LOCAL_MODEL_DIR:-/models}" +GIT_BRANCH="${GIT_BRANCH:-main}" # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' +CYAN='\033[0;36m' NC='\033[0m' # No Color # 打印带颜色的消息 @@ -37,35 +40,36 @@ print_error() { echo -e "${RED}[ERROR]${NC} $1" } +print_step() { + echo -e "${CYAN}[STEP]${NC} $1" +} + # 显示使用帮助 show_usage() { echo "用法:$0 [选项]" echo "" echo "选项:" - echo " -b, --build-only 仅构建镜像,不运行容器" - echo " -r, --rebuild 重新构建镜像(不使用缓存)" + echo " -f, --force 强制重新构建镜像(忽略 Git 状态)" echo " -s, --stop 仅停止并删除容器" echo " -d, --detach 后台运行容器(默认)" echo " -i, --interactive 交互式运行容器" echo " -c, --config FILE 指定配置文件路径" echo " -m, --models DIR 指定模型目录路径" echo " -p, --port PORT 指定服务端口" + echo " -b, --branch NAME 指定 Git 分支(默认:main)" echo " -h, --help 显示此帮助信息" echo "" echo "示例:" - echo " $0 # 构建并运行" - echo " $0 -b # 仅构建镜像" - echo " $0 -r # 重新构建并运行" + echo " $0 # 智能部署(检测 Git 更新)" + echo " $0 -f # 强制重新构建并部署" echo " $0 -s # 停止并删除容器" echo " $0 -p 8080 # 使用端口 8080 运行" - echo " $0 -c /path/to/config.yaml # 使用指定配置文件" - echo " $0 -m /path/to/models # 使用指定模型目录" + echo " $0 -b master # 使用 master 分支" exit 0 } # 解析命令行参数 -BUILD_ONLY=false -REBUILD=false +FORCE_BUILD=false STOP_ONLY=false DETACH=true CUSTOM_CONFIG="" @@ -74,12 +78,8 @@ CUSTOM_PORT="" while [[ $# -gt 0 ]]; do case $1 in - -b|--build-only) - BUILD_ONLY=true - shift - ;; - -r|--rebuild) - REBUILD=true + -f|--force) + FORCE_BUILD=true shift ;; -s|--stop) @@ -106,6 +106,10 @@ while [[ $# -gt 0 ]]; do CUSTOM_PORT="$2" shift 2 ;; + -b|--branch) + GIT_BRANCH="$2" + shift 2 + ;; -h|--help) show_usage ;; @@ -147,28 +151,116 @@ check_docker() { print_success "Docker 检查通过" } -# 构建镜像 -build_image() { - print_info "开始构建 Docker 镜像..." - print_info "镜像名称:${IMAGE_NAME}:${IMAGE_TAG}" +# 检查并切换到项目目录 +check_project_dir() { + print_step "检查项目目录..." - BUILD_ARGS="--no-cache" - if [ "$REBUILD" = false ]; then - BUILD_ARGS="" + if [ ! -d "$PROJECT_DIR" ]; then + print_error "项目目录不存在:${PROJECT_DIR}" + exit 1 fi - if docker build ${BUILD_ARGS} -t "${IMAGE_NAME}:${IMAGE_TAG}" .; then - print_success "镜像构建成功" + # 切换到项目目录 + cd "$PROJECT_DIR" + print_info "项目目录:${PROJECT_DIR}" + print_success "已切换到项目目录" +} + +# 检查 Git 仓库 +check_git() { + if [ ! -d ".git" ]; then + print_warning "当前目录不是 Git 仓库" + return 1 + fi + + # 检查 git 命令是否存在 + if ! command -v git &> /dev/null; then + print_warning "Git 未安装,跳过 Git 检查" + return 1 + fi + + return 0 +} + +# 拉取最新代码 +pull_latest_code() { + print_step "拉取最新代码..." + + # 保存当前分支 + current_branch=$(git rev-parse --abbrev-ref HEAD) + + # 尝试拉取 + if git fetch origin "${GIT_BRANCH}" 2>/dev/null; then + # 检查是否有更新 + LOCAL=$(git rev-parse HEAD) + REMOTE=$(git rev-parse origin/"${GIT_BRANCH}") + + if [ "$LOCAL" != "$REMOTE" ]; then + print_info "检测到代码更新,正在更新..." + if git pull origin "${GIT_BRANCH}" 2>/dev/null; then + print_success "代码已更新到最新版本" + return 0 # 有更新 + else + print_warning "代码拉取失败,继续执行" + return 1 # 无更新或失败 + fi + else + print_info "代码已是最新版本" + return 1 # 无更新 + fi + else + print_warning "无法连接到远程仓库,使用本地代码" + return 1 # 失败 + fi +} + +# 检查代码是否有本地修改 +has_local_changes() { + # 检查是否有未提交的更改 + if ! git diff --quiet 2>/dev/null; then + print_info "检测到未提交的更改" + return 0 + fi + + # 检查是否有暂存的更改 + if ! git diff --cached --quiet 2>/dev/null; then + print_info "检测到暂存的更改" + return 0 + fi + + return 1 # 无更改 +} + +# 构建镜像 +build_image() { + print_step "开始构建 Docker 镜像..." + print_info "镜像名称:${IMAGE_NAME}:${IMAGE_TAG}" + print_info "构建目录:${PROJECT_DIR}" + + BUILD_START=$(date +%s) + + if docker build --no-cache -t "${IMAGE_NAME}:${IMAGE_TAG}" .; then + BUILD_END=$(date +%s) + BUILD_TIME=$((BUILD_END - BUILD_START)) + + print_success "镜像构建成功 (耗时:${BUILD_TIME}秒)" docker images "${IMAGE_NAME}:${IMAGE_TAG}" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" + return 0 # 构建成功 else print_error "镜像构建失败" exit 1 fi } +# 检查镜像是否存在 +image_exists() { + docker image inspect "${IMAGE_NAME}:${IMAGE_TAG}" > /dev/null 2>&1 + return $? +} + # 运行容器 run_container() { - print_info "开始部署容器..." + print_step "开始部署容器..." # 设置卷挂载参数 VOLUME_ARGS="" @@ -252,32 +344,72 @@ run_container() { fi } -# 主流程 -main() { +# 智能部署主流程 +smart_deploy() { echo "==========================================" - echo "vLLM R9700 Container 构建和部署" + echo "vLLM R9700 Container 智能部署" echo "==========================================" echo "开始时间:$(date '+%Y-%m-%d %H:%M:%S')" echo "" + # 检查并切换到项目目录 + check_project_dir + # 检查 Docker check_docker # 停止旧容器 stop_container - # 构建镜像 - build_image + # 检查是否需要重新构建 + NEED_REBUILD=false - # 如果仅构建,退出 - if [ "$BUILD_ONLY" = true ]; then - print_success "镜像构建完成" - print_info "运行以下命令启动容器:" - echo " $0" - exit 0 + if [ "$FORCE_BUILD" = true ]; then + print_step "强制重新构建模式" + NEED_REBUILD=true + elif check_git; then + # 是 Git 仓库 + print_step "检查代码更新..." + + # 拉取最新代码并检查是否有更新 + if pull_latest_code; then + NEED_REBUILD=true + print_info "代码有更新,需要重新构建" + elif has_local_changes; then + NEED_REBUILD=true + print_info "检测到本地更改,需要重新构建" + else + # 检查镜像是否存在 + if ! image_exists; then + NEED_REBUILD=true + print_info "镜像不存在,需要构建" + else + print_info "代码无更新,跳过构建" + fi + fi + else + # 不是 Git 仓库或 Git 不可用 + print_warning "无法检测 Git 状态" + + # 检查镜像是否存在 + if ! image_exists; then + NEED_REBUILD=true + print_info "镜像不存在,需要构建" + else + print_info "使用现有镜像" + fi + fi + + # 构建镜像(如果需要) + if [ "$NEED_REBUILD" = true ]; then + echo "" + build_image + else + print_success "使用现有镜像" fi # 运行容器 + echo "" run_container echo "" @@ -288,4 +420,4 @@ main() { } # 执行主流程 -main +smart_deploy diff --git a/scripts/__pycache__/start_vllm.cpython-313.pyc b/scripts/__pycache__/start_vllm.cpython-313.pyc new file mode 100644 index 0000000..9cd44ac Binary files /dev/null and b/scripts/__pycache__/start_vllm.cpython-313.pyc differ