1. 为什么要在 Docker 里跑 Ollama,再挂一层统一通道

如果你手里有一台闲置的 Linux 服务器或者一台内存够大的开发机,想跑本地大模型,Ollama 是目前门槛最低的选择之一。它把模型权重下载、量化格式、推理进程管理都封装成了一条 ollama run 命令,你不用去折腾 llama.cpp 的编译参数,也不用管 GGUF 文件放哪。而 Docker 部署 Ollama 的好处是环境隔离干净,升级镜像就能换版本,数据卷挂出来模型不会丢。

但只跑 Ollama 会碰到一个现实问题:Ollama 原生只监听 11434,没有鉴权,谁扫到你的端口都能调;而且它的接口格式和 OpenAI 的 /v1/chat/completions 不完全一致,很多现成的客户端、IDE 插件、Agent 框架默认只认 OpenAI 协议。这时候就需要一个统一接入层,把本地 Ollama 和云端模型都收敛到同一个 Key、同一个 Base URL 下。TaoToken 在这里扮演的就是这个统一通道的角色:你可以在本地模型和远端模型之间用同一套调用方式切换,客户端配置只写一份。

这篇面向的是已经有一台 Docker 机器、想从零把 Ollama 跑起来、并且希望后续多工具调用不用反复改配置的人。下面从 docker-compose 开始,到模型拉取、TaoToken 接入、curl 验证、报错排查,一步步给可复制的命令。

2. TaoToken 前置准备:拿 Key 和确认接入地址

在写配置之前,先把统一通道这一侧准备好。TaoToken 的官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,注册登录后进入控制台。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在里面创建 API Key。

创建 Key 的页面在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,点新建,复制出来的字符串形如 sk- 开头的一长串。这个 Key 只显示一次,先存到密码管理器或者环境变量文件里。

接入地址这一侧要记两个:

  • API 根地址:https://taotoken.net/api ,注意这个地址后面不加 UTM 参数,直接作为 Base URL 使用。
  • 对话补全路径:在根地址后拼 /v1/chat/completions,也就是 https://taotoken.net/api/v1/chat/completions。

如果你后面要用 Claude Code 这类编码工具,Anthropic 兼容入口在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 里有说明,文档页会把不同协议的路径列清楚。想先在线试模型效果,可以直接开模型对话页 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite ,不用写代码就能验证 Key 是否可用。

注意:Key 不要写进会提交到 Git 的 compose 文件里。用 .env 文件加 .gitignore,或者用 Docker 的 secrets,后面配置章节会给具体写法。

3. 可复制配置:docker-compose 跑 Ollama + 环境变量

先建目录,把数据卷和配置文件分开:

mkdir -p /opt/ollama-stack/data
cd /opt/ollama-stack

新建 .env 文件,把 TaoToken 的 Key 放进去,这个文件不要提交:

# /opt/ollama-stack/.env
TAOTOKEN_API_KEY=sk-你的真实key
TAOTOKEN_BASE_URL=https://taotoken.net/api

然后是 docker-compose.yaml。这里 Ollama 只映射到本机回环,避免直接暴露到公网:

# /opt/ollama-stack/docker-compose.yaml
version: "3.8"

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    ports:
      - "127.0.0.1:11434:11434"
    volumes:
      - ./data:/root/.ollama
    environment:
      - OLLAMA_KEEP_ALIVE=24h
      - OLLAMA_HOST=0.0.0.0:11434
    restart: always
    healthcheck:
      test: ["CMD", "ollama", "list"]
      interval: 30s
      timeout: 10s
      retries: 3

几个参数说明一下。OLLAMA_KEEP_ALIVE=24h 让模型加载后常驻内存,避免每次请求都重新加载权重,CPU 机器上这个差别很明显。OLLAMA_HOST=0.0.0.0:11434 是容器内监听地址,配合端口映射才能被外部访问。healthcheck 用 ollama list 判断服务是否就绪,后面做依赖编排时有用。

启动:

cd /opt/ollama-stack
docker compose up -d
docker compose ps

看到 ollama 状态是 Up (healthy) 就说明容器起来了。验证本机端口:

curl http://127.0.0.1:11434

返回 Ollama is running 即正常。

如果你的机器有 NVIDIA 显卡,需要在 compose 里加 GPU 段,参考官方镜像说明:

    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

同时宿主机要装好 NVIDIA Container Toolkit,否则容器看不到显卡。

4. 拉取本地模型并验证推理

容器起来后,模型还没下载。Ollama 的模型库在 https://ollama.com/library ,选一个适合你硬件的。纯 CPU、内存 32G 以上,建议从 7B 级别的中文友好模型开始,比如 qwen2:7b。

进容器执行拉取:

docker exec -it ollama ollama pull qwen2:7b

拉取完成后确认:

docker exec -it ollama ollama list

输出里能看到 qwen2:7b 和它的体积。再确认运行状态:

docker exec -it ollama ollama ps

如果模型没在内存里,ps 可能是空的,第一次调用后才会加载。

直接用命令行对话测试:

docker exec -it ollama ollama run qwen2:7b "用一句话解释什么是容器"

能返回中文回答就说明本地推理链路通了。常用命令整理成表:

命令作用
ollama pull qwen2:7b下载指定模型
ollama list查看本地已下载模型
ollama ps查看当前加载在内存的模型
ollama rm qwen2:7b删除本地模型
ollama run qwen2:7b交互式对话
ollama -h查看全部子命令

模型选型上,实测下来 7B 是 CPU 推理的可用下限,再小的 3B 级别在中文多轮对话里容易跑偏;14B 以上纯 CPU 会明显变慢,有显卡再考虑。中文场景优先选 qwen 系列和 glm 系列,llama 系列对中文的支持相对弱一些。

5. 接入 TaoToken 统一通道:settings.json 骨架与 curl 验证

本地 Ollama 跑通后,接下来把它和 TaoToken 统一通道串起来。思路是:客户端只认一个 Base URL 和一个 Key,本地模型和远端模型通过模型名区分。TaoToken 的 API 根地址是 https://taotoken.net/api,对话补全走 /v1/chat/completions。

先给一个通用的 settings.json 骨架,很多工具(比如各类 IDE 插件、Agent 框架)都吃这种结构:

{
  "apiBase": "https://taotoken.net/api",
  "apiKey": "sk-你的真实key",
  "defaultModel": "qwen2:7b",
  "models": {
    "local-qwen": {
      "provider": "openai-compatible",
      "baseUrl": "http://127.0.0.1:11434/v1",
      "model": "qwen2:7b"
    },
    "unified": {
      "provider": "openai-compatible",
      "baseUrl": "https://taotoken.net/api",
      "model": "qwen2:7b"
    }
  }
}

这里 local-qwen 直连本地 Ollama 的 OpenAI 兼容端点(Ollama 从较新版本起提供 /v1 兼容层),unified 走 TaoToken。实际使用时把 apiKey 换成环境变量注入,不要硬编码。

先验证本地 Ollama 的 OpenAI 兼容接口:

curl http://127.0.0.1:11434/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen2:7b",
    "messages": [
      {"role": "user", "content": "你好,做个自我介绍"}
    ]
  }'

返回 JSON 里有 choices[0].message.content 就说明本地兼容层正常。

再验证 TaoToken 统一通道:

curl https://taotoken.net/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TAOTOKEN_API_KEY" \
  -d '{
    "model": "qwen2:7b",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Hello!"}
    ]
  }'

如果 TaoToken 侧配置了对应模型的路由,会返回标准 OpenAI 格式响应。两个 curl 都通,说明本地模型和统一通道各自可用,客户端只需要在 settings.json 里切换 baseUrl 和 model 就能在两者之间切换。

对于长期编码和 Agent 场景,如果调用量大、需要更稳定的配额和并发,可以看 Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,里面有针对编码工具的套餐说明。Claude Code 的接入方式在 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 有专门文档。

6. 本篇常见错排查

端口 11434 连不上。 先确认 compose 里映射的是 127.0.0.1:11434:11434,如果你从另一台机器访问,需要改成 0.0.0.0:11434:11434,但这样会暴露到公网,务必配合防火墙只放行可信 IP。检查 docker compose ps 端口列是否显示。

模型拉取卡住或超时。 大模型动辄几个 G,网络抖动很正常。可以重试 ollama pull,它支持断点续传。磁盘空间不足也会导致拉取失败,df -h 看一下 /opt 所在分区。

curl 返回 404 或 model not found。 检查模型名是否和 ollama list 里完全一致,包括 tag,比如 qwen2:7b 不能写成 qwen2。走 TaoToken 时,确认该模型名在统一通道侧有对应路由。

TaoToken 返回 401。 Key 没带对,或者 .env 没被正确加载。用 echo $TAOTOKEN_API_KEY 确认变量存在,curl 里 Authorization: Bearer 后面不要有多余空格。

CPU 推理特别慢。 确认 OLLAMA_KEEP_ALIVE 生效,模型常驻后第二次请求会快很多。另外检查是否误用了大参数模型,7B 在纯 CPU 上是比较现实的起点。

容器重启后模型丢失。 说明数据卷没挂对。确认 compose 里 ./data:/root/.ollama 这一行存在,且 ./data 目录有写权限。

stream 流式返回空白。 部分中间件版本对流式支持有 bug,可以先用非流式请求验证链路,确认后再开 "stream": true。如果客户端强制流式,换一个稳定版本或改用非流式轮询。

7. 后续怎么把这套配置用起来

到这里,Docker 里的 Ollama、本地模型、TaoToken 统一通道三件事都通了。日常使用中,客户端配置只维护一份 settings.json,本地调试时把 baseUrl 指向 http://127.0.0.1:11434/v1,需要更强模型或不想占本地资源时切到 https://taotoken.net/api。Key 统一用 TaoToken 控制台里创建的那一个,换工具不用重新申请。

安全上再强调一次:Ollama 默认无鉴权,生产环境不要直接把 11434 暴露到公网。要么只绑回环,要么在前面加一层带白名单的反向代理。TaoToken 这一侧负责的是统一入口和 Key 管理,本地推理和远端调用各司其职,配置一次,后面加新工具时改的只是模型名。

更多推荐