ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用Docker部署New-API:实现大模型API统一网关与令牌管理

用Docker部署New-API:实现大模型API统一网关与令牌管理 很多人手里都攒着一堆大模型API的keyChatGPT的、Claude的、DeepSeek的、各家国产模型的散落得到处都是。真正要开发一个自己的AI应用时问题就来了要么这个渠道突然限流要么那个服务商接口升级要改代码钥钥钥钥切换维护成本极高。New-API这个开源项目就是冲着这个痛点来的它本质上是把你所有的上游API渠道统一接入到一个服务里对外只暴露一个固定的网关地址同时内置令牌管理、额度控制和调用日志。这篇文章完整记录了我用docker部署New-API的全过程从选型思路、参数规划到完整实操步骤和踩坑记录一次性说清楚适合刚接触API网关、想给团队或自建应用做统一AI接口层的朋友参考。1. 先搞清楚New-API到底解决什么问题1.1 多模型渠道的统一接入New-API这个项目是开源社区里One-API的一个衍生版本保留了原版的核心设计做了一堆针对个人和团队使用的增强。它最核心的能力就是把十几种上游渠道全部聚拢到一起包括OpenAI官方接口、Azure OpenAI、Anthropic Claude、Google Gemini以及国内主流的通义千问、DeepSeek、智谱、百度千帆等等。这些渠道不再是散落在各个应用里的单独账户而是统一挂在New-API里面每个渠道作为一份独立配置单独管理。我这里用一个生活类比说明它的价值就好比你家里攒了一大堆充电器有Type-C的、有Lightning的、有各种快充协议直接给手机充电时每个设备都得带对应的线非常痛苦。New-API相当于一个智能充电坞你只需要把手机插到这个充电坞上它自己会判断该走哪根线、用哪个协议。对下游应用而言它们永远只对着New-API这一个IP和一个端口说话根本不需要关心上游到底是哪个服务商。这种统一接入带来的好处不只是管理方便。很多渠道有免费额度、有阶梯计价不同渠道对同一个模型的价格可能差好几倍。你在New-API里可以给每个渠道设置权重让系统自动按比例分发请求——简单说就是可以用便宜的渠道承担大部分流量贵的渠道作为兜底整体成本能明显降下来。1.2 令牌体系与额度控制New-API的第二个核心能力是令牌Token管理。这里说的令牌不是上游渠道的API Key而是New-API自己签发的访问凭证。你可以在系统里为每一个下游应用创建独立的令牌每个令牌可以单独绑定某个模型、单独设置总额度上限、单独设置每秒并发数甚至单独定义这个令牌可以使用哪些渠道。这个设计在真实场景里太实用了。我见过不少团队把公司唯一的API Key直接写进业务代码里一旦Key泄露或者被某个同事滥用整个账户都被上游封掉。有了令牌机制之后每个应用、每个项目、每个环境都用独立的令牌某个令牌出了问题直接吊销完全不影响其他业务。更狠的是你还可以给令牌设置额度比如这个令牌最多只能花100块钱超了之后系统自动停止服务再也不怕后台跑了个死循环把钱烧光。1.3 为什么一定要用Docker部署New-API是Go后端加React前端打包在一起的单体项目理论上直接下载二进制文件也能跑。但我个人强烈建议用Docker部署原因有几个层面第一是环境隔离。这个项目依赖运行时环境、系统库、配置文件直接装在宿主机上容易和系统里其他软件打架尤其是服务器上还跑着MySQL、Nginx、其他业务程序的时候。Docker容器相当于一个独立的小房间项目需要的环境和宿主机的其他东西完全隔离互不干扰。第二是部署和升级极其简单。升级就是换一个镜像重新启动容器回滚就是切换到旧镜像整个过程在几秒钟内完成不需要关心各种依赖包冲突。这一点在实际运维中价值非常大我发现很多人部署完服务之后基本不动了不是因为不想升级而是怕升级出一堆环境问题。第三是数据持久化有保障。New-API容器内部默认把所有数据写在/data目录下包括SQLite数据库文件、日志文件。我们用Docker的volume机制把这个目录映射到宿主机上就算容器被删掉、重建、迁移到别的机器数据都还在。第四是资源可控。通过Docker的启动参数可以限制容器最大内存使用量、设置日志文件大小上限这些是裸机部署很难做到的精细化管理直接关系到服务器的稳定运行。2. 部署前的关键准备2.1 镜像选型与获取方式New-API的官方Docker镜像发布在Docker Hub项目仓库的镜像名为calciumion/new-api我们会用到的标签是latest。如果你所在的网络环境拉取Docker Hub镜像速度很慢建议先配置国内镜像加速器这个操作是在Docker引擎层面做的。在Linux上配置文件位于/etc/docker/daemon.json如果文件不存在就创建它写入如下内容{ registry-mirrors: [ https://docker.m.daocloud.io ] }配置好之后重启Docker服务生效执行systemctl restart docker或者service docker restart。配置完可以用docker info命令检查Registry Mirrors是否生效。这一步虽然简单但对部署体验影响很大如果不配置加速器拉取镜像可能会卡到怀疑人生。镜像选型上还有一个细节New-API项目针对Docker额外提供了一些环境变量开关这些功能依赖镜像内的配置所以尽量不要自己用源码去构建镜像直接用官方发布版本最省心。你真要自己做镜像的话至少得熟悉它前端的构建参数这属于不必要的折腾。2.2 端口与存储规划New-API容器内部默认监听3000端口这个端口主要用途是提供Web管理界面和API网关入口。部署时我们需要把这个容器端口映射到宿主机的某个端口上。这里有一个容易忽略的点容器内端口和宿主机端口是两回事。容器内端口是固定的3000但宿主机端口你可以随便选比如你不想暴露默认端口以免被扫描可以映射到8080、9527或者其他高位端口。映射命令的核心写法是-p 宿主机端口:容器端口也就是-p 8080:3000。存储方面容器内的数据都写在/data目录下我们必须把这个目录映射到宿主机上的一个固定位置。我的习惯是在宿主机上建一个专门的目录比如/opt/new-api/data然后用卷的方式挂载。这样做的直接好处是未来容器出问题数据依然安安稳稳地放在宿主机上换一个容器接着用。如果你的服务器正在跑其他Docker容器要注意一下端口冲突问题。可以用netstat -tlnp或ss -tlnp检查端口占用情况确认3000端口没被别的进程占住再启动New-API。2.3 数据库方案SQLite还是MySQLNew-API支持SQLite和MySQL两种数据存储方式。这一步的选型决定了你后续的配置复杂度我的建议是基于使用规模来判断如果你是个人使用、或者团队规模在十几个人以内、对并发要求不高直接用SQLite。它的好处是零配置容器启动之后自动创建数据库文件备份也简单直接拷贝对应目录下的文件就行。如果你们团队用户量较多、请求量很大、需要和现有MySQL体系统一管理那就用MySQL。配置上需要额外指定SQL_DSN环境变量同时要保证New-API容器能连接到MySQL服务。SQLite模式下数据库文件会出现在我们挂载的宿主机目录下文件名是one-api.db。这个文件的备份就是你的全部数据备份包括用户、令牌、渠道、日志别无其他。MySQL模式需要你提前建好数据库空白库然后通过环境变量告诉New-API怎么连接。一条典型的连接串长这样root:yourpasswordtcp(127.0.0.1:3306)/new-api?charsetutf8mb4parseTimeTruelocLocal其中127.0.0.1是MySQL地址如果你把MySQL也部署在Docker里这个地址就要改成MySQL容器的服务名或IP并且两者要在同一个Docker网络下。3. 完整部署实操3.1 快速跑通一条Docker命令我建议第一次部署时先用最简单的Docker命令快速跑通服务确认镜像拉取、端口访问、数据卷都正常再切换到docker compose编排做正式部署。这就像装新手机先开机看看能不能亮屏再决定要不要贴膜换壳。在宿主机上执行docker run -d --restart always --name new-api \ -p 3000:3000 \ -v /opt/new-api/data:/data \ calciumion/new-api:latest这条命令里的每个参数我这样解释-d表示后台运行--name给容器起名叫new-api--restart always让容器异常退出后自动重启理解为开机自启和故障自动恢复-p 3000:3000做端口映射-v /opt/new-api/data:/data把宿主机目录挂载为容器内的数据目录最后的calciumion/new-api:latest是要拉取的镜像。执行完之后用docker ps查看容器状态正常情况下STATUS列应该是Up状态。再用docker logs new-api查看日志如果看到类似one-api service started at port 3000之类的输出说明服务已经启动成功。然后浏览器打开http://你的服务器IP:3000就能看到New-API的登录页面。默认管理员账号是root默认密码是123456登录之后系统会提示你立即修改密码这个在后面初始化配置部分细说。3.2 正式部署用docker compose编排快速跑通验证完成之后我强烈建议你切换到docker compose方式接管这个容器。compose的核心价值是把容器的所有配置参数固化在一个docker-compose.yml文件里想改配置就改文件然后重新执行一遍整个部署的配方是版本化、可迁移的换一台服务器只要把这个文件复制过去就能原样拉起一套环境。下面是我实际使用的docker-compose.yml文件你可以直接复制修改version: 3.4 services: new-api: image: calciumion/new-api:latest container_name: new-api restart: always ports: - 3000:3000 volumes: - ./data:/data environment: - TZAsia/Shanghai - SESSION_SECRET请改成一段足够长的随机字符串 logging: driver: json-file options: max-size: 10m max-file: 3我把几个关键点单独拎出来讲version: 3.4是compose文件的语法版本这个版本已经够用了。restart: always保证开机自启和崩溃自动拉起。environment里我配置了两个变量TZAsia/Shanghai把容器时区设为北京时间不然日志和统计数据里的时间会差8个小时排查问题的时候很痛苦SESSION_SECRET用于会话加密你不设置它也能跑但设置一段随机值能避免会话安全问题。logging这一段是我后来主动加上去的作用是对容器日志做体积限制。如果放任不管Docker会把所有标准输出无限累积到宿主机的/var/lib/docker/containers目录下跑上几个月就是好几个G的垃圾文件。加上max-size: 10m和max-file: 3之后每个日志文件最大10MB最多保留3个文件超过的部分自动滚动覆盖硬盘空间安全得多。执行部署docker compose up -dcompose会自动完成拉取镜像、创建容器、启动服务的完整流程。3.3 加入MySQL的完整编排方案如果你想用MySQL作为持久化存储前面的compose文件就要扩展。这里有一个比较推荐的方案用一个MySQL容器专门给New-API使用两者放在同一个compose网络里通过服务名互相访问。完整的docker-compose.yml参考如下version: 3.4 services: mysql: image: mysql:8.0 container_name: new-api-mysql restart: always environment: - MYSQL_ROOT_PASSWORDyourpassword - MYSQL_DATABASEnew-api - TZAsia/Shanghai volumes: - ./mysql-data:/var/lib/mysql command: --default-authentication-pluginmysql_native_password --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci new-api: image: calciumion/new-api:latest container_name: new-api restart: always depends_on: - mysql ports: - 3000:3000 volumes: - ./data:/data environment: - TZAsia/Shanghai - SESSION_SECRET请改成一段足够长的随机字符串 - SQL_DSNroot:yourpasswordtcp(mysql:3306)/new-api?charsetutf8mb4parseTimeTruelocLocal这里需要注意的重点是SQL_DSN里mysql:3306中的mysql这是compose网络里MySQL服务的逻辑主机名。当New-API容器连接数据库时它会把mysql解析到MySQL容器的IP地址理解成在Docker网络内直接用容器名互相访问比写死IP地址要灵活因为容器重建后IP会变但容器名不会变。depends_on表示New-API容器要等MySQL容器启动后再启动但这不是一个强依赖检查只是启动顺序上的声明。如果MySQL初始化比较慢New-API启动时可能连接不上数据库报错退出。我实际遇到过几次这样的问题解决办法很简单New-API设置了restart: always它报错退出之后Docker会反复重启它等MySQL就绪之后总能连上。MySQL官方8.0镜像默认要求设置root密码如果你用MYSQL_ALLOW_EMPTY_PASSWORD允许空密码后面连接串也会更简单但生产环境不建议这么做。4. 常见问题与排查实录4.1 页面打不开、网络不通这类问题部署完之后最常遇到的问题就是容器启动了但浏览器访问不到页面。我总结了一个排查顺序基本能解决九成问题第一步确认宿主机端口有没有监听。执行ss -tlnp | grep 3000如果能看到监听结果说明映射生效了。第二步确认防火墙是否放行。这一步在云服务器上尤其容易被忽略。Linux系统firewalld或ufw会拦掉外部访问云平台的安全组规则也需要显式放行对应端口。我的排查习惯是先在服务器本机用curl http://127.0.0.1:3000测试本机通而外部访问不通基本可以确定是防火墙或安全组的问题。第三步确认容器日志有没有异常。执行docker logs new-api查看最近的输出如果日志停在启动阶段没有监听端口的信息说明应用内部启动失败接着往下排查。4.2 容器反复重启、启动即退出容器日志里如果频繁出现重启记录常见原因就是启动时外部依赖没就绪。比如你配置了MySQL连接但MySQL容器还没完成初始化New-API连不上数据库就会报错退出。在restart: always机制下Docker会不断尝试重启容器直到依赖服务就绪。还有个比较隐蔽的问题和挂载目录权限有关。如果你挂载的宿主机目录权限不对容器内的进程无法写入数据库文件也会导致启动异常。我遇到过用sudo docker compose创建容器后宿主机对应目录归属变成了root后续改成普通用户运行compose时权限就对不上了。最直接的办法是把宿主机的数据目录授权给当前用户执行chown -R 当前用户 /opt/new-api/data或者直接把目录权限放开为chmod -R 777 /opt/new-api/data虽然简单粗暴但确实能解决大部分权限类问题。容器退出后想查看更多细节用docker logs --tail 100 new-api查看最后100条日志重点找error、panic、fatal等关键字。4.3 数据卷挂载与数据丢失问题很多人在使用过程中会踩一个坑容器升级时没有妥善处理数据卷导致数据丢失。实际上只要卷挂载正确升级不会丢任何数据所谓的丢失通常是把新容器直接跑起来但没有指定原来的数据卷系统就自动创建了一个全新的/data目录看起来像数据丢了但旧数据还躺在原来的宿主机目录里。所以这里要反复强调每次重建容器时务必保证-v或compose文件里的volumes路径和之前一模一样。我的做法是在数据目录里放一个说明文件记录这个目录是由哪个项目的哪个容器挂载的避免时间久了忘记目录归属。针对数据安全我还有一个额外的建议把日志文件和数据库文件分开存放。New-API容器默认在一个数据目录里包含所有东西如果日志膨胀得厉害可以定期清理。SQLite文件则是核心资产可以每天凌晨用crontab做个压缩备份把one-api.db拷贝到另一个目录并保留近7天版本即可。4.4 Docker环境本身的常见坑很多朋友在Windows环境下使用Docker Desktop部署时会遇到一些配置问题比如提示虚拟化未启用、Docker服务启动失败等。这些问题绝大多数是Windows虚拟化功能没开或者Windows版本和Docker Desktop版本不兼容。Windows上部署Docker容器时我建议把Docker Desktop的资源配置稍微调高一点尤其是内存分配给到4G以上因为New-API容器本身很轻量但加上MySQL容器、日志采集这些资源不够会很卡。Linux环境下最常见的坑是Docker权限问题普通用户执行docker ps会报permission denied。解决办法是把用户加入docker组sudo usermod -aG docker $USER执行完之后重新登录终端才能生效。这个操作会让当前用户拥有管理Docker的权限安全性上要谨慎但作为管理员的常用操作你自己权衡即可。还有一个新手容易遇到的是容器网络问题。如果你在宿主机上同时跑了多个容器相互之间需要通信记住一个关键点它们必须处于同一个Docker网络。默认的bridge网络确实能让容器互通但建议自己创建一个专用网络执行docker network create new-api-net然后在compose文件里用networks字段指定网络名称网络管理更清晰。5. 部署后的初始化配置与日常维护5.1 首次登录与安全加固容器跑起来页面能访问部署只算完成了一半。第一次用root加123456登录之后我建议做这几件事第一立即修改管理员密码。在系统设置里找到通用设置或用户管理把root账号的密码改成强密码建议至少12位以上混合大小写和特殊字符。第二开启管理员二次验证。New-API支持二次验证功能如果你把它用于生产环境这步绝对不能省。逻辑上就相当于给管理员账号上了把独立的锁即使密码泄露没有二次验证码也进不来。第三修改站点名称和公告。这些虽然不是安全配置但会在登录页和用户界面上展示花两分钟设置一下整个管理系统会显得专业得多。第四如果能改容器映射端口建议把宿主机端口从默认的3000改成一个不常用的高位端口减小被扫描工具探测到的概率。这算是最基础的加固措施。5.2 添加渠道与创建令牌登录之后先别急着使用添加一个渠道测试整体链路是否通畅。在左侧菜单找到渠道页面点击添加渠道这里以接入DeepSeek为例类型选择DeepSeek名称随便填建议填环境标识API地址填https://api.deepseek.com密钥填你在对应服务商申请的API Key模型列表填deepseek-chat等可用模型名称填完之后保存点击测试按钮如果返回成功说明渠道配置正确。用同样的方式把所有用到的上游服务商全部添加进来之后他们的Key信息就不再散落在各处了。接着创建令牌。在令牌页面点击添加令牌设置令牌名称选择可用模型范围设置额度上限。这里分享一个我的习惯给每个下游应用创建独立令牌并且令牌名称里带上应用名和环境名例如prod-website-app、dev-chatbot-test。后续如果想限制某个应用的调用量直接编辑对应令牌即可不需要动整个系统。下游应用接入时把原本直连的API地址改成http://你的New-API服务器IP:3000API Key填刚创建的令牌值模型的调用路径就被New-API接管了。别忘了在应用端测试一下真实调用是否正常遇到401或者404就检查一下令牌是否有效、模型是否在这个令牌的授权范围内。5.3 用量监控、日志查看与日常备份New-API自带比较完整的日志和数据统计功能。在日志页面能看到每一次调用的完整记录包括时间、用户、令牌、渠道、模型、Token消耗数和计费金额。对想控制成本的团队来说这个页面就是记账本能精确看到每天哪个应用烧了多少Token。日常维护主要围绕三件事备份SQLite数据。直接用crontab定时脚本把挂载目录下的one-api.db文件复制到另一个目录加上时间戳保留近7天。我的备份脚本大致长这样#!/bin/bash DATE$(date %Y%m%d_%H%M) mkdir -p /backup/new-api cp /opt/new-api/data/one-api.db /backup/new-api/one-api_$DATE.db find /backup/new-api -name *.db -mtime 7 -delete写入crontab让它每天凌晨执行一次。如果使用MySQL模式正常备份MySQL数据库即可逻辑上是一致的。日志清理。用前面compose里配置的日志限制可以自动滚动清理如果你没有配置Docker的日志文件会不断膨胀需要定期清理删除容器日志文件这种操作千万别直接删文件正确做法是docker logs --tail 0配合日志轮转配置。定时升级。New-API社区更新比较频繁每次升级前先备份数据然后执行docker compose pull拉取最新镜像再docker compose up -d重建容器。如果升级后遇到问题用旧镜像的tag重新启动即可一分钟回滚。我个人的经验是每次升级前看一眼release notes确认有没有破坏性变更其余情况直接升。5.4 通过反向代理绑定域名和HTTPS如果你希望New-API通过一个正式的域名对外提供服务并且用HTTPS加密流量那就在前面加一层反向代理。我比较推荐Caddy因为它能自动获取和续期HTTPS证书配置非常简单。在宿主机上用Docker跑一个Caddy容器通过宿主机端口把流量转给New-API容器。简化理解的话Caddy作为门卫负责处理域名验证和HTTP转HTTPS再把请求转发给内网里的New-API。一份最小的Caddy配置如下api.example.com { reverse_proxy new-api:3000 }Caddy会自动申请并续期证书转发的时候把真实客户端IP等信息也带上。如果你不习惯Caddy用Nginx也是一样的思路配置里加入WebSocket支持的头信息即可因为New-API的部分功能需要WebSocket长连接。我个人的建议是只要对外提供服务一律套一层HTTPS反向代理不要把裸的HTTP端口直接暴露在公网上。这条路我已经在多个项目里验证过了能解决绝大多数的安全告警问题。写到这里我把自己部署New-API的完整思路和细节都梳理了一遍。最后再分享一个实际体会这套系统的稳定性其实不太取决于容器本身而取决于你对数据卷和升级流程的纪律性。我见过太多人部署完就扔一边不管几个月后想升级时发现数据目录都不知道在哪了。你只要坚持把数据挂在固定目录、每次升级前做备份、升级后第一时间测试渠道联通性它就能安安稳稳跑很长时间。部署完成后再回头看看那些被统一管理的API Key你会觉得当初花半小时搭建这套网关确实是值了。
返回列表