精彩小说尽在58小说网!

58小说网 > 都市 > KingFlow AI Docker 与云服务器接入教程

KingFlow AI Docker 与云服务器接入教程

KingFlow AI Docker 与云服务器接入教程

佚名 著

都市连载

KingFlow AI 云端部署 应用 Compose Nginx 运维 排错 KingFlow AI Docker 与云服务器接入教程 从容器化部署到反向代理 健康检查 流式响应和密钥保护 本教程把 KingFlow AI 封装成一个只在服务端持有密钥的轻量 API 服务。你将使用 FastAPI 和 OpenAI 兼容 SDK 编写普通请求与流式接口,再

主角:   更新:2026-10-23 14:23:38

继续看书

扫描二维码手机上阅读

二维码
  • 读书简介
  • 免费章节在线阅读

男女主角分别是的都市小说《KingFlow AI Docker 与云服务器接入教程》,由网络作家“佚名”所著,讲述一系列精彩纷呈的故事,本站纯净无弹窗,精彩内容欢迎阅读!小说详情介绍:KingFlow AI 云端部署 应用 Compose Nginx 运维 排错 KingFlow AI Docker 与云服务器接入教程 从容器化部署到反向代理 健康检查 流式响应和密钥保护 本教程把 KingFlow AI 封装成一个只在服务端持有密钥的轻量 API 服务。你将使用 FastAPI 和 OpenAI 兼容 SDK 编写普通请求与流式接口,再

《KingFlow AI Docker 与云服务器接入教程》精彩片段

KingFlow AI Docker 与云服务器接入教程

从容器化部署到反向** 健康检查 流式响应和密钥保护

本教程把 KingFlow AI 封装成一个只在服务端持有密钥的轻量 API 服务。你将使用 FastAPI 和 OpenAI 兼容 SDK 编写普通请求与流式接口,再用 Docker Compose、健康检查和 Nginx 完成单机云服务器部署。示例适合个人服务、团队内部工具和小型业务后端。

内容核验日期 2026-10-23

云服务器中的容器化模型网关

部署架构

客户端不直接获得 KingFlow 密钥。请求先到你控制的 ****S 入口,再由容器中的服务端代码调用 KingFlow AI。

组件职责安全边界
浏览器或业务服务只访问你自己的域名不接触 KingFlow API Key
Nginx终止 TLS 并转发请求关闭流式响应缓冲
FastAPI 容器校验应用令牌并调用模型限制输入长度和超时
KingFlow AI按兼容协议转发模型请求使用控制台中的模型 ID

开始前的准备

  • 一台能够访问 KingFlow AI 接口的 Linux 云服务器,建议先完成系统更新、防火墙和 SSH 安全配置。
  • Docker Engine 与 Docker Compose v2。执行 docker compose version 可确认 Compose 是否可用。
  • KingFlow AI 控制台生成的 sk- API Key,以及模型广场或控制台显示的完整模型 ID。
  • 可选的域名和 TLS 证书。没有域名时先在服务器本机验证,再决定是否开放外部访问。

OpenAI 兼容 *ase **L 为 https://api.**nju**shen.com/v1。Anthropic 兼容 *ase **L 为 https://api.**nju**shen.com。

创建项目目录

kingflow-service/
├─ app.py
├─ requirements.txt
├─ Dockerfile
├─ compose.yaml
├─ .dockerignore
└─ secrets/
   ├─ kingflow_api_key.txt
   └─ app_token.txt

secrets 目录只放在服务器上,并从版本控制和 Docker 构建上下文中排除。

编写依赖文件

fastapi
uvicorn[stan**rd]
openai

编写服务端应用

import h**c
import json
import os
from pathli* import Path

from fastapi import FastAPI, Header, ****Exception
from fastapi.responses import StreamingResponse
from openai import OpenAI
from py**ntic import *aseModel, Field


def read_secret(env_name: str) -> str:
    path = Path(os.environ[env_name])
    value = path.read_text(encoding="utf-8").strip()
    if not value:
        raise RuntimeError(f"{env_name} 指向的 Secret 为空")
    return value


KINGFLOW_API_KEY = read_secret("KINGFLOW_API_KEY_FILE")
APP_TOKEN = read_secret("APP_TOKEN_FILE")
MODEL_ID = os.environ["KINGFLOW_MODEL_ID"]

client = OpenAI(
    api_key=KINGFLOW_API_KEY,
    *ase_url=os.getenv(
        "KINGFLOW_*ASE_**L",
        "https://api.**nju**shen.com/v1",
    ),
    timeout=45.0,
    **x_retries=2,
)

app = FastAPI(title="KingFlow Gateway")


class ChatRequest(*aseModel):
    prompt: str = Field(min_length=1, **x_length=8000)


def authorize(token: str | None) -> None:
    if not token or not h**c.compare_digest(token, APP_TOKEN):
        raise ****Exception(status_code=401, detail="invalid app token")


@app.get("/healthz")
def healthz():
    # 只检查本地进程,不触发模型调用和计费。
    return {"status": "ok"}


@app.post("/chat")
def chat(*ody: ChatRequest, x_app_token: str | None = Header(default=None)):
    authorize(x_app_token)
    response = client.chat.completions.create(
        model=MODEL_ID,
        messages=[{"role": "user", "content": *ody.prompt}],
    )
    return {"text": response.choices[0].message.content or ""}


@app.post("/chat/stream")
def chat_stream(*ody: ChatRequest, x_app_token: str | None = Header(default=None)):
    authorize(x_app_token)

    def events():
        stream = client.chat.completions.create(
            model=MODEL_ID,
            messages=[{"role": "user", "content": *ody.prompt}],
            stream=True,
        )
        for chunk in stream:
            text = chunk.choices[0].delta.content or ""
            if text:
                payload = json.dumps({"text": text}, ensure_ascii=False)
                yield f"**ta: {payload}\n\n"
        yield "**ta: [DONE]\n\n"

    return StreamingResponse(
        events(),
        media_type="text/event-stream",
        headers={"Cache-Control": "no-cache", "X-Accel-*uffering": "no"},
    )

/healthz 只检查本地进程,不调用模型。/chat/stream 使用 SSE 分段返回文本。

构建容器镜像

FROM python:3.13-slim

ENV PYTHONDONTWRITE*YTECODE=1 \
    PYTHONUN*UFFERED=1

WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py ./
RUN useradd --create-home --uid 10001 appuser \
    && chown -R appuser:appuser /app

USER appuser
EXPOSE 8000

CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers"]

编写 Compose 配置

services:
  api:
    *uild: .
    restart: unless-stopped
    environment:
      KINGFLOW_*ASE_**L: https://api.**nju**shen.com/v1
      KINGFLOW_MODEL_ID: <控制台中的完整模型ID>
      KINGFLOW_API_KEY_FILE: /run/secrets/kingflow_api_key
      APP_TOKEN_FILE: /run/secrets/app_token
    secrets:
      - kingflow_api_key
      - app_token
    ports:
      - "127.0.0.1:8000:8000"
    healthcheck:
      test: ["CMD", "python", "-c", "import urlli*.request; urlli*.request.urlopen('http://127.0.0.1:8000/healthz', timeout=3)"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

secrets:
  kingflow_api_key:
    file: ./secrets/kingflow_api_key.txt
  app_token:
    file: ./secrets/app_token.txt

Secret 以只读文件挂载;容器同时使用只读文件系统和最小权限。

排除敏感文件

.git
.env
secrets/
__pycache__/
*.pyc
生产部署链路
图二 从密钥到容器、健康检查、反向**和客户端的部署链路。AI 生成示意图。

创建密钥文件

mkdir -p secrets
printf '%s' 'sk-替换为你的真实密钥' > secrets/kingflow_api_key.txt
openssl rand -hex 32 > secrets/app_token.txt
chmod 600 secrets/*.txt

把占位密钥替换为控制台生成的真实值。应用令牌用于保护你自己的接口。

启动和验证容器

docker compose config
docker compose *uild --pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 api

测试普通响应和流式响应

APP_TOKEN=$(cat secrets/app_token.txt)

curl -sS http://127.0.0.1:8000/chat \
  -H "Content-Type: application/json" \
  -H "X-App-Token: ${APP_TOKEN}" \
  -d '{"prompt":"请回复:Docker 接入成功"}'

curl -N http://127.0.0.1:8000/chat/stream \
  -H "Content-Type: application/json" \
  -H "X-App-Token: ${APP_TOKEN}" \
  -d '{"prompt":"用三句话介绍流式输出"}' 

配置 Nginx 反向**

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # ssl_certificate 和 ssl_certificate_key 使用你的证书路径

    client_**x_*ody_size 1m;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection "";

        proxy_*uffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

替换域名和证书路径。关闭**缓冲,避免流式内容被聚合。

设置公网边界

  • 容器端口绑定到 127.0.0.1,公网只开放 Nginx 的 443 端口。不要把 8000 直接映射到 0.0.0.0。
  • 应用接口必须继续校验 X-App-Token。TLS 只能保护传输,不能替代访问控制。
  • 生产环境可把 X-App-Token 换成正式身份系统、签名请求或**鉴权,并设置速率限制。

日常运维

任务命令检查重点
查看状态docker compose ps服务应显示 running 和 healthy
查看日志docker compose logs --tail=100 api确认没有输出密钥或完整敏感提示词
更新代码docker compose up -d --*uildCompose 会按新镜像重建服务
更新配置docker compose up -d不要只执行 restart,配置变化需要重建容器
停止服务docker compose stop保留容器以便再次启动

更新密钥文件后应重新创建容器,使进程重新读取 Secret。验证健康状态后再切换流量。

常见故障排查

现象常见原因处理方法
容器 unhealthy应用未启动或本地端口不可达查看容器日志并在容器内访问 /healthz
401 来自本地服务X-App-Token 缺失或错误重新读取 app_token.txt 并检查请求头
上游 401KingFlow 密钥无效 已禁用或额度不足重新复制密钥并检查账户状态
上游 404模型 ID 不存在或当前分组不可用从控制台复制完整模型 ID
上游 503所选通道暂时没有可用账号有限重试或切换同类备用模型
流式输出一次性出现**缓冲未关闭确认 proxy_*uffering off 和响应头设置
约一分钟后中断**读取超时或上游长时间无数据核对 proxy_read_timeout 并检查上游状态

密钥和数据安全

  • 不要把 KingFlow API Key 写入镜像、代码、Compose 文件、前端 J**aScript 或移动端安装包。
  • Docker Secret 会把密钥作为只读文件挂载到容器;仍应限制服务器账号、备份和宿主机文件权限。
  • 日志只记录时间、模型、状态码、耗时和本地追踪 ID。隐藏 Authorization、x-api-key、Cookie、应用令牌和敏感提示词。
  • 开发、测试和生产分别使用不同密钥。怀疑泄露时立即停用旧密钥,创建新密钥并检查近期用量。
  • 对外服务需要请求大小限制、并发限制、速率限制和成本告警,避免异常流量直接放大为模型费用。

上线检查清单

  • docker compose config 能通过,且配置中没有硬编码真实密钥。
  • 容器以非 root 用户运行,文件系统只读,并移除了不需要的 Linux capa**lities。
  • 本地 /healthz 返回 ok,健康检查不会触发上游模型调用。
  • 普通接口与流式接口都能返回内容,模型 ID 来自当前控制台。
  • 8000 只绑定在 127.0.0.1,公网流量通过 ****S 和鉴权进入。
  • Nginx 已关闭响应缓冲并为长响应设置合理读取超时;日志、告警和用量监控不会保存密钥或完整敏感内容。
本文档包含的密钥、域名和模型 ID 均为占位内容,部署时请替换为自己的配置。