diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..833213e --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,59 @@ +name: Build and Push Docker Image to GHCR + +on: + push: + branches: + - main + tags: + - "v*.*.*" + pull_request: + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha,prefix=sha-,format=short + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/README.md b/README.md index 7291912..045af29 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Bun](https://img.shields.io/badge/runtime-Bun-black)](https://bun.sh) [![TypeScript](https://img.shields.io/badge/language-TypeScript-blue)](https://www.typescriptlang.org) +[![Docker Image](https://img.shields.io/badge/ghcr.io-gojam11%2Fllmrelayservice-blue?logo=docker)](https://github.com/GoJam11/LLMRelayService/pkgs/container/llmrelayservice) LRS 是一个基于 **Bun + Hono** 的轻量 LLM 中继服务。它将多个 AI 服务商统一在单一入口下,配合内置的 Web 控制台,让你精确观测每一笔请求的延迟、Token 用量与缓存命中情况。 @@ -123,15 +124,11 @@ Railway / Render 等平台部署时构建命令同上。 ### Docker 部署 ```bash -# 1. 复制并配置环境变量 +# 1. 复制并配置环境变量(至少设置 GATEWAY_API_KEY,PASSWORD 可选) cp .env.example .env -# 至少设置 GATEWAY_API_KEY(PASSWORD 可选) # 2. 启动服务(包含内置 PostgreSQL) GATEWAY_API_KEY=your-key docker compose up -d - -# 或者使用 .env 文件 -docker compose up -d ``` 访问 `http://localhost:3000` 打开控制台。 diff --git a/changelog/2026-04-30.md b/changelog/2026-04-30.md index 186d458..cbb015e 100644 --- a/changelog/2026-04-30.md +++ b/changelog/2026-04-30.md @@ -2,6 +2,15 @@ ### 新增 +- 添加 GitHub Actions 工作流 `.github/workflows/docker-publish.yml`,使用 GHCR(`ghcr.io`)自动构建并推送 Docker 镜像: + - 触发条件:推送到 `main` 分支、推送语义版本 tag(`v*.*.*`)、以及针对 `main` 的 Pull Request(仅构建不推送) + - 使用 `docker/metadata-action` 自动生成 tag(branch、semver、short SHA) + - 启用 GitHub Actions 缓存加速构建(`cache-from/cache-to: type=gha`) + - 使用内置 `GITHUB_TOKEN` 进行 GHCR 认证,无需额外配置 Secret +- 更新 `README.md` 及 `docker-compose.yml` 完善 Docker 部署指南: + - `docker-compose.yml` 改为默认使用 GHCR 预构建镜像(`ghcr.io/gojam11/llmrelayservice:main`) + - README Docker 部分精简为纯用户视角的启动步骤,去除 CI 内部细节与本地构建说明 + - 顶部徽章区新增 GHCR 镜像徽章 - **API Key 模型限制**:新增通过 API key 限制可使用模型的白名单机制,前后端全实现。 - 数据库 `console_api_keys` 表新增 `allowed_models_json` 列(JSON 字符串数组,空数组=不限制),通过启动时 inline migration 自动迁移(迁移编号 0015)。 - 后端 `src/api-keys.ts`:`StoredApiKeyRecord` 和 `AuthenticatedApiKeyInfo` 均增加 `allowed_models: string[]` 字段;新增 `setApiKeyAllowedModels(id, models)` 函数;`authenticateManagedApiKey` 返回携带 `allowed_models` 的完整信息。 @@ -14,9 +23,9 @@ ### 变更 +- `.github/workflows/docker-publish.yml` 新增 `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true`,主动 opt-in Node.js 24 运行时(强制切换时间:2026-06-02) - **API Key 模型限制 review 修复**: - `src/index.ts`:`authenticateGateway()` 返回类型改为正确使用 `AuthenticatedApiKeyInfo | null`;限制检查变量重命名为 `clientRequestedModel` 并添加注释说明检查对象是 pre-resolution 的 alias/model 名,而非 resolved 上游模型;配置了非空 `allowed_models` 的 key 遇到 `unknown` 模型时 fail closed(返回 403)。 - `src/api-keys.ts`:导出纯函数 `isModelAllowed(model, patterns)`;`parseAllowedModels` 读取时 trim + dedup;`setApiKeyAllowedModels` 写入时 `Array.from(new Set(...))` 去重。 - `src/db/migrate.ts`:注释编号整理,将 `token_usage_estimated` migration 编号从 `0014` 更正为 `0016`,确保编号唯一有序。 - `test/api-key-model-restrictions.test.ts`:新增完整测试覆盖 `isModelAllowed` exact/wildcard、normalize/parse、gateway enforcement,以及 alias 语义(允许 alias 访问、拒绝直接访问底层模型、unknown 模型 fail closed、admin key 绕过)。 - diff --git a/docker-compose.yml b/docker-compose.yml index 5cbfc01..dcf64c9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: app: - build: . + image: ghcr.io/gojam11/llmrelayservice:main ports: - "3000:3000" environment: