1. 为什么我要把 OpenCode 塞进 Docker Compose
OpenCode 是一款开源的 AI 编程助手,能做的事和你在用的商业补全插件差不多:代码补全、对话式改代码、解释一段看不懂的遗留逻辑、批量生成单元测试。它适合谁?适合那些不想把公司代码往第三方云端送、又希望成本可控的团队和个人开发者。你可以把它理解成「自己家里搭一个代码助手」,模型跑在你自己的机器上,数据不出内网。
但真动手部署时,麻烦往往不在 OpenCode 本身,而在「模型从哪来」。本地跑 vLLM 要显卡、要下几十 GB 权重、要调显存参数;直接接商业 API 又得在每台机器上散落一堆 Key,换个人就得重新配一遍。我试过把两者混着用,结果配置文件里三套 base_url、四把 Key,维护起来头大。
这篇的做法是:OpenCode 用 Docker Compose 编排,模型通道统一走 TaoToken 的 API 网关。TaoToken 在这里的角色是「统一 Key / API 通道」——你只需要在 config.toml 里填一个 base_url 和一把 Key,背后接的是本地 vLLM 还是别的模型,对 OpenCode 来说都是同一个 OpenAI 兼容接口。这样本地推理和远端模型可以随时切换,而不用改 OpenCode 的代码。
下面从零走一遍:写 docker-compose.yml、写 config.toml、起服务、发一个真实请求验证连通性,最后把几个我踩过的坑列出来。
2. 前置准备:TaoToken Key 与目录结构
在写编排文件之前,先把两件事办了。
第一件是拿 TaoToken 的 API Key。访问 https://taotoken.net/api-keys ,登录后在控制台创建一把 Key,复制出来形如sk-xxxx的字符串。这把 Key 就是 OpenCode 访问模型通道的凭证,后面写进 config.toml。如果你还没注册,从 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 进官网走一遍即可,整个过程不涉及任何网络工具。
第二件是规划目录。我习惯把配置和数据分开,方便备份和迁移:
mkdir -p ~/opencode-deploy/{config,data,models} cd ~/opencode-deploy最终目录长这样:
opencode-deploy/ ├── docker-compose.yml ├── config/ │ └── config.toml ├── data/ # OpenCode 会话与索引数据 └── models/ # 本地 vLLM 权重(可选)注意:
data/目录会存会话历史和代码索引,别放在容器里,否则docker compose down一执行就没了。挂载出来最省心。
关于硬件,如果你打算本地跑 vLLM,7B 级别的代码模型大概需要 16GB 以上显存;如果只走 TaoToken 通道接远端模型,那对本地显卡没要求,一台 4 核 8GB 的机器就能把 OpenCode 本体跑起来。这也是统一通道的好处之一:算力可以后置。
3. 可复制的 docker-compose.yml 与 config.toml
3.1 docker-compose.yml 骨架
这份编排包含两个服务:opencode本体,以及可选的vllm本地推理后端。如果你只用 TaoToken 通道,把 vllm 那段注释掉即可。
version: "3.8" services: opencode: image: ghcr.io/opencode-ai/opencode:latest container_name: opencode ports: - "8000:8000" # 后端 API - "3000:3000" # Web 界面 volumes: - ./config:/root/.config/opencode - ./data:/root/.local/share/opencode environment: - OPENCODE_CONFIG=/root/.config/opencode/config.toml depends_on: - vllm restart: unless-stopped vllm: image: vllm/vllm-openai:latest container_name: vllm ports: - "8080:8080" volumes: - ./models:/models command: > --model /models/Qwen2.5-Coder-7B-Instruct --served-model-name qwen-coder --port 8080 --max-model-len 32768 --gpu-memory-utilization 0.9 deploy: resources: reservations: devices: - driver: nvidia count: 1 capabilities: [gpu] restart: unless-stopped几个参数值得说明。--served-model-name qwen-coder是给模型起的别名,config.toml 里引用这个名字就行,不用写一长串路径。--max-model-len 32768控制上下文长度,代码补全场景 32K 够用,调太大会吃显存。--gpu-memory-utilization 0.9表示允许 vLLM 占用 90% 显存,留一点给系统。
3.2 config.toml 骨架
OpenCode 的模型配置写在 config.toml 里。下面这份同时配了「走 TaoToken 通道」和「走本地 vLLM」两个 provider,你可以按需保留。
# ~/opencode-deploy/config/config.toml [providers.taotoken] type = "openai" base_url = "https://taotoken.net/api/v1" api_key = "sk-你的TaoToken密钥" models = ["qwen-coder", "gpt-4o-mini"] [providers.local] type = "openai" base_url = "http://vllm:8080/v1" api_key = "not-needed" models = ["qwen-coder"] [default] provider = "taotoken" model = "qwen-coder" max_tokens = 2048 temperature = 0.2这里的关键点是base_url。TaoToken 提供的是 OpenAI 兼容接口,所以type填openai即可,OpenCode 会用标准的/chat/completions协议去请求。api_key填你第 2 步拿到的那把。temperature = 0.2是我对代码场景的偏好,低温度让补全更稳定,不会天马行空。
提示:config.toml 里出现明文 Key,记得给文件设权限
chmod 600 config/config.toml,别提交到 Git。
4. 启动服务与连通性验证
4.1 拉起容器
cd ~/opencode-deploy docker compose up -d第一次执行会拉镜像,vLLM 镜像比较大,耐心等。起来之后看状态:
docker compose ps正常的话两个服务都是running。如果 vllm 一直重启,多半是显存不够或权重路径不对,先看日志:
docker compose logs -f vllm4.2 验证 TaoToken 通道
在 OpenCode 之前,先用 curl 单独验证通道是否通。这一步能帮你把「通道问题」和「OpenCode 配置问题」分开定位:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的TaoToken密钥" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen-coder", "messages": [{"role": "user", "content": "用 Python 写一个快速排序"}], "max_tokens": 256 }'返回里如果能看到choices[0].message.content里有代码,说明通道没问题。如果返回 401,检查 Key 是否复制完整;返回 404,检查 base_url 是不是写成了https://taotoken.net/api(少了/v1)。
4.3 验证 OpenCode 本体
OpenCode 起来后,后端健康检查:
curl http://localhost:8000/health返回{"status":"ok"}之类即可。然后打开浏览器访问http://localhost:3000,进入 Web 界面,在对话框里输入一句「解释一下这段代码的作用」并贴一段代码,看是否有流式返回。如果界面能出字,说明 OpenCode → config.toml → TaoToken 整条链路打通了。
想更直接一点,也可以走 API:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "qwen-coder", "messages": [{"role": "user", "content": "写一个 Dockerfile 多阶段构建示例"}] }'4.4 切换本地 vLLM 后端
如果你本地起了 vLLM,把 config.toml 的[default]段改成:
[default] provider = "local" model = "qwen-coder"然后docker compose restart opencode。这样请求就走内网http://vllm:8080/v1,不经过外部通道。两种模式随时切,OpenCode 侧不用改任何代码,这就是统一配置层的好处。
5. 本篇常见错排查
报错一:CUDA out of memory。vLLM 启动时显存不够。先把--gpu-memory-utilization降到 0.8,再把--max-model-len从 32768 降到 16384。还不行就换量化版本权重,AWQ 或 GPTQ 能省一半显存。
报错二:Connection refused连不上 vllm。在 compose 网络里,服务之间要用服务名互访,也就是http://vllm:8080,不是http://localhost:8080。localhost 在容器里指向容器自己,当然连不上。这个坑我第一次部署时卡了半小时。
报错三:TaoToken 返回 401 Unauthorized。九成是 Key 复制时带了空格或换行。用echo -n "sk-xxx" | wc -c数一下长度,或者直接在 config.toml 里重新粘贴一遍。另外确认请求头是Authorization: Bearer sk-xxx,Bearer 后面有一个空格。
报错四:OpenCode 界面能开但对话无响应。先看docker compose logs -f opencode,如果报model not found,说明 config.toml 里[default]的 model 名和 provider 的 models 列表对不上。model 名要和--served-model-name或 TaoToken 侧支持的模型名完全一致,大小写敏感。
报错五:改了 config.toml 不生效。OpenCode 只在启动时读配置,改完必须docker compose restart opencode。别指望热重载。
报错六:端口被占用。3000 或 8000 被别的服务占了,改 compose 里的端口映射,比如"13000:3000",然后访问http://localhost:13000。
6. 后续怎么用:把通道固定下来
部署跑通只是第一步。真正让这套东西在团队里活起来,关键是别让每个人各自去配 Key。我的做法是把 TaoToken 的 Key 放在 config.toml 里统一管理,团队成员通过 OpenCode 的 Web 界面访问,不接触底层凭证。需要换模型或调额度时,只改一处配置,重启容器即可。
如果你后面要接长期编码任务或者 Agent 类的自动化流程,可以看看 Coding Plan 这类按周期计费的方案,比按 token 零散调用更可控:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。日常调试模型输出、对比不同模型效果,用模型对话页面就够了:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。接入细节和参数说明都在文档里:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
最后留一个实用技巧:把docker compose logs -f opencode挂在一个终端里别关,边用边看日志。OpenCode 请求失败时,日志里会打出实际请求的 base_url 和返回码,比在界面上猜快得多。这套编排我用了几个月,最常改的就是 config.toml 里的 model 字段,其余部分基本没动过。