
1. 为什么要在 Docker 里给 One API 接一条统一通道One API 是一个把多家模型服务聚合成统一 OpenAI 兼容接口的网关你在本地或服务器上用 Docker 跑起来之后前端工具、脚本、Agent 都只需要认一个 Base URL 和一把 Key。但真正落地时麻烦往往不在容器本身而在「上游渠道怎么填」。每个渠道都要单独配地址、单独配密钥、单独处理模型名映射渠道一多配置文件就开始失控。我这次的做法是One API 继续用 Docker Compose 部署但上游渠道统一走 TaoToken 这一条通道。TaoToken 是一个模型 API 聚合服务提供 OpenAI 兼容的接口地址你可以在它的控制台里生成 Key然后把同一个 Base URL 和 Key 填进 One API 的渠道配置。这样 One API 对外仍然是你自己的域名和令牌对内只维护一条上游模型 ID 的差异在 TaoToken 侧处理容器里的环境变量和渠道表都干净很多。这篇适合三类人一是已经在用 Docker 跑 One API、想简化上游渠道维护的人二是准备第一次用 Docker Compose 部署 One API、希望一步到位接好模型通道的人三是手上有多套工具Cline、Codex、Claude Code 之类想共用一个出口的人。下面从零开始给出可复制的docker-compose.yml、环境变量片段、渠道配置 JSON以及启动后用/v1/models验证连通性的完整动作。需要先明确一点One API 容器本身不负责「连外网模型」它只负责转发。真正决定能不能调通的是渠道里填的 Base URL 和 Key。所以本文的重点会放在「容器怎么起」和「渠道怎么填」这两件事上两者缺一不可。2. 前置准备TaoToken Key、模型 ID 与 Docker 环境在写 Compose 文件之前先把三样东西准备好后面配置会顺很多。第一样是 TaoToken 的 API Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册登录后进入控制台在 API Keys 页面创建一个新 Key。建议按用途命名比如one-api-docker方便以后区分。创建后立刻复制保存页面刷新后通常不再完整显示。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API Keys 页面是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。第二样是 Base URL 和模型 ID。TaoToken 的接口地址是https://taotoken.net/api注意这个地址后面不加 UTM 参数直接作为渠道的代理地址使用。模型 ID 建议先去模型对话页面确认一下当前可用的名称页面在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 选一个模型发一条消息看请求里用的 model 字段是什么把它记下来。One API 渠道里的「模型」列表要和这个名称对得上否则会出现「模型不存在」的报错。第三样是 Docker 和 Docker Compose 环境。确认版本docker --version docker compose version如果第二条报错说明你用的是旧版docker-compose带横杠本文命令统一用docker compose空格两者语法基本一致按你本机情况替换即可。另外确认 3000 端口没有被占用ss -tlnp | grep 3000有输出就换个端口比如映射成3001:3000。关于数据库One API 支持 SQLite 和 MySQL。单机测试用 SQLite 最省事不用额外起 MySQL 容器如果要多人用或者数据量大再上 MySQL。本文给两份 Compose一份纯 SQLite 的最小可用版一份带 MySQL 的完整版你按需选。还有一个容易忽略的点One API 的渠道配置存在数据库里不在环境变量里。也就是说docker-compose.yml只负责把容器跑起来渠道的 Base URL 和 Key 是启动后进 Web 后台填的。很多人以为改环境变量就能换上游结果重启容器发现没变化就是踩了这个坑。下面会分别讲清楚。3. 可复制的 docker-compose.yml 与环境变量配置先给最小可用版用 SQLite适合本地验证。services: one-api: image: justsong/one-api:latest container_name: one-api restart: always ports: - 3000:3000 volumes: - ./volumes/one-api/data:/data - ./volumes/one-api/logs:/app/logs environment: - TZAsia/Shanghai - SESSION_SECRETchange_me_to_a_random_string - SQL_DSN command: --log-dir /app/logs healthcheck: test: [CMD-SHELL, wget -q -O - http://localhost:3000/api/status | grep -o \success\:\\s*true] interval: 30s timeout: 10s retries: 3SQL_DSN留空时 One API 会自动用 SQLite数据落在/data目录也就是宿主机的./volumes/one-api/data。SESSION_SECRET一定要改随便生成一串openssl rand -hex 32把输出填进去。TZ设成Asia/Shanghai是为了日志时间对得上排查问题时不用心算时差。如果你要上 MySQL换成这份services: mysql: image: mysql:8.0 container_name: one-api-mysql restart: always environment: - MYSQL_ROOT_PASSWORDoneapi_root_pwd - MYSQL_DATABASEoneapi - TZAsia/Shanghai volumes: - ./volumes/mysql:/var/lib/mysql healthcheck: test: [CMD-SHELL, mysqladmin ping -h localhost -p$$MYSQL_ROOT_PASSWORD] interval: 10s timeout: 5s retries: 5 one-api: image: justsong/one-api:latest container_name: one-api restart: always ports: - 3000:3000 volumes: - ./volumes/one-api/data:/data - ./volumes/one-api/logs:/app/logs environment: - TZAsia/Shanghai - SESSION_SECRETchange_me_to_a_random_string - SQL_DSNroot:oneapi_root_pwdtcp(mysql:3306)/oneapi command: --log-dir /app/logs depends_on: mysql: condition: service_healthy healthcheck: test: [CMD-SHELL, wget -q -O - http://localhost:3000/api/status | grep -o \success\:\\s*true] interval: 30s timeout: 10s retries: 3注意SQL_DSN里的主机名是mysql也就是服务名不是localhost。容器之间通过 Compose 默认网络用服务名互访写成127.0.0.1会连不上。密码里的特殊字符如果包含或:需要做 URL 编码简单起见先用纯字母数字。启动mkdir -p volumes/one-api/data volumes/one-api/logs docker compose up -d docker compose logs -f one-api看到日志里出现监听 3000 端口、数据库初始化完成之类的信息就可以访问http://你的服务器IP:3000。首次进入用默认账号root/123456登录登录后第一件事是改密码。接下来是渠道配置。进后台「渠道」页面新建渠道类型选 OpenAI填入代理地址https://taotoken.net/api密钥你在 TaoToken 控制台创建的 Key模型填你在模型对话页面确认过的模型 ID多个用逗号分隔如果你习惯用配置文件方式管理One API 也支持通过环境变量预置渠道但更推荐在后台点因为改完即时生效不用重启容器。渠道建好后去「令牌」页面创建一个访问令牌这个令牌是给下游工具用的和上游 TaoToken 的 Key 是两回事别搞混。4. 启动后验证用 /v1/models 确认通道连通容器起来、渠道填好之后不要急着接下游工具先用最直接的方式验证一遍。第一步确认 One API 自身活着curl -s http://localhost:3000/api/status返回里应该有success:true。如果没有看容器日志多半是数据库连接或端口问题。第二步用你在 One API 里创建的令牌调/v1/modelscurl -s http://localhost:3000/v1/models \ -H Authorization: Bearer sk-你的OneAPI令牌这个接口会返回当前渠道里配置的模型列表。如果返回了模型 ID说明 One API 到 TaoToken 这条链路是通的。如果返回空列表或者报错往下看第五节。第三步发一条真实的对话请求验证端到端curl -s http://localhost:3000/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的OneAPI令牌 \ -d { model: 你配置的模型ID, messages: [{role: user, content: 只回复两个字通了}] }返回的 JSON 里choices[0].message.content应该有内容。到这一步Docker 里的 One API 加 TaoToken 通道就算完整跑通了。如果你用的是 Cline、Codex 或 Claude Code 这类工具配置方式是把 Base URL 指向http://你的服务器:3000/v1Key 填 One API 的令牌Model ID 填渠道里配置的模型名。这三件套缺一不可Base URL 决定请求打到哪Key 决定身份Model ID 决定用哪个模型。少填一个就会出现 401 或者模型不存在的报错。关于 Coding Plan如果你的用途是长期编码、跑 Agent 任务可以了解一下 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它面向的是持续性的编码场景和按量调用是两种用法按自己的频率选。验证通过后建议把这条 curl 命令存成一个脚本以后换 Key 或者换服务器时直接跑一遍比进后台点来点去快得多。5. 常见报错排查401、local proxy failed 与模型不存在这一节按真实遇到的报错来排每条都给定位思路。401 Unauthorized。分两种。一种是调 One API 时报 401说明你用的 One API 令牌不对检查Authorization: Bearer后面的字符串是不是「令牌」页面创建的那个注意别把上游 TaoToken 的 Key 填到这里。另一种是 One API 日志里报上游 401说明渠道里填的 TaoToken Key 有问题可能是复制时少了字符或者 Key 被删了。去 API Keys 页面重新生成一个更新渠道密钥。local proxy failed / dial tcp 超时。这个报错说明 One API 容器访问不到上游地址。先确认容器内能不能解析和访问外网docker compose exec one-api wget -q -O - https://taotoken.net/api如果这条也失败是容器网络问题检查宿主机 DNS 和防火墙。如果这条成功但渠道还是报错检查代理地址是不是写成了带路径的完整地址正确写法是https://taotoken.net/api不要多加/v1One API 会自己拼路径。reading choices: unexpected end of JSON input。这个通常出现在流式响应场景上游返回了非 JSON 内容比如 HTML 错误页。原因可能是模型 ID 写错上游返回了 404 页面。去模型对话页面确认模型名注意大小写和连字符。也可能是渠道类型选错了TaoToken 走 OpenAI 兼容格式类型要选 OpenAI不要选别的。OAuth 相关报错。如果你在配 Claude Code 或 Codex 时看到 OAuth 字样说明工具在走它自己的登录流程而不是用你填的 Key。这类工具要显式指定 API Key 模式把 Base URL 和 Key 填进对应的配置文件。Codex 的配置在~/.codex/auth.jsonClaude Code 用环境变量ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY。填完之后重启工具让它重新读取配置。模型列表为空。/v1/models返回空数组说明渠道没有启用或者模型没填。进后台看渠道状态是不是「已启用」模型字段是不是空的。One API 的模型字段支持通配但建议显式列出避免下游工具请求到不存在的模型。容器反复重启。看docker compose logs one-api如果是数据库连接失败检查SQL_DSN里的主机名和密码如果是端口占用换映射端口。健康检查失败也会导致重启可以先把 healthcheck 注释掉确认服务本身能起来再排查健康检查命令。排查时有个通用技巧把 One API 的日志级别调高或者直接看./volumes/one-api/logs下的日志文件里面会记录每次请求的上游地址和返回码比在界面上看错误信息详细得多。6. 把统一通道固化下来后续维护与接入入口跑通之后日常维护其实就几件事。换 Key 的时候只改 One API 渠道里的密钥下游工具完全不用动这是统一通道最大的好处。加新模型的时候先在模型对话页面确认模型 ID再在渠道的模型列表里追加下游工具按需切换。扩容的时候One API 支持多渠道负载你可以建多个指向同一 Base URL 的渠道用不同的 Key 分摊One API 会自动轮询。如果你要把这套配置交给团队其他人建议把docker-compose.yml和一份渠道配置说明放进仓库说明里写清楚 Base URL、模型 ID 的获取位置以及验证用的 curl 命令。这样别人拿到就能复现不用再来问你。接入相关的文档入口在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各语言的调用示例和参数说明。API Keys 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 控制台总入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。模型对话验证在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。长期编码场景看 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个我自己的习惯每次改完渠道配置先跑一遍第 4 节那三条 curl确认/api/status、/v1/models、/v1/chat/completions都正常再去动下游工具。这样出问题时能快速判断是 One API 这一层还是工具那一层省掉很多来回试的时间。