最近不少朋友问我,在自己服务器上跑个大模型到底怎么折腾最省心。试了一圈下来,我自己的结论是:用 Docker 装 Ollama 是目前在 Linux 服务器上部署本地大模型最稳、最干净、也最好维护的路线。这篇就把我的实操过程、踩过的坑、以及一些配置细节完整记录下来,给准备上手的朋友一个参考。
这篇内容适合谁?如果你手里有一台 Linux 服务器(哪怕是乞丐版 2 核 4G、没有独立显卡,也有一堆小模型可以跑),想跑自己的私有 AI 助手、想写代码接 API、或者想跟我一样折腾点自动化任务,这篇文章可以帮你少走很多弯路。如果你对 Docker 和 Linux 命令几乎零基础,也没有关系——下面的每条命令我都会解释它在做什么,每步操作背后的原因我也会说清楚,你跟着抄作业就行。
1. 为什么非要用 Docker 来部署 Ollama
1.1 直接装和容器化部署的差别
很多人一上来就习惯性的用官方一键脚本装:
bash复制curl -fsSL https://ollama.com/install.sh | sh
这个方式确实也能跑起来。但是等你用了一段时间,就会遇到几个头疼的问题:
卸载不干净。 官方脚本会在你系统里撒下 systemd 服务文件、环境变量配置、用户组权限、以及一整个 /usr/share/ollama 目录。哪天你想换个方式重新装,手动删这些文件非常容易漏,残留的东西有时候还会干扰新安装。
升级容易出岔子。 本地直接装的 Ollama 每次升级,实际上是把二进制文件覆盖一遍。如果新版改了默认模型目录或者依赖的库,老版本缓存可能会出现各种奇奇怪怪的兼容问题。
和你现有的服务抢端口和环境。 如果你这台服务器上本身就跑了不少其他服务,直接装一个海外软件,它默认自带的 systemd 单元可能会干扰你的已有网络配置,尤其是在代理环境和复杂网络拓扑下。
而用 Docker 部署之后,整个 Ollama 就像一个隔离的"盒子",它运行所需的运行库、文件、端口、环境变量,全都在这个盒子里定义好。你想升级就换镜像,想完全卸载就删容器,不会给系统留任何"垃圾"。这跟我平时在服务器上跑 Nginx 和 MySQL 一个思路:能容器化就绝不直接装在宿主上,省下的时间绝对比你多投入的学习成本值。
1.2 隔离环境带来的实际好处
我举一个非常现实的例子。做 AI 应用开发的时候,你经常需要跟着项目切换不同的模型版本、不同的底层库。如果直接装在系统里,每个项目依赖的模型版本一变,可能要把 Ollama 整个卸掉重装。但是用 Docker,我可以同时跑好几个 Ollama 容器,每个容器挂载不同的数据卷、用不同的 Ollama 版本,测试完直接删掉容器,对系统零污染。
还有一点很重要:模型文件本身非常大(几个 GB 到几十个 GB 都有)。用 Docker 的数据卷机制,你把模型文件放到指定的 volume 或者宿主机目录中,这样即使容器被删掉重建,模型文件还在,不需要重新下载。这个机制对经常折腾、喜欢"推倒重来"的选手来说非常友好。我用下来最大的感受是,容器化让"部署"真正变成了"配置"——我不再关心它内部怎么工作的,只需知道给它喂什么参数、它在哪个端口等我。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署前的硬性检查与准备
2.1 服务器配置要求与我的推荐下限
在正式开始之前,你最好先弄清楚自己的服务器能撑起多大的模型。这里有一个很实用的换算逻辑:7B 参数级别的模型(比如 Llama3 8B、Qwen2.5 7B),大概需要 6-10GB 内存(包括 CPU 推理的情况);13B 参数级别的模型,内存需求会翻到 16GB 左右;70B 及以上级别的模型,基本就脱离普通家用服务器的范畴了。
如果你像我一样没有独立 GPU,只能靠 CPU 推理,特别建议你的服务器内存不低于 16GB。内存不够的时候,系统会用 swap 交换分区来凑,但一旦开始用 swap,推理速度会慢到让人怀疑人生——生成一个字可能要卡好几秒。如果你是在云厂商买的按量付费机器,建议先把内存拉满,跑完再降配。我个人的实践经验是:2 核 4G 的机器跑 3B 级别的小模型还勉强够用;4 核 16G 的机器跑 7B 级别模型就比较舒服了;想要流畅跑 14B 级别模型,建议内存直接上 32G。
磁盘空间也需要提前评估。模型文件本身很大,Ollama 在运行过程中还需要临时空间。我建议在部署之前,先用 df -h 看一下你的根目录和 /root 目录剩余空间。如果你跟我一样喜欢把数据卷放在 /home 或者独立数据盘,那就在挂载的时候指定路径,别默认全堆在系统盘里。跑大模型是长期的事,磁盘规划一开始就要想好。
2.2 Linux 环境与 Docker 安装要点
这里我不做发行版的严格限定,无论是 CentOS、Ubuntu 还是 Debian 系,Docker 的安装方式都大同小异。唯一要注意的是:尽量不要用 Linux 发行版自带的旧版本 Docker 包,我见过太多因为 Docker 版本过老导致各种兼容问题的案例。优先用官方源安装。
以 Ubuntu 为例,一条命令清理旧版本(如果存在的话):
bash复制sudo apt remove docker docker-engine docker.io containerd runc
然后装依赖并添加官方 Docker 仓库:
bash复制sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
这里要注意,国内服务器访问 Docker 官方仓库偶尔会抽风。如果添加仓库这步卡住,可以考虑使用国内镜像源替换,方式是把 download.docker.com 替换成对应的镜像地址。之后更新索引并安装 Docker:
bash复制sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
装好之后,务必把当前用户加进 docker 组,这样执行 docker 命令不用每次加 sudo:
bash复制sudo usermod -aG docker $USER
newgrp docker
验证安装是否成功:
bash复制docker --version
docker compose version
最后检查 Docker 服务是否已经自启:
bash复制sudo systemctl enable docker --now
sudo systemctl status docker
在这阶段我踩过最蠢的坑是:装完 Docker 之后没有重启会话就直接用 docker 命令,结果一直提示权限不足。实际上 newgrp docker 已经切到了新组,但某些终端环境还是要彻底重开一下才生效。
2.3 显卡直通与 CPU 简易方案
如果你有 NVIDIA 显卡,那就值得把 GPU 直通进容器,推理速度比 CPU 快一个数量级不止。想要 GPU 直通,有两个前提:宿主机已经装了 NVIDIA 驱动(用 nvidia-smi 验证),并且装好 NVIDIA Container Toolkit。注意,Docker 默认没法直接访问宿主机的 GPU,必须装这个插件。
bash复制# 在 Ubuntu/Debian 上添加 NVIDIA 官方源
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 update
sudo apt install -y nvidia-container-toolkit
安装完 Toolkit 之后,还要配置 Docker 的 runtime:
bash复制sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
验证的时候,你可以跑一个测试容器:
bash复制docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
如果能看到显卡信息,就说明 GPU 直通没问题了。没有 GPU 的也不用气馁,纯 CPU 跑小模型其实完全可行,后面我会单独讲怎么挑模型。我经常在没 GPU 的测试机上跑 Qwen2.5 3B 这种小模型,配合量化版本,速度虽然不算快,但用来做文本分类、信息抽取这类任务完全够用,关键是还能省下 GPU 的费用。
3. 用 Docker 拉取 Ollama 镜像并启动容器
3.1 镜像拉取与启动命令逐行拆解
在一切准备就绪之后,核心操作其实只有几步。先拉取官方镜像:
bash复制docker pull ollama/ollama
这个就是 Ollama 的官方镜像,它定期的跟着上游版本走。默认拉下来是最新的 latest 标签,如果你想锁定到某个特定版本,可以去 Docker Hub 上看看该镜像的 tags。比如在团队协作环境里,为了统一版本避免"我这是新版、你那还是老版"的尴尬,可以拉一个固定版本:
bash复制docker pull ollama/ollama:0.5.7
然后是启动容器。我常用的部署命令是长这样:
bash复制docker run -d \
--name ollama \
--gpus all \
--restart always \
-v ollama:/root/.ollama \
-p 11434:11434 \
ollama/ollama
我逐行解释一下这些参数的含义,方便你根据自己的情况调整:
-d:后台运行,终端关掉也不会中断。--name ollama:给容器起个名字叫 ollama,后面操作容器都靠这个名字。--gpus all:让容器能使用宿主机所有 GPU。如果你的机器没有 GPU,直接删掉这行。--restart always:设置容器在退出或者服务器重启后自动重新启动。这在大模型服务中非常实用,毕竟你肯定不希望服务器重启一次,还得手动 docker start。-v ollama:/root/.ollama:创建一个名为 ollama 的 Docker 数据卷,挂载到容器内的模型存储目录。这个目录里面就是所有模型文件,做好这个挂载之后,你升级容器或者重装 Docker,模型不会丢失。-p 11434:11434:把容器内部的 11434 端口映射到宿主机的 11434 端口。Ollama 默认监听 11434 端口,这样外部请求就能通过宿主机 IP 访问到服务了。
如果你希望把模型文件直接放在宿主机的某个目录(比如 /data/ollama),可以换成 bind mount 的写法:
bash复制docker run -d \
--name ollama \
--gpus all \
--restart always \
-v /data/ollama:/root/.ollama \
-p 11434:11434 \
ollama/ollama
两种方式的主要区别是:named volume 由 Docker 管理,好处是你可以随时 docker volume inspect ollama 查看详细路径;bind mount 则适合你已经规划好了目录结构、想直接在宿主机上看到模型文件的场景。
启动完成后,可以用 docker ps 看一下容器状态。如果看到 STATUS 列是 Up,说明容器已经正常运行了。再用 docker logs ollama 看看有没有报错信息。
3.2 为什么我把端口暴露限制到本地
对于 11434 这个端口,我强烈建议你在做安全加固的时候认真考虑一下。大模型服务本身没有内置鉴权,只要端口暴露到公网,任何人都可以直接调你的接口,让他们白嫖你的算力甚至读取你的模型。如果只是开发调试,最稳妥的方式是只绑定到本机回环地址:
bash复制docker run -d \
--name ollama \
--gpus all \
--restart always \
-v ollama:/root/.ollama \
-p 127.0.0.1:11434:11434 \
ollama/ollama
这样外部完全无法访问,只能通过你在服务器上运行的其他程序来调用。对于云服务器,还要记得在安全组规则里把 11434 端口限制为只有你自己的 IP 可以访问,或者干脆不对公网开放。我有一次图省事,直接把安全组端口全放开了,结果一个小时内日志里就开始出现大量外部扫描请求——虽然模型跑不了太大响应,但被人反复探测总归不是什么愉快的体验。
3.3 国内环境拉取镜像的常见问题与加速方案
我知道很多人在国内服务器上执行 docker pull ollama/ollama 的时候会遇到卡住或者超时的现象。如果你的服务器不在墙外,确实有可能出现这种情况,这里有几个实用的加速办法。
我测试下来,最有效的方式是配置 Docker 的镜像加速器。在 /etc/docker/daemon.json 中添加镜像源(没有这个文件就创建一个):
json复制{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://dockerproxy.com"
]
}
然后重启 Docker 让配置生效:
bash复制sudo systemctl daemon-reload
sudo systemctl restart docker
配置好后再重新 docker pull ollama/ollama,速度会明显提升。这里我也遇到过镜像源失效的情况,所以在选择加速源时尽量多准备几个备选的,万一哪个挂了还能切换。如果所有加速源都试过还是拉不动,可以试试在公司网络环境、或者有代理条件的机器上先把镜像 docker save 成 tar 包,再传到服务器上 docker load 装载,这种方法虽然土,但在某些极端网络环境下反而最可靠。
4. 模型下载、运行与热切换实操
4.1 手动拉取与运行模型
容器起来之后,接下来就是真正"跑模型"的时候了。正常情况下,你需要先进入容器内部,再去拉取模型:
bash复制docker exec -it ollama ollama pull llama3.1
这个命令会在容器内部执行 ollama pull llama3.1,从模型库下载指定模型。如果你的网络够快,等待条就会刷刷地走;如果卡在某个百分比不动,多半是网络问题,可以用 Ctrl + C 取消重来。
下载完成之后,直接执行:
bash复制docker exec -it ollama ollama run llama3.1
这样就会进入交互式对话界面,你输入什么它回答什么。这是最快验证模型好不好用的方式。不需要额外的客户端,不需要写代码,敲进去就能聊,非常适合刚上手的同学体验一下本地大模型和 ChatGPT 这类在线服务的差别——每次生成都是本地实打实的算力输出。
4.2 打开外网交互的 API 请求创意
不过老实说,很少有人会天天登录服务器用命令行聊天。实际项目里更多是通过 HTTP API 接口来调用模型。Ollama 在容器里暴露了 11434 端口,默认就支持 HTTP 请求。你可以用一个最简单的 curl 命令来测试:
bash复制curl http://localhost:11434/api/generate -d '{
"model": "llama3.1",
"prompt": "用一句话介绍你自己"
}'
这样就能以 API 的形式驱动模型推理了。如果你在用 Python、Node.js 这类后端语言开发应用,直接用官方的 ollama python 库或者 requests 往这个接口发 POST 请求即可,不需要额外安装其他依赖。对于我来说,这个 API 的能力才是关键——把它接进自动化的脚本里,无论是做本地文档总结、定时生成报表描述,还是做一个自定义的聊天机器人,都比在终端手动敲要实用得多。
4.3 让容器自动拉取模型的技巧
很多朋友第一次接触时容易犯迷糊:明明容器已经起来了,但是 docker exec 进去之后,发现 ollama pull 还要手动敲那一长串命令。其实这里有个更优雅的做法,不用进容器、也不用多敲命令。Ollama 提供了一个 环境变量预加载 的方式:在容器启动命令中加上 OLLAMA_MODELS 和一个模型列表,容器起来之后就会自动拉取指定模型。
在 docker run 的时候,你可以加上:
bash复制docker run -d \
--name ollama \
--gpus all \
--restart always \
-e OLLAMA_MODELS="llama3.1,qwen2.5:7b" \
-v ollama:/root/.ollama \
-p 11434:11434 \
ollama/ollama
不过实测中这个变量并不会像想象中那样去自动拉取,它只是指定默认加载的模型路径。真正我常用的自动拉取方式,是在启动容器之后用一个循环脚本去执行:
bash复制docker exec -d ollama ollama pull llama3.1
docker exec -d ollama ollama pull qwen2.5:7b
这样启动完毕之后,后台自动把需要的模型下载好,你甚至不需要盯着终端。之后调用的时候模型会在首次加载时稍微等一下,之后就顺畅了。
4.4 如何挑选适合自己的模型
这部分是纯经验谈,可以帮你少浪费不少时间。我按使用场景和硬件条件把常见模型粗略分一下类:
如果你想在低配机器(2 核 4G 或 4 核 8G)上跑,建议选 0.5B ~ 3B 级别的模型。之前提到过的 Qwen2.5 3B 就非常合适,特别擅长中文场景。如果你主要处理英文,TinyLlama 或 Llama 3.2 3B 也可以作为备选。这类小模型生成速度快,但回答质量和上下文理解能力相对有限,作为个人助手用我觉得刚好。
如果内存有 16G,可以上 7B ~ 8B 这个档位。Llama 3.1 8B、Qwen2.5 7B、Gemma 2 9B 是当下比较热门的几个选择。它们的中文能力、逻辑推理能力和代码生成能力已经在很多任务上非常能打了。哪怕没有 GPU,CPU 推理也就是慢一点,但结果质量完全在线。这个档位是我日常用得最多的。
如果内存有 32G 甚至更高,并且不担心磁盘占用,可以尝试 14B ~ 32B 级别。比如 Qwen2.5 14B / 32B,以及 Llama 3.1 70B 的量化版。参数越大,逻辑能力越强,但 CPU 推理速度会让你等到怀疑人生。没有 GPU 的话,我一般不推荐上这个档位,除非你只是做离线批处理任务,对时间不敏感。
这里还涉及一个上下文长度的取舍。默认情况下 Ollama 给的上下文窗口较短,如果处理长文档会觉得模型"失忆"。你可以在运行命令中指定参数来调整上下文长度:
bash复制docker exec -it ollama ollama run qwen2.5:7b --num-ctx 8192
但要注意,上下文越长,内存消耗和推理耗时都会显著上升。如果你是 16G 内存跑 7B 模型,建议保持 4096 或以下上下文,否则内存很容易被吃满,甚至触发 OOM 导致进程被杀。
5. 让 Docker 和 Ollama 深度融合的高阶配置
5.1 修改模型下载路径与并发参数
默认情况下,Ollama 的模型下载临时文件也放在 /root/.ollama 里。如果你希望临时目录避开系统盘,或者想同时跑多个推理任务,就需要用到环境变量。在启动容器时,可以加多个 -e 参数:
bash复制docker run -d \
--name ollama \
--gpus all \
--restart always \
-e OLLAMA_NUM_PARALLEL=4 \
-e OLLAMA_MAX_LOADED_MODELS=2 \
-e OLLAMA_KEEP_ALIVE=5m \
-v /data/ollama:/root/.ollama \
-p 11434:11434 \
ollama/ollama
这几个环境变量的作用是:
OLLAMA_NUM_PARALLEL:允许同时处理多少个并发的请求。如果只有你自己在用,默认 1 就够;要是多人同时访问,可以适当调高到 4,但也要看显存或内存是否能扛得住。OLLAMA_MAX_LOADED_MODELS:最多同时加载几个模型到内存中。同时加载多个大模型会占掉大量内存,默认 1 是最保险的。OLLAMA_KEEP_ALIVE:模型加载后保持驻留内存的时间。默认是 5 分钟。如果你的调用非常频繁,设置更长的时间能避免反复加载造成的延迟;如果希望节省内存,就把它设小一点甚至设为 0。
我有一个个人体会:刚开始玩的时候,总觉得并发越大越好,于是把并发参数拉到 8,结果一压测内存直接打满,容器开始崩溃重启。后来才明白,大模型推理是典型的内存密集 + 计算密集任务,并发不是越高越好,一定要跟硬件匹配。稳妥的做法是先保持默认,用一段真实请求观察内存占用和响应时间,再慢慢往上试。
5.2 GPU 显存不够时的量化模型选择
如果你有显卡但显存不大(比如 8G),直接跑 7B 模型可能会比较吃力,甚至爆显存。这个场景下,量化模型是你的救星。量化可以简单理解为把模型的参数从高精度压缩到低精度(比如从 16bit 降到 4bit),换来的是显存占用大幅降低,速度更快,代价是精度有轻微损失。但对于绝大多数实际应用来说,损失的那一点质量几乎无感。
Ollama 提供了一个很贴心的量化模型管理功能。你可以用以下命令查看某个模型有哪些量化版本可选:
bash复制docker exec -it ollama ollama show llama3.1 --modelfile
或者直接在模型名后面加后缀来指定量化级别:
bash复制docker exec -it ollama ollama pull llama3.1:8b-instruct-q4_K_M
在这里,q4_K_M 就代表 4-bit 量化(K_M 是量化策略)。8G 显存跑 8B 模型的 q4 量化版通常是没问题的。如果你没指定量化级别,Ollama 默认也会拉取官方推荐的量化版本,但显存紧张时显式指定会让你更心里有数。
5.3 使用 Docker Compose 管理自己的 Ollama 环境
当配置项变多之后,一串超长的 docker run 命令维护起来就非常痛苦了。这一阶段我更推荐你把配置写进 docker-compose.yml 文件里,这样既清晰又容易改,别人看你的文件也能一眼看懂整个环境长什么样。
我日常用的一份 docker-compose.yml 长这样:
yaml复制services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: always
ports:
- "127.0.0.1:11434:11434"
volumes:
- /data/ollama:/root/.ollama
environment:
- OLLAMA_NUM_PARALLEL=2
- OLLAMA_KEEP_ALIVE=10m
deploy:
resources:
limits:
memory: 32G
然后启动它:
bash复制docker compose up -d
要注意的是 Compose 文件里的 deploy.resources.limits.memory 并不仅仅是大模型配置,它实际上会限制容器最多能用多少内存。这个限制对于防止 OOM 把宿主机拖垮非常有效。有一次我在一台共享服务器上跑大模型,忘了加内存限制,结果模型加载时直接把整台机器内存吃满,其他服务全部跟着遭殃。从那以后,我给所有部署大模型的容器都加了内存上限和 swap 限制。
5.4 配合 Open WebUI 搭建可视化界面
服务器上的模型 API 已经能跑了,但很多朋友还是习惯用网页来聊。这时候推荐一个非常好用的开源项目:Open WebUI(就是原来的 Ollama WebUI)。它能连到 Ollama 的服务,给你一个类似 ChatGPT 的浏览器界面。
在 docker-compose.yml 里加上 Open WebUI 服务:
yaml复制services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: always
ports:
- "127.0.0.1:11434:11434"
volumes:
- /data/ollama:/root/.ollama
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: always
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
volumes:
- /data/open-webui:/app/backend/data
注意这里 OLLAMA_BASE_URL 填的是 http://ollama:11434,这是 Docker Compose 内部网络中的服务名。这样做的好处是,Open WebUI 和 Ollama 之间走的是容器内网,流量不经过宿主机,既快又安全。启动之后,浏览器打开 http://服务器IP:3000,注册一个管理员账号,就能在网页上和你的本地模型对话了。整套体验下来,跟用云端的聊天工具非常接近,但数据完全掌握在自己手里,用来跑一些内部的敏感数据也安心很多。
6. 运维实践中的常见坑与修复手记
6.1 容器启动失败日志排查
我遇到过不少次刚启动容器,docker ps 却发现它一直没有起来的情况。这个时候不要慌,第一步永远是看日志:
bash复制docker logs ollama
如果是 Error response from daemon: could not select device driver "nvidia" with capabilities: [[gpu]],说明 --gpus all 参数触发了 GPU 直通,但宿主机没有正确安装 NVIDIA Container Toolkit,或者 Docker 没有被配置为使用 nvidia runtime。回到 2.3 节,把 nvidia-ctk runtime configure 和重启 Docker 的步骤走一遍就能解决。
如果日志里出现端口被占用相关的字样,可以用 netstat -tlnp | grep 11434 查一下是不是有另一个 Ollama 或者别的进程占着这个端口。我遇到过一次是之前本地直接装的 Ollama 还没卸干净,systemd 服务把 11434 端口占住了,跟 Docker 抢端口抢得不可开交。把旧服务停掉,再启动容器就好了。
6.2 模型下载中断的处理思路
模型动辄几个 GB,下载过程中断是家常便饭。Ollama 支持断点续传,你不需要从头再来,只需重新执行一遍 pull 命令,它会从断点接着下。如果反复在一个百分比卡住,可能是网络波动太频繁,建议临时换网络环境,或者把代理关了试一下。
还有一个我经常忽略的问题:磁盘空间不足。模型下载是边下边写入的,如果 /root/.ollama 所在分区空间耗尽,下载过程会直接失败。遇到下载进度停在 99% 然后报错的情况,先看看是不是磁盘满了:
bash复制df -h
如果是空间不足,立刻清理磁盘或者把挂载目录换到空间更大的盘。这也是为什么我反复强调,部署前最好先用 df -h 把空间情况看清楚。
6.3 模型加载后响应慢得不像话
模型能跑起来,但速度让你怀疑是不是服务器中病毒了,这种体验我太熟悉了。绝大多数情况是内存不够导致系统在用 swap(也就是把硬盘当作内存用)。你可以用 free -h 看一眼:
bash复制free -h
如果 swap 一栏显示用了不少,那内存确实不够了。CPU 推理本身就慢,再加上 swap 的磁盘 IO,速度自然惨不忍睹。这时候要么换一个更小的模型,要么换一个量化程度更高的版本。另外,我建议在跑模型的时候,用 top 或者 htop 实时观察内存和 CPU 的占用情况,一旦发现内存即将打满,就该考虑缩减上下文长度或者减少并发数了。
6.4 容器重启后模型消失的假象
有朋友跟我反馈,自己明明拉好了模型,但容器重启之后 ollama list 一看,模型没了。这个问题的根源基本都在数据卷上。用 docker inspect ollama 查看一下挂载信息:
bash复制docker inspect ollama | grep -A 5 Mounts
确认一下 Source 是不是指向一个 Docker named volume 或者你期望的宿主机目录。如果你用 --rm 参数启动容器,容器停止后会被直接删除,它关联的匿名卷也可能一起被清理。所以,要么固定一个具名 volume,要么像我这样直接指定绝对路径做 bind mount。模型文件下载一次真的很耗时,别因为数据卷配置疏忽导致推倒重来。
6.5 网络策略与防火墙的安全反思
最后再啰嗦一句安全问题。服务器只要暴露在公网,就会源源不断地收到各种扫描和探测。Ollama 本身没有身份认证机制,所以默认的端口绑定范围越严格越好。最稳妥的情况是把 Ollama 的端口只在容器内网或者 127.0.0.1 上暴露,然后通过 Open WebUI 或者你在宿主机上的 Nginx 反向代理来对外提供服务。如果你一定要让 Ollama 直接被外网访问,至少要在安全组、防火墙层面做好源 IP 白名单。这不是危言耸听,我自己就在一台公网服务器上,短短几小时看到过大量针对常见端口的扫描记录,安全这种事情,做到前面永远比事后补救省心。
在实际部署和长期运行的过程中,我最大的体会是:Docker 加 Ollama 这套组合,真正的优势不在于"能跑起来",而在于"出了问题能快速恢复"。容器丢了就重新起一个,模型文件在数据卷里安然无恙;版本想升级就换个镜像标签,几分钟就能切换。整套环境的运维成本相比传统裸机安装降低了很多,至少我不再需要为了某个依赖库版本冲突而折腾一整个下午。如果你也打算在自己服务器上搭一个本地大模型环境,完全可以按照这篇文章的操作顺序来一遍,遇到问题再对照最后一节的排查思路,相信你也能顺利跑起来自己的私有模型。
