diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2c4243c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,23 @@ +node_modules +npm-debug.log +.git +.gitignore +README.md +README-EN.md +Dockerfile +.dockerignore +.nyc_output +coverage +.nyc_output +.coverage +.env +.env.local +.env.*.local +credentials.json +*.md +LICENSE +jest.config.js +babel.config.js +tests/ +run-tests.js +test-summary.js \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..71fea90 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +# 使用官方Node.js运行时作为基础镜像 +# 选择20-alpine版本以满足undici包的要求(需要Node.js >=20.18.1) +FROM node:20-alpine + +# 设置标签 +LABEL maintainer="GeminiCli2API Team" +LABEL description="Docker image for GeminiCli2API server" + +# 设置工作目录 +WORKDIR /app + +# 复制package.json和package-lock.json(如果存在) +COPY package*.json ./ + +# 安装依赖 +# 使用--production标志只安装生产依赖,减小镜像大小 +# 使用--omit=dev来排除开发依赖 +RUN npm install + +# 添加非root用户以提高安全性 +RUN addgroup -g 1001 -S nodejs +RUN adduser -S nextjs -u 1001 + +# 复制源代码 +COPY . . + +# 更改文件所有者为非root用户 +RUN chown -R nextjs:nodejs /app +USER nextjs + +# 创建目录用于存储日志和系统提示文件 +RUN mkdir -p /app/logs + +# 暴露端口 +EXPOSE 3000 + +# 添加健康检查 +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD node healthcheck.js || exit 1 + +# 设置启动命令 +# 使用默认配置启动服务器,支持通过环境变量配置 +# 通过环境变量传递参数,例如:docker run -e ARGS="--api-key mykey --port 8080" ... +CMD ["sh", "-c", "node src/api-server.js $ARGS"] \ No newline at end of file diff --git a/README.Docker.md b/README.Docker.md new file mode 100644 index 0000000..15f8840 --- /dev/null +++ b/README.Docker.md @@ -0,0 +1,93 @@ +# Docker部署指南 + +本指南将帮助您使用Docker部署GeminiCli2API服务。 + +## 构建Docker镜像 + +在项目根目录下执行以下命令来构建Docker镜像: + +```bash +docker build -t gemini-cli2api . +``` + +## 运行容器 + +### 基本运行 + +```bash +docker run -d -p 3000:3000 --name gemini-cli2api gemini-cli2api +``` + +### 通过ARGS环境变量配置服务 + +服务支持通过`ARGS`环境变量来配置,例如: + +```bash +docker run -d \ + -p 3000:3000 \ + -e ARGS="--api-key 123456 --host 0.0.0.0" \ + --name gemini-cli2api \ + gemini-cli2api +``` + +### 使用Base64编码的凭据 + +项目包含两个脚本用于自动处理Base64编码的凭据: +- `run-docker.bat` (Windows) +- `run-docker.sh` (Linux/Unix) + +这些脚本会自动生成包含凭据的`ARGS`环境变量: + +```bash +# Windows +run-docker.bat + +# Linux/Unix (首次使用需要授予权限) +chmod +x run-docker.sh +./run-docker.sh +``` + +### 挂载配置文件和日志目录 + +```bash +# 挂载配置文件 +docker run -d \ + -p 3000:3000 \ + -v /path/to/your/config.json:/app/config.json \ + --name gemini-cli2api \ + gemini-cli2api + +# 挂载日志目录 +docker run -d \ + -p 3000:3000 \ + -v /path/to/your/logs:/app/logs \ + --name gemini-cli2api \ + gemini-cli2api +``` + +## 访问服务 + +容器启动后,您可以通过以下URL访问服务: + +``` +http://localhost:3000 +``` + +## 可用端点 + +- `POST /v1/chat/completions` - OpenAI兼容聊天完成端点 +- `GET /v1/models` - OpenAI兼容模型列表端点 +- `POST /v1beta/models/{model}:generateContent` - Gemini兼容内容生成端点 +- `GET /v1beta/models` - Gemini兼容模型列表端点 +- `GET /health` - 健康检查端点 + +## 故障排除 + +如果容器无法启动,请检查以下内容: + +1. 确保端口3000未被其他进程占用 +2. 检查环境变量配置是否正确 +3. 查看容器日志以获取更多信息: + +```bash +docker logs gemini-cli2api \ No newline at end of file diff --git a/README.md b/README.md index fefc337..5c7e7bd 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,12 @@ --- +## 🐳 Docker 部署 + +项目支持通过 Docker 进行部署,详细指南请参阅 [Docker部署指南](./README.Docker.md)。 + +--- + ### 4. 调用 API > **提示**: 如果您在无法直接访问 Google/OpenAI/Claude/Kiro 服务的环境中使用,请先为您的终端设置全局 HTTP/HTTPS 代理。 diff --git a/healthcheck.js b/healthcheck.js new file mode 100644 index 0000000..dbc726d --- /dev/null +++ b/healthcheck.js @@ -0,0 +1,46 @@ +/** + * Docker健康检查脚本 + * 用于检查API服务器是否正常运行 + */ + +const http = require('http'); + +// 从环境变量获取主机和端口,如果没有设置则使用默认值 +const HOST = process.env.HOST || 'localhost'; +const PORT = process.env.SERVER_PORT || 3000; + +// 发送HTTP请求到健康检查端点 +const options = { + hostname: HOST, + port: PORT, + path: '/health', + method: 'GET', + timeout: 2000 // 2秒超时 +}; + +const req = http.request(options, (res) => { + // 如果状态码是200,表示服务健康 + if (res.statusCode === 200) { + console.log('Health check passed'); + process.exit(0); + } else { + console.log(`Health check failed with status code: ${res.statusCode}`); + process.exit(1); + } +}); + +// 处理请求错误 +req.on('error', (e) => { + console.error(`Health check failed: ${e.message}`); + process.exit(1); +}); + +// 设置超时处理 +req.on('timeout', () => { + console.error('Health check timed out'); + req.destroy(); + process.exit(1); +}); + +// 结束请求 +req.end(); \ No newline at end of file diff --git a/run-docker.bat b/run-docker.bat new file mode 100644 index 0000000..61680eb --- /dev/null +++ b/run-docker.bat @@ -0,0 +1,65 @@ +@echo off +:: run-docker-with-credentials.bat +:: 生成指定的Docker运行命令,使用USERPROFILE环境变量构建路径 + +setlocal enabledelayedexpansion + +echo 正在生成指定的Docker运行命令... + +:: 设置配置文件路径,使用USERPROFILE环境变量 +set "AWS_SSO_CACHE_PATH=%USERPROFILE%\.aws\sso\cache" +set "GEMINI_CONFIG_PATH=%USERPROFILE%\.gemini\oauth_creds.json" + +:: 检查AWS SSO缓存目录是否存在 +if exist "%AWS_SSO_CACHE_PATH%" ( + echo 发现AWS SSO缓存目录: %AWS_SSO_CACHE_PATH% +) else ( + echo 未找到AWS SSO缓存目录: %AWS_SSO_CACHE_PATH% + echo 注意:AWS SSO缓存目录不存在,Docker容器可能无法访问AWS凭证 +) + +:: 检查Gemini配置文件是否存在 +if exist "%GEMINI_CONFIG_PATH%" ( + echo 发现Gemini配置文件: %GEMINI_CONFIG_PATH% +) else ( + echo 未找到Gemini配置文件: %GEMINI_CONFIG_PATH% + echo 注意:Gemini配置文件不存在,Docker容器可能无法访问Gemini API +) + +:: 构建Docker运行命令,使用USERPROFILE环境变量构建的路径 +set "DOCKER_CMD=docker run -d ^" +set "DOCKER_CMD=!DOCKER_CMD! -p 3000:3000 ^" +set "DOCKER_CMD=!DOCKER_CMD! -e ARGS="--api-key 123456 --host 0.0.0.0" ^" +set "DOCKER_CMD=!DOCKER_CMD! -v "%AWS_SSO_CACHE_PATH%:/home/nextjs/.aws/sso/cache" ^" +set "DOCKER_CMD=!DOCKER_CMD! -v "%GEMINI_CONFIG_PATH%:/home/nextjs/.gemini/oauth_creds.json" ^" +set "DOCKER_CMD=!DOCKER_CMD! --name gemini-cli2api ^" +set "DOCKER_CMD=!DOCKER_CMD! gemini-cli2api" + +:: 显示将要执行的命令 +echo. +echo 生成的Docker命令: +echo !DOCKER_CMD! +echo. + +:: 将命令保存到文件中 +echo !DOCKER_CMD! > docker-run-command.txt +echo 命令已保存到 docker-run-command.txt 文件中,您可以从该文件复制完整的命令。 + +:: 询问用户是否要执行该命令 +echo. +set /p EXECUTE_CMD="是否要立即执行该Docker命令?(y/n): " +if /i "!EXECUTE_CMD!"=="y" ( + echo 正在执行Docker命令... + !DOCKER_CMD! + if !errorlevel! equ 0 ( + echo Docker容器已成功启动! + echo 您可以通过 http://localhost:3000 访问API服务 + ) else ( + echo Docker命令执行失败,请检查错误信息 + ) +) else ( + echo 命令未执行,您可以手动从docker-run-command.txt文件复制并执行命令 +) + +echo 脚本执行完成 +pause \ No newline at end of file diff --git a/run-docker.sh b/run-docker.sh new file mode 100644 index 0000000..83288ce --- /dev/null +++ b/run-docker.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# run-docker-with-credentials.sh +# 生成指定的Docker运行命令,使用HOME环境变量构建路径 + +echo "正在生成指定的Docker运行命令..." + +# 设置配置文件路径,使用HOME环境变量 +AWS_SSO_CACHE_PATH="$HOME/.aws/sso/cache" +GEMINI_CONFIG_PATH="$HOME/.gemini/oauth_creds.json" + +# 检查AWS SSO缓存目录是否存在 +if [ -d "$AWS_SSO_CACHE_PATH" ]; then + echo "发现AWS SSO缓存目录: $AWS_SSO_CACHE_PATH" +else + echo "未找到AWS SSO缓存目录: $AWS_SSO_CACHE_PATH" + echo "注意:AWS SSO缓存目录不存在,Docker容器可能无法访问AWS凭证" +fi + +# 检查Gemini配置文件是否存在 +if [ -f "$GEMINI_CONFIG_PATH" ]; then + echo "发现Gemini配置文件: $GEMINI_CONFIG_PATH" +else + echo "未找到Gemini配置文件: $GEMINI_CONFIG_PATH" + echo "注意:Gemini配置文件不存在,Docker容器可能无法访问Gemini API" +fi + +# 构建Docker运行命令,使用HOME环境变量构建的路径 +DOCKER_CMD="docker run -d \\ + -p 3000:3000 \\ + -e ARGS=\"--api-key 123456 --host 0.0.0.0\" \\ + -v $AWS_SSO_CACHE_PATH:/home/nextjs/.aws/sso/cache \\ + -v $GEMINI_CONFIG_PATH:/home/nextjs/.gemini/oauth_creds.json \\ + --name gemini-cli2api \\ + gemini-cli2api" + +# 显示将要执行的命令 +echo +echo "生成的Docker命令:" +echo "$DOCKER_CMD" +echo + +# 将命令保存到文件中 +echo "$DOCKER_CMD" > docker-run-command.txt +echo "命令已保存到 docker-run-command.txt 文件中,您可以从该文件复制完整的命令。" + +# 询问用户是否要执行该命令 +echo +read -p "是否要立即执行该Docker命令?(y/n): " EXECUTE_CMD +if [ "$EXECUTE_CMD" = "y" ] || [ "$EXECUTE_CMD" = "Y" ]; then + echo "正在执行Docker命令..." + eval "$DOCKER_CMD" + if [ $? -eq 0 ]; then + echo "Docker容器已成功启动!" + echo "您可以通过 http://localhost:3000 访问API服务" + else + echo "Docker命令执行失败,请检查错误信息" + fi +else + echo "命令未执行,您可以手动从docker-run-command.txt文件复制并执行命令" +fi + +echo "脚本执行完成" \ No newline at end of file diff --git a/src/gemini/gemini-strategy.js b/src/gemini/gemini-strategy.js index 23cc342..e4c0c3b 100644 --- a/src/gemini/gemini-strategy.js +++ b/src/gemini/gemini-strategy.js @@ -36,7 +36,6 @@ class GeminiStrategy extends ProviderStrategy { } async applySystemPromptFromFile(config, requestBody) { - console.log(`[System Prompt] Applying system prompt from ${config.SYSTEM_PROMPT_FILE_PATH} in '${config.SYSTEM_PROMPT_MODE}' mode for provider 'gemini'.`); if (!config.SYSTEM_PROMPT_FILE_PATH) { return requestBody; }