# llama-cpp-docker-stack **Repository Path**: aizuda/llama-cpp-docker-stack ## Basic Information - **Project Name**: llama-cpp-docker-stack - **Description**: llama.cpp Docker 本地模型服务栈 本项目使用 Docker Compose 在 NVIDIA GPU 上运行多个 llama.cpp 服务,并通过一个 Nginx 网关提供统一 HTTP 入口。聊天和 Embedding 接口采用 OpenAI 兼容格式,/v1/rerank 是 llama.cpp 提供的扩展接口。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2026-07-10 - **Last Updated**: 2026-07-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # llama.cpp Docker 本地模型服务栈 本项目使用 Docker Compose 在 NVIDIA GPU 上运行多个 llama.cpp 服务,并通过 Python 网关(`nginx/gateway.py`)提供**统一 HTTP 入口**。聊天、Embedding 使用 OpenAI 兼容接口;`/v1/rerank` 为 llama.cpp 扩展。可选 MinerU 文档解析也走同一网关。 ## 能做什么 | 能力 | 入口 | 说明 | | --- | --- | --- | | 聊天 / 多模态对话 / 栈内 OCR | `POST /v1/chat/completions` | `llama-cpp` | | 文本向量 | `POST /v1/embeddings` | `embedding`(bge / Qwen3-Embedding) | | 图文向量 | `POST /v1/embeddings` | `embedding-vl`(model 名含 VL 时自动分流) | | 重排序 | `POST /v1/rerank` | `reranker` | | 文档解析(可选) | `/mineru/*`、`/mineru-gpu/*` | MinerU CPU/GPU | | 占用监控 / 卸载模型 | `/`、`/usage`、`/api/unload` | 需 API Key 登录 | 默认入口:`http://127.0.0.1:8023` 模型权重与 API Key 仅保存在本机,不纳入 Git。 ## 架构 ```text 客户端 │ ▼ Python gateway :8023 (nginx/gateway.py) ├─ /login、/dashboard、/usage、/api/unload 监控与运维(需 Key) ├─ /mineru/* ──► mineru-api-cpu (profile: mineru) ├─ /mineru-gpu/* ──► mineru-api-gpu (profile: mineru-gpu) ├─ /v1/embeddings │ ├─ model 含 vl/vision/multimodal ──► embedding-vl │ └─ 其他 ───────────────────────────► embedding ├─ /v1/rerank ──► reranker └─ 其他路径 ──► llama-cpp (聊天 / OCR / 推理) │ 共享 ./models(只读)+ Docker Secret(llama_api_key) ``` ### Compose 服务 | 服务 | 容器名 | 作用 | 启动方式 | | --- | --- | --- | --- | | `gateway` | `llama-cpp-gateway` | 统一入口、分流、监控页、流式透传 | 默认 | | `llama-cpp` | `llama-cpp` | 聊天 / 工具调用 / 栈内多模态 OCR | 默认 | | `embedding` | `embedding` | 文本 Embedding | 默认 | | `embedding-vl` | `embedding-vl` | 图文 Embedding | 默认 | | `reranker` | `reranker` | Rerank | 默认 | | `mineru-api-cpu` | `mineru-api-cpu` | 文档解析 pipeline | `--profile mineru` | | `mineru-api-gpu` | `mineru-api-gpu` | 文档解析 VLM | `--profile mineru-gpu` | ### 角色 preset 每个 llama.cpp 后端 `models-max=1`,配置互相隔离,避免文本/VL 向量互踢: | 服务 | preset | | --- | --- | | `llama-cpp` | `models/presets/chat.ini` | | `embedding` | `models/presets/embedding.ini` | | `embedding-vl` | `models/presets/embedding-vl.ini` | | `reranker` | `models/presets/reranker.ini` | `models/models.ini` 仅作全量目录参考,运行时不直接加载。 ### 端口一览 | 地址 | 说明 | | --- | --- | | `http://127.0.0.1:8023` | **统一入口**(推荐) | | `http://127.0.0.1:8024` | MinerU CPU 直连(可选) | | `http://127.0.0.1:8025` | MinerU GPU 直连(可选) | ## 项目结构 ```text . ├─ docker-compose.yml # 主栈 + 可选 MinerU profiles ├─ README.md ├─ LICENSE ├─ docs/ # 全部说明文档 │ ├─ README.md │ ├─ MODEL_GUIDE.md │ ├─ IHONGHU_*.md │ ├─ TEST_REPORT.md / SHA256SUMS │ └─ mineru/ # MinerU 文档 │ ├─ nginx/ │ ├─ gateway.py # 运行时网关(分流 / 流式 / 监控 / MinerU 代理) │ ├─ gateway.conf # 纯 Nginx 参考(默认不用) │ └─ static/ │ ├─ login.html # 监控登录页 │ └─ dashboard.html # 占用监控页 │ ├─ models/ │ ├─ models.ini # 全量目录参考 │ ├─ models.ini.example │ ├─ presets/ │ │ ├─ chat.ini │ │ ├─ embedding.ini │ │ ├─ embedding-vl.ini │ │ └─ reranker.ini │ └─ *.gguf # 权重(Git 忽略) │ ├─ secrets/ │ └─ llama-api-key.txt # API Key(Git 忽略) │ ├─ mineru/ # 文档解析(可并入主 compose profile) │ ├─ README.md │ ├─ compose.yaml # 也可单独启动 │ └─ Dockerfile.cpu / Dockerfile.gpu │ └─ tests/ ├─ *_smoke_test.py / retrieval_demo.py ├─ test_*.py ├─ 8e769fa46cd3168d4daa46f6f0ca2ded.jpg └─ output/ # 本地联调输出(结果 Git 忽略) └─ README.md ``` `.gitignore`:忽略 `models/*` 权重、`secrets/*`、`tests/output/**` 结果文件;保留 preset 与 `tests/output/README.md`。 ## 环境要求 - Docker Engine / Docker Desktop,Compose v2 - NVIDIA 显卡 + 驱动;Linux 需 NVIDIA Container Toolkit - 本地镜像:`llamacpp:server-cuda`、`python:3.12-slim` - `models/presets/*.ini` 引用的 GGUF 已放入 `models/` - 跑测试脚本建议 Python 3.9+ 创建 llama.cpp 镜像标签: ```bash docker pull ghcr.io/ggml-org/llama.cpp:server-cuda docker tag ghcr.io/ggml-org/llama.cpp:server-cuda llamacpp:server-cuda ``` 当前验证镜像:`b9917` / revision `4a7ee3126`。 ## 快速启动 ### 1. 创建 API Key ```powershell New-Item -ItemType Directory -Force secrets | Out-Null $bytes = New-Object byte[] 32 $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() $rng.GetBytes($bytes); $rng.Dispose() Set-Content -Encoding ascii -NoNewline -LiteralPath secrets/llama-api-key.txt -Value ([Convert]::ToBase64String($bytes)) ``` ```bash mkdir -p secrets openssl rand -hex 32 | tr -d '\n' > secrets/llama-api-key.txt ``` ### 2. 准备模型与 preset 把 `.gguf` 放到 `models/`,并维护对应 `models/presets/*.ini`(可同步更新 `models/models.ini` 目录)。 最小集:1 个聊天模型 + 1 个文本 Embedding + 1 个 Reranker。视觉模型需匹配的 `mmproj`。详见 [docs/MODEL_GUIDE.md](docs/MODEL_GUIDE.md)。 ### 3. 启动 ```powershell # 仅主栈(聊天 / embedding / rerank / 监控) docker compose up -d # 主栈 + MinerU CPU(推荐文档解析时用) docker compose --profile mineru up -d # 主栈 + MinerU CPU + GPU(需约 8GB+ 空闲显存) docker compose --profile mineru --profile mineru-gpu up -d ``` ```bash docker compose ps curl http://127.0.0.1:8023/health # ok curl http://127.0.0.1:8023/mineru/health # 启用 mineru profile 后 ``` 浏览器监控:打开 `http://127.0.0.1:8023/`,用 `secrets/llama-api-key.txt` 登录。 ### 4. 停止 ```powershell docker compose --profile mineru --profile mineru-gpu down # 或 docker compose down ``` ## 统一入口速查 | 方法 | 路径 | 鉴权 | 说明 | | --- | --- | --- | --- | | GET | `/health` | 否 | 网关探活,返回 `ok` | | GET | `/login` | 否 | 监控登录页 | | GET | `/` `/dashboard` | Key | 占用监控 | | GET | `/usage` | Key | GPU + 已加载模型 JSON | | POST | `/api/unload` | Key | 卸载模型 | | POST | `/v1/chat/completions` | Key | 聊天 / 栈内 OCR | | POST | `/v1/embeddings` | Key | 文本或 VL 向量(按 model 分流) | | POST | `/v1/rerank` | Key | 重排 | | * | `/mineru/*` | 否* | 代理到 MinerU CPU(服务需启动) | | * | `/mineru-gpu/*` | 否* | 代理到 MinerU GPU | \* MinerU 后端本身默认无 Key;是否暴露取决于端口绑定与防火墙。主栈推理接口需 `Authorization: Bearer `。 ```powershell $env:LLAMA_API_KEY = (Get-Content -Raw secrets/llama-api-key.txt).Trim() ``` ```bash export LLAMA_API_KEY="$(cat secrets/llama-api-key.txt)" ``` ## MinerU 文档解析 | 版本 | 网关路径 | 直连 | profile | backend | | --- | --- | --- | --- | --- | | CPU | `/mineru` | `:8024` | `mineru` | `pipeline` | | GPU | `/mineru-gpu` | `:8025` | `mineru-gpu` | `vlm-engine` | ```powershell # 经统一网关解析 curl -X POST "http://127.0.0.1:8023/mineru/file_parse" ` -F "files=@.\document.pdf" ` -F "backend=pipeline" ` -F "return_md=true" # 冒烟 py -3 -B tests\mineru_api_smoke_test.py --variant cpu ``` 选型(Markdown / 结构化 / 同步异步)见: - [docs/mineru/USAGE_MODES.md](docs/mineru/USAGE_MODES.md) - [docs/mineru/API.md](docs/mineru/API.md) - [docs/mineru/DEPLOY.md](docs/mineru/DEPLOY.md) ## 测试 ```powershell # 单元测试 py -3 -m unittest discover -s tests -p "test_*.py" -v # 本地联调(服务已启动) $env:LLAMA_API_KEY = (Get-Content -Raw secrets/llama-api-key.txt).Trim() py -3 -B tests\vl_embedding_smoke_test.py py -3 -B tests\retrieval_demo.py py -3 -B tests\paddleocr_vl_smoke_test.py py -3 -B tests\mineru_api_smoke_test.py --variant cpu ``` 联调产物写入 `tests/output/`(默认不提交)。 ## 模型与文档索引 | 文档 | 内容 | | --- | --- | | [docs/README.md](docs/README.md) | **全部文档索引** | | [docs/MODEL_GUIDE.md](docs/MODEL_GUIDE.md) | 本地模型与端点选型 | | [docs/mineru/USAGE_MODES.md](docs/mineru/USAGE_MODES.md) | MinerU:什么时候用什么模式 | | [docs/mineru/API.md](docs/mineru/API.md) | MinerU HTTP API | | [docs/mineru/DEPLOY.md](docs/mineru/DEPLOY.md) | MinerU 部署运维 | | [mineru/README.md](mineru/README.md) | MinerU 构建目录入口 | | [docs/IHONGHU_VL_EMBEDDING_GUIDE.md](docs/IHONGHU_VL_EMBEDDING_GUIDE.md) | 外部 ihonghu VL Embedding | | [docs/IHONGHU_PADDLEOCR_VL_GUIDE.md](docs/IHONGHU_PADDLEOCR_VL_GUIDE.md) | 外部 ihonghu OCR | | [docs/TEST_REPORT.md](docs/TEST_REPORT.md) | Qwythos GGUF 上游验证记录 | | [docs/SHA256SUMS](docs/SHA256SUMS) | 本地模型哈希清单 | ## 常用运维 ```bash docker compose ps docker compose --profile mineru ps docker compose logs -f gateway docker compose logs -f llama-cpp embedding embedding-vl reranker docker compose logs -f mineru-api-cpu # 重建网关(改 gateway.py 后) docker compose up -d --force-recreate gateway # 卸载已加载模型释放显存(需 Key) curl -X POST http://127.0.0.1:8023/api/unload \ -H "Authorization: Bearer $LLAMA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"all":true}' ``` ## 常见问题 ### 网关一直不 healthy 四个 llama 后端需先 healthy: ```bash docker compose ps docker compose logs llama-cpp embedding embedding-vl reranker ``` ### 文本 / VL Embedding 并发 500 已拆成 `embedding` 与 `embedding-vl`。确认使用当前 compose,并走 `8023`。 ### 模型加载慢 冷启动与换模(`models-max=1`)会加载 GGUF;带 mmproj 更慢。可用监控页固定常用模型或先卸载其它模型。 ### `/mineru` 502 MinerU 未启动:`docker compose --profile mineru up -d`。 ### 监控页 unauthorized 使用 `secrets/llama-api-key.txt` 登录,或 API 带 `Authorization: Bearer ...`。改 Key 后: ```bash docker compose up -d --force-recreate gateway ``` ### 显存不足 1. 监控页卸载模型 2. 换更小量化 / 降 `ctx-size` 3. 不要同时开大聊天 + MinerU GPU 4. `docker compose stop llama-cpp embedding-vl` 等按需停服务 ## 安全提示 - 端口 `8023` 默认绑定所有网卡;仅本机可改为 `127.0.0.1:8023:8080` - `/health`、`/v1/models` 默认不鉴权;监控与卸载需 Key - `/mineru*` 转发本身不额外鉴权(后端亦默认无 Key) - 无 TLS;跨机访问请加反向代理与防火墙 - 勿提交 API Key、模型权重与隐私样例 ## 当前验证状态 - 主栈五容器 + 可选 `mineru-api-cpu` 可 healthy 运行 - 网关按 model 分流文本/VL embedding;聊天 SSE 流式正常 - `/usage`、登录监控页、`/api/unload` 可用 - `/mineru/health` 与 `/mineru/file_parse` 经网关实测通过 - `tests/vl_embedding_smoke_test.py`、`retrieval_demo.py`、`paddleocr_vl_smoke_test.py`、`mineru_api_smoke_test.py`(CPU)已通过