从 Ollama 迁移到 Docker Model Runner:一份可验证、可回退的实操教程
目标:在不夸大性能收益的前提下,把一个本地 LLM 从 Ollama 迁移到 Docker Model Runner(DMR),验证 CLI、兼容 API 与 Docker Compose 模型依赖,并保留清晰的回退路径。
>
适用对象:已经使用 Docker Desktop 或 Docker Engine 管理应用,希望把模型版本、配置和应用生命周期放进同一套工作流的开发者。
>
不适用对象:只在单机偶尔聊天、没有 Docker 工作流,或期待“换成 Docker 后推理一定更快”的用户。原文没有提供性能基准,DMR 的主要价值是管理、分发与 Compose 集成。
1. 你将完成什么
完成后,你会得到三个可独立验证的闭环:
- 使用
docker model拉取并运行一个小模型; - 通过 Ollama 兼容 API 和 OpenAI 兼容 API 调用同一个模型;
- 在
compose.yaml中把模型声明为应用依赖,而不是写死一个外部 Ollama 地址。
迁移路线:
现有应用 ── Ollama API :11434
│
├─ 记录旧配置与模型
├─ 启用 Docker Model Runner
├─ 重新拉取模型制品
├─ 先验证 DMR :12434
└─ 只修改应用 base URL ──> Docker Model Runner
├─ llama.cpp / GGUF
├─ vLLM / Safetensors(硬件受限)
└─ Diffusers(硬件受限)2. 事实、提炼与实践扩展
原文事实
- DMR 可以把 GGUF 或 Safetensors 模型当作带标签的制品管理,并推送到兼容 OCI 的注册表。
- DMR 支持 OpenAI 与 Ollama 兼容 API;原文迁移时主要修改了 API 地址。
- Ollama 默认使用
11434,DMR 的主机 TCP 端口通常为12434。 - DMR 可根据模型格式使用不同推理引擎;作者实际验证的是 Mac 上量化 GGUF、llama.cpp 与 Metal。
- Ollama 与 DMR 分别保存模型,迁移通常需要重新下载。
- 作者没有证明 DMR 性能更好,结论只是 Docker 工作流下更方便。
本文提炼
真正值得迁移的不是“运行一条不同的命令”,而是把模型变成项目依赖:模型标识、上下文配置、应用绑定和启动方式可以一起审查、复现与交接。
实践扩展
本文增加了原文没有展开的预检、双轨验证、Compose 最小示例、失败处理与回退步骤。它们依据 Docker 官方文档整理,不代表原作者亲自执行过这些步骤。
3. 前置条件与边界
3.1 软件要求
- Docker Desktop,或已安装 Docker Engine 的 Linux;
- 若使用 Compose 模型:Docker Compose v2.38 或更高版本;
curl;- 足够的磁盘空间和内存;首次拉取模型可能耗时较长。
先检查:
docker version
docker compose version
docker model version通过标准:三条命令均正常返回版本信息,且 Compose 版本不低于 v2.38。
失败处理:
- 若出现
docker: 'model' is not a docker command,说明 Model Runner 尚未启用或插件未安装; - 若 Compose 低于 v2.38,不要继续测试
models:,先升级 Compose; - 不要为了“试一下”删除现有 Ollama 模型。
3.2 硬件边界
- GGUF 通常走 llama.cpp;Apple Silicon 可使用 Metal 加速;
- vLLM 面向更高吞吐服务,但需要匹配的 NVIDIA GPU 与受支持系统;
- Diffusers 也有 NVIDIA/CUDA 与平台限制;
- 模型能否加载取决于模型大小、量化方式、上下文长度和可用内存,而不是仅看参数量。
本教程选择体积较小的 ai/smollm2:360M-Q4_K_M 作为验证模型,目的是先证明链路,不代表它适合真实业务。
4. 步骤一:记录 Ollama 基线并准备回退
迁移前先记录现状:
mkdir -p dmr-migration-evidence
ollama list | tee dmr-migration-evidence/ollama-models.txt
curl -fsS http://localhost:11434/api/tags \
| tee dmr-migration-evidence/ollama-tags.json再记录应用中的旧配置,例如:
OLLAMA_BASE_URL=http://localhost:11434
MODEL_NAME=<当前模型名>验证标准:
ollama-models.txt中能看到当前模型;ollama-tags.json是非空 JSON;- 已知道应用在哪里配置 base URL 和模型名。
如果 Ollama 本身不可用,先停止迁移。否则后面出现问题时,你无法判断是原环境故障还是迁移引入的问题。
5. 步骤二:启用 Docker Model Runner
5.1 Docker Desktop
进入 Settings → AI:
- 启用 Docker Model Runner;
- 若要从主机进程调用 API,启用 host-side TCP support;
- 端口使用
12434; - Windows 且有受支持 NVIDIA GPU 时,再按需要启用 GPU 推理。
然后检查:
docker model version
docker model status5.2 Linux Docker Engine
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install docker-model-pluginRPM 系发行版:
sudo dnf update
sudo dnf install docker-model-plugin再验证:
docker model versionDocker Engine 的 TCP 支持默认使用 12434。如果你修改了端口,后续命令必须同步修改。
6. 步骤三:拉取并运行验证模型
拉取固定量化标签,避免不同机器隐式选择不同制品:
docker model pull ai/smollm2:360M-Q4_K_M
docker model list运行一次 CLI 对话:
docker model run ai/smollm2:360M-Q4_K_M \
"只回答一个词:Docker"预期输出形态:命令返回模型生成的文本,内容应包含 Docker。具体格式和生成速度会随版本、硬件与模型而变化。
失败处理:
docker model logs重点检查:
- 模型是否完整下载;
- 是否内存不足;
- 模型标签是否拼写正确;
- Model Runner 是否处于运行状态。
不要在首次拉取很慢时直接判断 DMR 性能差。下载耗时和推理耗时是两件事。
7. 步骤四:验证两套兼容 API
7.1 先检查模型列表
Ollama 兼容端点:
curl -fsS http://localhost:12434/api/tagsOpenAI 兼容端点:
curl -fsS http://localhost:12434/engines/v1/models通过标准:响应为非空 JSON,并包含 ai/smollm2 或所拉取的完整标签。
如果主机访问失败:
- Docker Desktop:确认已启用 host-side TCP support;
- 检查
12434是否被其他进程占用; - 确认没有把容器内地址和主机地址混用。
7.2 Ollama 兼容调用
curl -fsS http://localhost:12434/api/chat \
-H 'Content-Type: application/json' \
-d '{
"model": "ai/smollm2:360M-Q4_K_M",
"stream": false,
"messages": [
{"role": "user", "content": "用一句中文解释什么是容器镜像。"}
]
}'7.3 OpenAI 兼容调用
curl -fsS http://localhost:12434/engines/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "ai/smollm2:360M-Q4_K_M",
"temperature": 0,
"messages": [
{"role": "user", "content": "只返回 JSON:{\"status\":\"ok\"}"}
]
}'验证标准:
- HTTP 请求成功;
- 响应是 JSON;
- Ollama 兼容响应包含模型回复字段;
- OpenAI 兼容响应包含
choices; - 不要只看“答案像真的”,还要确认请求实际发到了
12434。
DMR 本地 OpenAI 兼容 API 不要求真实 API key。若第三方客户端强制填写,可用无意义占位值,例如 not-needed,不要放入真实云端密钥。
8. 步骤五:把现有客户端从 Ollama 切到 DMR
最小迁移原则:先只改端点,不同时更换模型、提示词和采样参数。
| 客户端类型 | Ollama 旧地址 | DMR 新地址 |
|---|---|---|
| Ollama 兼容客户端 | http://localhost:11434 |
http://localhost:12434 |
| OpenAI 兼容客户端 | 视原配置而定 | http://localhost:12434/engines/v1 |
示例环境变量:
export MODEL_BASE_URL=http://localhost:12434/engines/v1
export MODEL_NAME=ai/smollm2:360M-Q4_K_M
export MODEL_API_KEY=not-needed切换后,用同一条固定提示分别请求 Ollama 和 DMR,并记录:
- 是否成功;
- 首次响应时间;
- 总响应时间;
- 内存/显存占用;
- 输出是否满足任务要求。
原文没有提供这些基准,所以不要把个人体验当成你的验收结论。
9. 步骤六:用 Docker Compose 声明模型依赖
下面的例子展示 Compose 模型绑定。它不会部署生产应用,只用容器打印自动注入的模型地址和模型名。
文件:`compose.yaml`
services:
model-env-check:
image: alpine:3.22
command:
- /bin/sh
- -ec
- |
test -n "$$LLM_URL"
test -n "$$LLM_MODEL"
printf 'LLM_URL=%s\n' "$$LLM_URL"
printf 'LLM_MODEL=%s\n' "$$LLM_MODEL"
models:
- llm
models:
llm:
model: ai/smollm2:360M-Q4_K_M
context_size: 2048先做静态解析:
docker compose config再运行:
docker compose up --abort-on-container-exit预期输出形态:
LLM_URL=<由平台注入的非空模型端点>
LLM_MODEL=ai/smollm2:360M-Q4_K_M这里使用 $$LLM_URL 而不是 $LLM_URL,是为了让变量在容器内展开,而不是被 Compose 提前替换。
通过标准:
docker compose config无语法错误;- 服务退出码为 0;
- 两个变量均非空;
- 模型名与
compose.yaml中声明的一致。
失败处理:
models字段不识别:检查 Compose 是否达到 v2.38;- 模型未拉取:检查 Model Runner 状态和注册表访问;
- 变量为空:确认服务的
models绑定与顶层模型名称一致; - 不要用硬编码
localhost:12434替代注入变量来“绕过”失败,否则会丢失 Compose 模型依赖的核心价值。
10. 可选:自定义变量名
如果应用已经使用 AI_MODEL_URL 和 AI_MODEL_NAME,可以使用长语法:
文件:`compose.yaml`(替换服务中的绑定部分)
services:
app:
image: your-app-image
models:
llm:
endpoint_var: AI_MODEL_URL
model_var: AI_MODEL_NAME
models:
llm:
model: ai/smollm2:360M-Q4_K_M
context_size: 2048这是配置契约示例;your-app-image 必须替换为真实应用镜像,应用也必须读取这两个环境变量。
11. 迁移验收清单
只有以下条件全部满足,才建议停用旧 Ollama 路径:
- 已保存 Ollama 模型列表和旧端点配置;
docker model version与docker model status正常;- DMR 已拉取明确标签的模型;
- CLI 调用成功;
12434/api/tags或 OpenAI 模型列表端点成功;- 真实客户端只修改 base URL 后仍能工作;
- Compose 配置能解析,模型变量能注入;
- 已记录下载成本、内存/显存和响应表现;
- 回退到 Ollama 的配置仍可用;
- 没有把“更方便”写成“性能更好”。
12. 回退步骤
若 DMR 链路不稳定,先恢复应用端点:
export MODEL_BASE_URL=http://localhost:11434
export MODEL_NAME=<原 Ollama 模型名>然后验证:
curl -fsS http://localhost:11434/api/tags如果应用恢复正常,说明回退完成。此时保留 DMR 模型用于排查,不要急着删除任何一侧的模型文件。
只有确认不再需要测试模型时,才执行清理:
docker model rm ai/smollm2:360M-Q4_K_M13. 常见误区
“换成 Docker,推理一定更快”
不成立。原文没有性能测试;DMR 的主要收益是模型制品化、Compose 集成与统一管理。
“Ollama 的模型文件可以直接复用”
原文作者需要重新下载。迁移前应预留网络时间和磁盘空间。
“端口改成 12434 就算迁移完成”
不够。还应验证模型标识、API 格式、真实客户端、Compose 绑定和回退路径。
“本地 API 不需要密钥,所以可以对公网开放”
危险。DMR 本地兼容 API不要求真实 API key,不等于适合裸露在公网。需要远程访问时,应增加网络隔离、认证、TLS 和访问控制;这些属于部署扩展,不是原文已验证结论。
“上下文越大越好”
上下文长度会消耗更多内存。官方建议根据实际任务保持尽可能小的上下文;先用 2048 做链路验证,再按需求调整。
14. 原文方法覆盖清单
| 原文方法 | 是否纳入 | 落点 | 若遗漏原因 |
|---|---|---|---|
| 启用 Docker Model Runner | 是 | 步骤二 | — |
使用 docker model pull 与 docker model run |
是 | 步骤三 | — |
| 将 API 从 Ollama 端口切换到 DMR | 是 | 步骤四、五 | — |
| 使用 OpenAI/Ollama 兼容 API | 是 | 步骤四 | — |
| 在 Compose 中声明模型依赖 | 是 | 步骤六、十 | — |
| 将模型作为带版本的 OCI 制品管理 | 部分 | 步骤三及原理说明 | 推送私有注册表涉及账号和外部写入,不纳入最小迁移闭环 |
| 使用 GGUF、Safetensors 与不同推理引擎 | 部分 | 硬件边界 | 原文未实际验证 vLLM 与 Diffusers,本教程不伪造运行结果 |
| 重新下载模型 | 是 | 步骤一、三及验收清单 | — |
| 判断是否值得从 Ollama 迁移 | 是 | 适用对象、验收清单、误区 | — |
15. 验证证据级别
static_publish_ok:教程的 Markdown/HTML 生成、结构与发布检查通过后方可标记为真;mock_code_run_ok:不适用,本教程没有用 Mock 替代模型;real_backend_contract_ok:本文命令依据 Docker 官方文档整理,但应在读者自己的 DMR 版本上重新验证;real_backend_smoke_ok:本文不声称已在你的硬件上完成模型拉取和推理。只有你实际执行步骤三至六并保存输出后,才能标记为真。
参考资料
- 原文:I ditched Ollama for Docker, and my local LLM setup finally stopped being a hassle,XDA Developers,Anurag Singh,发布于 2026-07-28。
- Docker 官方:Docker Model Runner 入门
- Docker 官方:在 Compose 中定义 AI 模型
- Docker 官方:Docker Model Runner REST API
文档命令与接口已按 2026 年 7 月可访问的 Docker 官方文档核对。Docker Model Runner 仍可能迭代;正式迁移前,请再次检查与你安装版本对应的官方文档。