最近团队里又有同事在群里问Ollama到底怎么装,说他照着网上各种教程手动配了两遍都没跑起来,不是Python依赖打架,就是下载的模型文件不知道去哪了。这事我太熟了,我自己刚开始玩Ollama也是一样,后来干脆全部改用Docker部署,整个流程一下就清爽了。这篇内容就是我把这两年用Docker跑Ollama模型的经验完整梳理一遍,从最基础的安装命令,到GPU直通、API对接,再到生产环境里会踩的坑,一次说清楚。如果你正在做模型评测、本地私有化部署、或者想给团队搭一个统一的大模型服务环境,这篇基本可以拿来直接当操作手册。
用Docker部署Ollama,本质上就是把Ollama运行时、模型文件和环境依赖全部塞进一个标准化的容器里,宿主机只需要一个Docker引擎。这样做最直接的好处是:不管你在Ubuntu、Debian还是CentOS上,也不管是个人笔记本还是服务器,同一个镜像跑起来的结果完全一样,再也不用花时间清理环境。
1. 为什么我坚持用Docker跑Ollama——容器化部署的实际收益
1.1 裸机安装的三个老大难问题
先说我在裸机环境装Ollama踩过的坑。早期Ollama版本对Linux的依赖其实挺挑的,需要系统里有合适的glibc版本、显卡驱动、CUDA运行库。每次在新机器上装,几乎都会碰到一类问题:Ollama安装好了,但跑模型的时候提示CUDA版本不对,或者libcuda.so找不到,又不敢乱动系统里正在跑的CUDA环境,因为可能有其他业务依赖旧版本。
再有一个是Python环境的问题。虽然Ollama本身不是Python项目,但它周边工具链(比如各种自动调用脚本、WebUI工具)往往依赖特定Python版本和一堆库,自己环境一旦很乱,很容易出现"装A依赖就把B的版本改了"的情况。在多人共用的机器上,这种问题尤其烦人。
最后一个问题是卸载和回滚。裸机装的东西,想要换版本或者彻底清掉,需要手动删一堆文件、还要检查环境变量、清理缓存。操作不熟练的话,很容易把系统搞出毛病。
1.2 Docker把这些问题简化成了什么
用Docker部署之后,上面这些痛点基本消失:
- 依赖隔离:Ollama运行时连同它需要的系统库都封装在镜像里,宿主机只需要有Docker引擎。
- 版本可控:想换Ollama版本,换一个镜像标签就可以,回滚也简单,再启动旧容器就是旧版本。
- 一致性:同一个镜像在任何机器上行为一致,不用再写"在我机器上是好的"这种话。
- 可迁移:模型文件存到数据卷里,备份、迁移都很方便。
我自己的经验是,容器化部署看起来多学一个Docker概念,但实际上把后期运维成本降得非常明显。尤其是在服务器上,一台机器可能同时跑多个AI服务,用Docker天然隔离端口、内存、日志,互不干扰,这在裸机环境下要手动做很多配置才能达到。
1.3 也有不需要Docker的场景
当然不是所有人一上来就必须Docker。如果你只是在个人电脑上装来尝鲜,平时跑跑小模型、不涉及给别人提供服务,那直接按Ollama官网的脚本装也挺好,省事。但如果你想把这个模型服务稳定地跑起来、供多个应用调用、或者部署到团队共用的服务器上,那我建议直接用Docker,一步到位。后面我说的所有操作,也都是基于Docker环境。
2. 部署前置工作:硬件清点、Docker环境与镜像版本选择
2.1 硬件需求心里要有数
部署前先搞清楚自己要跑什么规模的模型。Ollama支持很多开源模型,包括Qwen、Llama、Mistral等系列。模型参数大小和量化方式直接决定内存占用。我列一个常用参考表:
| 模型参数规模 | 量化方式 | 内存/显存预估 | 适用场景 |
|---|---|---|---|
| 0.5B~1.5B | Q4_K_M | 2~4GB | 轻量任务、快速测试 |
| 7B~8B | Q4_K_M | 6~8GB | 日常对话、文档总结 |
| 14B | Q4_K_M | 10~16GB | 中等复杂度推理 |
| 32B | Q4_K_M | 20~32GB | 高质量生成 |
| 70B | Q4_K_M | 40~50GB | 深度推理、代码生成 |
注意这里的内存数值是一个大概范围,实际占用会包括KV cache和上下文长度。跑32B以上模型,16GB内存的机器就会很吃力了,建议至少32GB内存起步。有NVIDIA显卡的话,显存尽量满足上述容量需求,否则模型会被放到内存里用CPU算,速度会慢很多。
没有独立显卡也能跑,比如7B Q4模型在现在主流的8核CPU上,单次生成大概每秒几个token到十几个token,体验一般,但调试API、做简单自动化是完全够用的。如果有RTX 3060 12GB这种级别的显卡,跑7B模型就非常流畅。我建议新手刚开始别贪大,先跑7B级别模型打通流程,之后再根据效果调整。
2.2 Docker环境的安装与验证
Linux服务器上安装Docker,最标准的做法是用官方脚本。Debian/Ubuntu系:
curl -fsSL https://get.docker.com | sh systemctl enable --now docker装好以后验证一下:
docker version输出里有client和server两段信息,就说明Docker引擎正常。然后还要确认一下当前用户有权限操作Docker,避免每次都要sudo:
sudo usermod -aG docker $USER newgrp docker如果你是CentOS/RHEL系,官方脚本同样适用。不建议再额外装docker-compose的方式安装compose插件,现在Docker自带docker compose命令,方便一点。
2.3 镜像版本怎么选
Ollama官方在Docker Hub上有ollama/ollama镜像。打开镜像仓库的tags页面,能看到两类标签:
- 纯版本号标签,比如
0.5.4、0.6.1 latest标签
我的建议是生产环境不要用latest,因为它指向最新发布版,万一官方某次升级引入了不兼容变化,你重启容器就中招了。正确做法是固定一个知道自己验证过的版本,比如ollama/ollama:0.5.4。等官方出稳定新版本、你验证过再手动升级。
如果你需要读模型文件做二次开发,还有带-rocm后缀的标签用于AMD GPU,-cu后缀用于NVIDIA GPU。不过多数情况下基础标签已经自动带CUDA支持了,我后面会专门讲GPU直通。
当前的镜像体积也不小,一般几百MB,拉取时有耐心。拉取完可以确认一下:
docker image inspect ollama/ollama:0.5.4 | head -30能看到镜像架构和配置信息,确认拉取成功。
3. 一条命令跑起Ollama:容器启动参数逐个拆解
3.1 最小可用容器
最简部署只需要下面这一条命令:
docker run -d \ --name ollama \ -p 11434:11434 \ -v ollama:/root/.ollama \ ollama/ollama:0.5.4这里每个参数背后都有讲究,我逐个说:
-d:后台运行容器,不会阻塞终端。--name ollama:给容器起名叫ollama,后面操作、查看日志、停止都方便。不指定就会随机生成一个名字,找起来很麻烦。-p 11434:11434:把容器内部的11434端口(Ollama API默认端口)映射到宿主机的11434端口。这样宿主机上其他程序、局域网内其他机器就能直接访问这个端口,调用模型服务。-v ollama:/root/.ollama:这是关键。把容器里的/root/.ollama目录挂载到Docker数据卷ollama里。Ollama下载的所有模型文件都存在这个目录下,不挂载的话,容器一删模型全没了。数据卷的好处是路径由Docker统一管理,不用关心具体位置。
跑起来之后,可以用docker ps确认容器状态是Up。
3.2 为什么建议用命名卷而不是bind mount
有人习惯用-v /data/ollama:/root/.ollama这种方式做路径映射(bind mount)。好处是模型文件直接落在宿主机某个具体目录里,自己好找。但坏处是权限问题很常见:容器内通常以root运行,挂载的目录如果属主不是root,或者SELinux没配置好,就会报permission denied。命名卷没有这个麻烦,数据卷目录归Docker管理,权限自动协调好。
我自己现在的做法是:容器部署用命名卷,备份的时候再用docker run --rm -v ollama:/data -v /backup:/backup临时把数据卷内容拷出来。这样兼顾了稳定性和可管理性。
3.3 GPU直通:让推理速度真正起飞
如果你的服务器上有NVIDIA显卡,不把显卡传给容器就亏大了。要让容器用上GPU,需要做的步骤如下。
先安装NVIDIA Container Toolkit。以Ubuntu为例,官方给的方式一般是添加APT源之后安装:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \ sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt-get update sudo apt-get install -y nvidia-container-toolkit装完后配置Docker运行时:
sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker然后启动容器的时候加上--gpus all参数:
docker run -d \ --name ollama \ --gpus all \ -p 11434:11434 \ -v ollama:/root/.ollama \ ollama/ollama:0.5.4验证GPU是否真的被容器用到了,进入容器执行:
docker exec -it ollama nvidia-smi能看到显卡信息就说明直通成功。如果看不到,多半是toolkit没装好或者Docker运行时没有切换,后面踩坑部分我会再展开。
3.4 下载模型并完成首次对话
容器跑起来之后,下载模型的命令要放到容器里执行:
docker exec -it ollama ollama pull qwen2.5:7b这里qwen2.5:7b是一个例子,你可以换成其他你想用的模型。下载过程会有进度条,模型会存到刚才挂载的/root/.ollama目录里。下完以后直接对话测试:
docker exec -it ollama ollama run qwen2.5:7b当终端出现>>> Send a message提示,输入一句话回车,模型就会返回结果。这一步通了,整套部署就算成功了一半。
4. 模型下载管理与API对接:让容器里的模型真正被用起来
4.1 容器内的ollama命令用法
因为Ollama跑在容器里,所有命令都要通过docker exec进入容器执行。我常用的几条命令:
# 查看本机已下载的模型 docker exec ollama ollama list # 查看某个模型详情 docker exec ollama ollama show qwen2.5:7b # 删除已下载的模型 docker exec ollama ollama rm qwen2.5:7b # 从本地文件导入模型 docker exec -it ollama ollama create mymodel -f /root/Modelfile特别是最后一条,Ollama支持把Hugging Face上其他格式的模型转换后导入,但操作上要先把模型文件拷到容器或者挂载目录里,再执行create命令。日常用得不多,但偶尔会有奇效。
4.2 用Modelfile定制模型
Ollama的强大之处在于可以通过Modelfile自定义模型参数。比如我嫌默认温度太高导致输出发散,就写一个简单的Modelfile:
FROM qwen2.5:7b PARAMETER temperature 0.3 PARAMETER top_p 0.8 SYSTEM 你是一个严谨的技术文档撰写助手。然后执行:
docker cp ./Modelfile ollama:/root/Modelfile docker exec ollama ollama create tech-writer -f /root/Modelfile之后用tech-writer这个模型名调用,就会自动带上这些参数和系统提示词。注意docker cp的路径别搞错,我经常因为路径不对导致create命令报找不到文件。
4.3 REST API调用方式
容器跑起来后,宿主机端口11434就是Ollama的API入口。最常用的接口有两个:
生成接口/api/generate,一般用于一问一答式补全:
curl http://localhost:11434/api/generate -d '{ "model": "qwen2.5:7b", "prompt": "用一句话解释Docker是什么", "stream": false }'不设置stream: true的话返回的是完整JSON;设置成true,会按SSE格式逐段返回token,适合做流式打字机效果。
对话接口/api/chat,适合模拟多轮对话:
curl http://localhost:11434/api/chat -d '{ "model": "qwen2.5:7b", "messages": [ {"role": "user", "content": "Docker和虚拟机有什么区别?"} ], "stream": false }'如果你的应用在另一个容器里,不想通过宿主机端口访问,更优雅的方式是让两个容器共享一个Docker网络,然后用容器名访问,比如http://ollama:11434。
4.4 快速配一个Web对话界面
命令行里玩模型终归不够直观,我一般会顺手部署一个Open WebUI,让团队里不懂命令行的同事也能用浏览器对话。
docker run -d \ --name open-webui \ -p 3000:8080 \ --add-host=host.docker.internal:host-gateway \ -v open-webui:/app/backend/data \ ghcr.io/open-webui/open-webui:main打开http://服务器IP:3000,注册账号后在模型选择里就能看到Ollama已经下载的模型。如果WebUI和Ollama不在同一个Docker网络,首次需要手动配置Ollama的Base URL,填http://宿主机IP:11434即可。
5. 生产级配置:GPU直通、持久化与并发调优
5.1 环境变量:这些参数得知道
Ollama容器支持通过环境变量控制行为。我常用这几个:
| 环境变量 | 作用 | 建议值 |
|---|---|---|
OLLAMA_HOST | 监听地址,默认0.0.0.0,除非有安全需求不用改 | 0.0.0.0 |
OLLAMA_NUM_PARALLEL | 同时处理的请求数 | 1~4 |
OLLAMA_MAX_LOADED_MODELS | 最多同时加载的模型数量 | 1~2 |
OLLAMA_KEEP_ALIVE | 模型在内存中保持加载的时间,单位秒 | 5m或者-1维持 |
OLLAMA_MODELS | 模型存储路径,容器内默认在/root/.ollama/models | 一般不用改 |
在启动容器时通过-e传进去即可:
docker run -d \ --name ollama \ --gpus all \ -e OLLAMA_NUM_PARALLEL=2 \ -e OLLAMA_MAX_LOADED_MODELS=1 \ -e OLLAMA_KEEP_ALIVE=5m \ -p 11434:11434 \ -v ollama:/root/.ollama \ ollama/ollama:0.5.45.2 并发和内存怎么权衡
内存和显存有限,并发开太高容易OOM。我建议先用默认值跑一天,观察内存和显存占用,再逐步调高OLLAMA_NUM_PARALLEL。比如8GB显存的卡跑7B Q4模型,同时处理2个请求通常没问题,开4个就可能爆显存。模型在内存里驻留有好处也有坏处:常驻可以省去加载时间(首次加载可能需要几秒到几十秒),但会一直占着显存。OLLAMA_KEEP_ALIVE=5m是一个比较平衡的设置。
5.3 自动重启和日志管理
服务跑在容器里,最怕机器重启后容器没起来。给docker run加上--restart always参数,或改成unless-stopped也行:
docker run -d \ --name ollama \ --gpus all \ --restart unless-stopped \ ...unless-stopped比always好的地方在于:如果你明确执行了docker stop ollama,Docker不会在重启机器后强行把它拉起来。
日志查看也是日常运维的必要操作:
docker logs -f ollama拉出来的日志会显示每次启动加载的GPU信息、模型加载时间以及API请求的错误原因。之前我遇到过一次容器能起来但模型加载异常,就是靠日志里unable to load model报错定位到是磁盘空间不足。
5.4 用docker-compose固化整套配置
命令行参数一长串,不便于团队共享。我还是建议把配置固化到docker-compose.yml里。下面是我目前在用的版本,可以直接抄:
services: ollama: image: ollama/ollama:0.5.4 container_name: ollama restart: unless-stopped ports: - "11434:11434" volumes: - ollama_data:/root/.ollama environment: - OLLAMA_NUM_PARALLEL=2 - OLLAMA_MAX_LOADED_MODELS=1 - OLLAMA_KEEP_ALIVE=5m deploy: resources: limits: memory: 32g # 如果有NVIDIA GPU,取消下一行的注释 # gpus: # - driver: nvidia # count: all # capabilities: [gpu] open-webui: image: ghcr.io/open-webui/open-webui:main container_name: open-webui restart: unless-stopped ports: - "3000:8080" volumes: - open_webui_data:/app/backend/data environment: - OLLAMA_BASE_URL=http://ollama:11434 volumes: ollama_data: open_webui_data:在这个配置文件所在目录执行:
docker compose up -d会自动创建自定义网络,两个服务可以通过ollama这个服务名互相访问。该限制内存32g也写在deploy配置里,防止模型加载时把机器其他服务挤垮。
6. 我在部署和日常使用中踩过的四个坑
6.1 模型下载中断和处理方法
第一次在服务器上下载7B模型,进度跑到一半卡住不动了,等十几分钟直接失败。后来发现Ollama的模型下载是多分片并发拉取,网络稍有抖动就会有一个分片超时,重试是整个文件从来,非常折磨。
我的对策:
- 下载前先检查磁盘空间和网络连通性。
- 不要让Ollama容器内存占用过高,下载阶段CPU占用也明显,尽量选空闲时段。
- 如果经常失败,可以在宿主机配置HTTP代理环境变量让Ollama走代理下载。注意这里说的是合法合规的代理,具体地址根据你的网络环境配置。不配置也可以,耐心多试几次。
- 另一个办法是从别人那直接拷贝模型文件放到数据卷的
models目录下,Ollama会识别。迁移时我通常用带命名卷的临时容器做打包拷贝。
6.2 端口11434被占用
这是多服务共存的服务器上很常见的问题。启动容器时提示:
Error response from daemon: driver failed programming external connectivity on endpoint ollama: Bind for 0.0.0.0:11434 failed: port is already allocated解决方案很简单,把宿主机的端口映射改成其他端口,比如:
-p 11435:11434但要注意,改成11435之后,所有API调用地址、WebUI里配置的Ollama Base URL都要同步改。我一开始图省事就直接换端口,结果Open WebUI一直连不上,排查半天才发现是这里没更新。
6.3 显卡明明有,容器里就是看不到
我在一块新卡服务器上部署时,--gpus all也加了,但容器内执行nvidia-smi报错找不到设备。排查链路是这样的:
- 首先确认宿主机带不带卡,直接执行
nvidia-smi,正常。 - 然后确认
docker run里有没有--gpus all,确认有。 - 再确认NVIDIA Container Toolkit是否安装:执行
docker info | grep -i runtime,发现runtimes里只有runc,没有nvidia。 - 问题定位在toolkit没用上,重新执行
sudo nvidia-ctk runtime configure --runtime=docker,然后重启Docker。 - 再启动容器时就能看到显卡了。
这类问题本质上就是运行时没注册,不是Ollama的问题,排查方向要明确。
6.4 容器内模型加载慢、输出越来越慢
有段时间我用7B模型做批量测试,跑了几百条之后发现单条响应时间明显变长。一看内存,模型常驻占了快20GB,系统开始用swap。原因是我一开始为了响应快设了OLLAMA_KEEP_ALIVE=-1,模型一直驻留内存,再加上同时跑着WebUI和其他任务,内存就吃不消了。
从那次之后,我把OLLAMA_KEEP_ALIVE改回5m,并限制了容器内存上限,问题没有再出现。在资源有限的机器上,让模型空闲一段时间后自动卸载是更划算的选择,那几秒加载延迟换来的是整体稳定。
6.5 一个容易忽视的权限坑
如果你一定要用bind mount挂载模型目录,比如-v /data/ollama:/root/.ollama,注意宿主机目录权限。Ollama容器默认用户是root,但目录如果挂在NFS或者有子目录权限限制,模型加载时会有permission denied。我建议除非清楚自己在做什么,否则统一用命名卷。硬要用bind mount,记得先:
mkdir -p /data/ollama chmod 755 /data/ollama再启动容器。
最后分享一点我自己的使用心得
用Docker把这套东西管起来之后,我最大的感受是不用再为环境问题焦虑了。一台新服务器要部署同样的模型服务,不需要再翻各种安装教程,只要把docker-compose文件拷过去,docker compose up -d,等镜像和模型下载完就能用。团队里几个人一起开发的时候,也不会出现"A的版本是0.4,B的版本是0.6"这种对不上的情况。
另外,容器化也让我养成了一件事:每次换Ollama版本之前,先停掉容器、备份数据卷、再拉新镜像。这一步花不了几分钟,但能避免很多不必要的返工。
如果后续你想把多个不同规模、不同用途的模型组合起来做一个私有化推理平台,这套Docker底子完全够用,甚至可以在这个基础上继续叠服务,比如自动化评测、数据标注、流式对话网关,都是顺着已有架构延伸的活。