局域网自建AI Agent平台:Docker部署DeepSeek Harness实战指南

发布时间:2026/10/12 6:58:34
局域网自建AI Agent平台:Docker部署DeepSeek Harness实战指南
1. 为什么要在局域网里自建 AI Agent 平台1.1 从“调用云端 API”到“把模型搬回自己机房”的转变过去一年我身边不少做企业内部工具的朋友都经历过同一个心路历程一开始图省事直接调用公有云的大模型接口几行代码就能跑通对话。但真到了要落地到业务场景里问题就一个接一个冒出来——数据合规部门盯着你问“用户输入的内容到底去了哪里”网络部门告诉你生产环境根本不通外网财务那边看着按 token 计费的账单直皱眉。尤其是当你想把 AI Agent 接入内部知识库、工单系统、代码仓库这些敏感数据源时把数据往外发这件事本身就很难过审。于是“局域网自建”这条路就被越来越多团队重新捡了起来。所谓局域网自建说白了就是把模型推理服务、Agent 编排框架、向量库这些组件全部部署在自己能掌控的内网机器上外部网络完全隔离数据不出机房。这样做的好处很直接数据流向完全可控没有按量计费的焦虑延迟也稳定得多——毕竟走的是内网千兆甚至万兆比绕一圈公网快得多。但自建也有自建的坑。模型权重动辄几十 GB推理框架依赖一堆 CUDA 版本Agent 框架又要 Python 环境、又要各种系统库装完一台机器往往就“污染”了整台服务器的环境。这时候容器化就成了几乎唯一优雅的解法而 Docker 又是其中门槛最低、生态最成熟的选择。标题里提到的“Docker 部署 DeepSeek Harness”本质上就是把这套“模型 Agent 编排 内网服务”的组合拳用一个可复现的容器方案打包起来让运维和开发都能省心。1.2 这套方案到底解决了谁的痛点我把这套方案的价值拆成三类人来理解这样你对号入座会更清楚。第一类是企业内部的技术团队。他们需要给业务部门提供一个“能问内部文档、能查内部数据”的智能助手但又不允许数据外流。局域网部署 Docker 化意味着他们可以在一台内网服务器上把整套东西跑起来业务同事通过浏览器访问内网地址就能用IT 部门也不用担心合规问题。第二类是对成本敏感的独立开发者或小团队。公有云 API 用起来爽但量一大账单就吓人。如果手上正好有一台带显卡的机器哪怕是消费级的把它利用起来跑本地模型长期看成本低得多。Docker 方案让环境搭建从“折腾两天”压缩到“半小时搞定”。第三类是做技术预研和 Demo 的人。他们需要在没有外网、或者网络受限的环境里快速搭一个能演示的 AI Agent验证产品思路。容器化方案最大的好处就是“一次打包到处运行”换台机器照样能起来不用重新配环境。需要说明的是标题里的“DeepSeek Harness”我理解为一种把 DeepSeek 系列模型与 Agent 编排能力封装在一起的运行框架或脚手架。由于原始描述比较零散下面涉及的具体组件选型、参数配置我会基于“一个合格从业者在局域网自建 AI Agent 平台时最可能采用的合理方案”来补全并在关键处标注这是常见实践而非唯一答案。1.3 阅读前你需要具备的基础这篇内容不是“点一下就能用”的傻瓜教程它更适合有一定 Linux 和 Docker 基础的人。你至少需要能看懂docker run命令、知道什么是端口映射、能通过 SSH 登录服务器。如果你还会一点 Python 和 YAML 配置那读起来会更顺。如果你是完全的新手我建议先补两个基础一是 Docker 的基本概念镜像、容器、卷、网络二是大模型推理的基本流程模型加载、显存占用、量化。这两块搞明白了后面的内容就不会觉得云里雾里。2. 整体架构设计与组件选型思路2.1 一套典型的局域网 AI Agent 平台长什么样在动手之前先把架构想清楚比上来就敲命令重要得多。我见过太多人一上来就docker run结果跑起来发现端口冲突、显存不够、模型加载失败回头返工的时间比规划的时间还长。一套完整的局域网 AI Agent 平台通常包含这么几层模型推理层负责加载 DeepSeek 模型权重对外提供推理接口。常见做法是用推理引擎如 vLLM、TGI 或 Ollama把模型跑起来暴露一个兼容 OpenAI 格式的 HTTP 接口。Agent 编排层也就是标题里的 Harness负责把用户输入、工具调用、记忆管理、提示词模板这些东西串起来。它通常是一个 Python 服务通过 HTTP 调用推理层。数据与工具层向量数据库存知识库 embedding、外部工具接口查数据库、调内部 API等。接入层一个 Web UI 或者 API 网关让用户能访问。局域网场景下通常就是一个内网 IP 端口。这四层用 Docker 网络串起来推理层和编排层可以放在同一台机器也可以分开放。如果只有一台带显卡的服务器全部塞一起也行但要注意显存和内存的分配。2.2 为什么选 Docker 而不是裸机或虚拟机这个问题我被问过很多次这里把我的思考过程完整说一下。裸机部署的问题是环境不可复现。你今天在这台机器上装好了 CUDA 12.1 PyTorch 2.1 某个特定版本的推理框架明天换台机器驱动版本不一样可能就跑不起来。而且 Python 的依赖冲突是出了名的Agent 框架要 A 版本的库推理框架要 B 版本装在一起就打架。虚拟机的优势是隔离彻底但代价是资源开销大。GPU 直通到虚拟机里配置起来也麻烦性能还有损耗。对于一台本来就不算富裕的内网服务器来说虚拟机有点重。Docker 恰好卡在中间隔离性够用进程、网络、文件系统都隔离资源开销小共享内核而且 GPU 支持已经相当成熟NVIDIA Container Toolkit。最关键的是Dockerfile 和 docker-compose.yml 本身就是文档别人拿到你的配置能一比一复现出同样的环境。这对团队协作和后续维护太重要了。提示如果你的服务器有多张显卡Docker 可以通过--gpus参数精确指定用哪几张这在多模型共存或者多人共用一台机器时非常有用。2.3 推理引擎选型vLLM、TGI 还是 Ollama这是整个方案里最关键的一个决策直接影响性能和易用性。我把三个主流选项拉出来对比一下。引擎优势劣势适合场景vLLM吞吐量高PagedAttention 显存利用率好支持并发配置相对复杂对显存要求较高多人并发访问的生产环境TGI官方维护部署规范支持多种量化资源占用偏大定制化不如 vLLM 灵活追求稳定、标准化的团队Ollama上手极简模型管理方便自带量化并发能力弱不适合高负载个人开发、小团队、Demo 验证我的建议是如果是个人或者三五人的小团队先用 Ollama 把流程跑通它的ollama pull和ollama run体验非常顺滑几分钟就能看到模型说话。等验证完产品思路需要上生产、要扛并发的时候再换成 vLLM。这个“先跑通再优化”的路径比一上来就啃 vLLM 的配置要省心得多。需要提醒的是DeepSeek 系列模型有不同的参数规模选哪个版本要看你手上的显卡显存。粗略的估算方法是FP16 精度下每 10 亿参数大约需要 2GB 显存再加上 KV Cache 和框架开销。比如一个 7B 的模型FP16 大概要 14GB 显存加上缓存和开销16GB 显存的卡勉强够用如果做 4-bit 量化显存需求能降到三分之一左右。这个计算过程你在选型时一定要自己过一遍别等下载完几十 GB 权重才发现跑不起来。2.4 网络与端口规划局域网部署的隐形坑局域网部署听起来简单但端口规划没做好后面全是麻烦。我踩过的坑包括推理服务端口和编排服务端口撞了、Docker 内部网络和宿主机网络混在一起导致容器互相访问不到、防火墙规则没放行导致内网其他机器访问不了。我的做法是提前画一张端口分配表把每个服务的端口固定下来写进 compose 文件里。比如推理服务用 8000编排服务用 8080Web UI 用 3000向量库用 6333。这样既避免了冲突也方便排查问题——看到某个端口就知道是哪个服务。另外Docker 的网络模式建议用自定义 bridge 网络而不是默认的 bridge。自定义网络里容器之间可以用服务名互相访问不用记 IP配置起来清爽很多。如果确实需要让内网其他机器访问就把端口映射到宿主机然后确认宿主机的防火墙放行了这些端口。3. 核心组件拆解与实操要点3.1 模型推理服务的容器化配置先把推理层搞定这是整个平台的地基。以 Ollama 为例它的容器化部署相对简单但有几个细节不注意就会翻车。首先是 GPU 支持。你得先装好 NVIDIA 驱动和 NVIDIA Container Toolkit然后在docker run时加上--gpus all或者指定具体显卡。如果这一步没做对容器里是看不到 GPU 的模型会退回到 CPU 推理速度慢到无法接受。其次是模型存储。模型权重动辄几十 GB绝对不能放在容器内部——容器一删权重就没了下次还得重新下载。正确做法是用 volume 把宿主机的目录挂载到容器里。比如把宿主机的/data/ollama挂到容器的/root/.ollama这样模型文件持久化在宿主机上容器重建也不影响。第三是端口暴露。Ollama 默认监听 11434 端口你需要把它映射到宿主机比如-p 11434:11434。但要注意如果只在内网用映射到127.0.0.1:11434更安全避免被同网段的其他机器随意访问。一个典型的启动命令大概是这样docker run -d \ --name ollama \ --gpus all \ -p 127.0.0.1:11434:11434 \ -v /data/ollama:/root/.ollama \ --restart unless-stopped \ ollama/ollama--restart unless-stopped这个参数很实用服务器重启后容器会自动起来不用手动干预。生产环境强烈建议加上。3.2 Agent 编排层的依赖与环境隔离编排层是整个平台的“大脑”它要处理用户输入、决定调用哪个工具、管理对话历史、拼接提示词。这部分通常是一个 Python 应用依赖比较多环境隔离尤其重要。我的经验是编排层不要和推理层塞进同一个容器。原因很简单两者的依赖完全不同推理层要 CUDA、要特定版本的推理框架编排层要的是 Web 框架、HTTP 客户端、向量库 SDK。混在一起依赖冲突几乎是必然的。分开两个容器通过 Docker 网络通信各自维护自己的依赖清爽得多。编排层的 Dockerfile 里有几个点要特别注意。一是基础镜像的选择用python:3.11-slim这种精简版能显著减小镜像体积但要注意有些系统库比如编译工具链可能缺失需要按需安装。二是依赖安装的顺序先装变化少的依赖再装变化多的这样能充分利用 Docker 的层缓存加快构建速度。三是把配置项通过环境变量注入不要把密钥、地址硬编码在代码里。注意编排层调用推理层时地址不要写localhost。在容器里localhost指的是容器自己不是宿主机。如果两个容器在同一个自定义网络里直接用服务名比如http://ollama:11434就能访问。3.3 向量库与知识库的持久化如果 Agent 需要“查内部文档”的能力向量库就是必需品。它的作用是把文档切块、向量化、存起来用户提问时做相似度检索把最相关的片段喂给模型。向量库的容器化部署本身不难难的是数据持久化和性能调优。持久化方面和模型权重一样一定要用 volume 挂载到宿主机否则容器一重建索引就没了重新 embedding 一遍可能要几个小时。性能方面向量库对内存比较敏感。如果知识库规模不大几万条以内内存里跑完全没问题。但如果上了百万级就要考虑磁盘索引和内存的平衡。我的建议是先用小规模数据把流程跑通观察内存占用再决定要不要扩容。还有一个容易被忽略的点embedding 模型的选择。向量库本身不产生向量向量是由 embedding 模型生成的。这个模型也要跑起来可以复用推理层的服务也可以单独部署一个小模型。如果复用推理层要注意 embedding 请求和对话请求会争抢资源高并发时可能互相影响。3.4 用 docker-compose 把一切串起来当服务超过两个手敲docker run就开始变得难以维护了。这时候docker-compose.yml就是救星。它把所有的服务、网络、卷、环境变量集中在一个文件里一条docker compose up -d就能全部拉起来。一个典型的 compose 文件结构大概是这样services: ollama: image: ollama/ollama deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] volumes: - /data/ollama:/root/.ollama ports: - 127.0.0.1:11434:11434 networks: - ai-net agent: build: ./agent environment: - LLM_BASE_URLhttp://ollama:11434 - VECTOR_DB_URLhttp://qdrant:6333 ports: - 8080:8080 depends_on: - ollama - qdrant networks: - ai-net qdrant: image: qdrant/qdrant volumes: - /data/qdrant:/qdrant/storage networks: - ai-net networks: ai-net: driver: bridge这里有几个设计考量值得说明。depends_on保证启动顺序但它只保证容器启动不保证服务就绪所以编排层的代码里最好加上重试逻辑。自定义网络ai-net让三个服务能用服务名互相访问。GPU 资源通过deploy.resources声明这是 compose 规范里指定 GPU 的方式。4. 完整部署流程与关键环节实现4.1 环境准备驱动、Docker 与工具链正式动手前把基础环境检查一遍能省掉后面一大堆莫名其妙的报错。第一步是确认显卡驱动。在宿主机上执行nvidia-smi能看到显卡型号、驱动版本、CUDA 版本就说明驱动没问题。如果这条命令报错先去装驱动别往下走。第二步是装 Docker 和 Docker Compose。现在 Docker 官方推荐用docker compose带空格V2 版本而不是老的docker-compose。装完之后用docker --version和docker compose version确认。第三步是装 NVIDIA Container Toolkit。这是让容器能用上 GPU 的关键。装完之后用一条测试命令验证docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi如果这条命令能输出显卡信息说明容器访问 GPU 的链路是通的。如果报错多半是 toolkit 没装好或者 Docker 服务没重启。第四步是规划目录。我习惯在宿主机上建一个/data/ai-platform目录下面分ollama、qdrant、agent几个子目录分别挂载给对应的容器。这样所有持久化数据集中管理备份和迁移都方便。4.2 拉取模型与首次推理验证环境就绪后先把模型拉下来。以 Ollama 为例进入容器执行拉取命令docker exec -it ollama ollama pull deepseek-r1:7b这里模型名称和版本要根据你的实际需求选。7B 版本对显存要求相对友好适合先跑通流程。拉取过程可能要几分钟到几十分钟取决于网络和模型大小。拉完之后直接在容器里做一次推理测试docker exec -it ollama ollama run deepseek-r1:7b 用一句话解释什么是容器如果模型能正常回复说明推理层没问题。这一步很重要它把“模型能不能跑”和“编排层能不能调”两个问题隔离开了。如果这里就失败那问题一定在推理层不用去怀疑编排层。实操心得首次加载模型时显存占用会有一个爬升过程nvidia-smi里能看到显存逐渐被占满。如果显存不够模型加载会失败或者退到 CPU。这时候要么换更小的模型要么用量化版本。别硬扛换模型比调参数快得多。4.3 编排服务的构建与联调推理层通了之后开始搞编排层。假设你已经有了一个 Agent 应用的代码接下来就是把它容器化。Dockerfile 我一般这么写FROM python:3.11-slim WORKDIR /app # 先装系统依赖这层变化少放前面利用缓存 RUN apt-get update apt-get install -y --no-install-recommends \ curl \ rm -rf /var/lib/apt/lists/* # 再装 Python 依赖 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 最后拷代码这层变化最频繁 COPY . . EXPOSE 8080 CMD [python, main.py]这个顺序的核心逻辑是变化越少的层放越前面这样改代码时不用重装依赖构建速度快很多。我见过有人把COPY . .放在最前面结果每次改一行代码都要重装所有依赖构建一次好几分钟效率极低。构建并启动docker compose up -d --build agent启动后看日志docker compose logs -f agent重点看它有没有成功连上推理层和向量库。如果报连接错误先检查服务名对不对、网络通不通。可以在 agent 容器里curl http://ollama:11434测试一下。4.4 内网访问与安全边界设置服务都跑起来后最后一步是让内网用户能访问。这里有个安全边界的问题要想清楚是只让本机访问还是让整个内网访问如果只是自己调试端口映射到127.0.0.1就够了。如果要让内网同事用就得映射到0.0.0.0或者宿主机的内网 IP同时确认防火墙放行。但要注意一旦开放到内网就意味着同网段的任何人都能访问如果 Agent 能查敏感数据这就存在风险。我的做法是加一层简单的认证。可以在编排层前面放一个反向代理比如 Nginx配置基础认证或者在应用层加一个 token 校验。局域网不等于绝对安全该有的边界还是要有。另外如果内网有多个网段要注意路由是否可达。有时候服务起来了但另一个网段的同事访问不了问题往往出在路由或防火墙而不是服务本身。5. 常见问题与排查技巧实录5.1 容器启动失败与显存不足的排查这是最常见的一类问题我把排查思路整理成一张表方便对照。现象可能原因排查方法解决方向容器启动后立即退出命令错误或依赖缺失docker logs 容器名看日志最后几行模型加载失败显存不足nvidia-smi看显存换小模型或量化版容器看不到 GPUtoolkit 未装或未重启跑 GPU 测试命令重装 toolkit 并重启 Docker端口被占用宿主机已有服务占用ss -tlnp | grep 端口换端口或停掉冲突服务容器间访问不通不在同一网络docker network inspect加入同一自定义网络显存不足这个问题特别值得展开说。很多人看到“CUDA out of memory”就慌了其实先别急着换硬件。第一步是确认到底需要多少显存用nvidia-smi观察加载过程中的峰值。第二步是考虑量化4-bit 量化能把显存需求降到原来的三分之一左右对推理质量的影响在可接受范围内。第三步才是考虑换更小的模型或者加卡。5.2 推理速度慢的性能调优推理慢的原因有很多得逐个排除。如果模型跑在 CPU 上那慢是必然的。先确认nvidia-smi里能看到推理进程占用 GPU。如果 GPU 利用率很低说明瓶颈不在 GPU可能在数据加载或者网络传输。如果 GPU 利用率高但速度还是慢可能是模型太大或者 batch 设置不合理。并发场景下适当增大 batch size 能提升吞吐但会增加显存占用和单次延迟需要权衡。还有一个容易被忽略的点是首次推理的“预热”。模型刚加载完第一次推理往往特别慢因为要初始化各种缓存。这是正常现象多跑几次就稳定了。生产环境可以在启动后主动跑一次预热请求避免第一个真实用户等待过久。5.3 数据持久化与备份的注意事项数据丢失是自建平台最痛的坑没有之一。我见过有人辛辛苦苦 embedding 了几万条文档结果容器重建时忘了挂 volume全没了。核心原则就一条所有需要保留的数据都必须挂载到宿主机。模型权重、向量库索引、对话历史、配置文件一个都不能少。备份策略上我建议至少做到两点。一是定期把宿主机的数据目录打包备份到另一块盘或者另一台机器。二是把docker-compose.yml和所有 Dockerfile 纳入版本管理这样即使机器彻底挂了换台机器也能快速重建。提示向量库的备份要注意一致性。如果备份时正好有写入操作可能备份到不完整的数据。稳妥的做法是先停掉写入服务再备份或者用向量库自带的快照功能。5.4 内网访问异常的定位思路内网访问不了问题可能出在四个地方服务本身、容器网络、宿主机防火墙、网络路由。排查要按顺序来从近到远。先在宿主机上curl localhost:端口确认服务本身是活的。然后在同网段另一台机器上curl 宿主机IP:端口确认端口映射和防火墙没问题。如果这一步不通检查防火墙规则和端口绑定地址。如果同网段通了但跨网段不通那就是路由问题得找网络管理员。我踩过的一个坑是端口映射写成了127.0.0.1:8080:8080结果只有宿主机自己能访问内网其他机器全都不行。后来改成0.0.0.0:8080:8080才解决。这个细节在调试阶段很容易忽略因为自己在宿主机上测试一切正常。6. 后续扩展与个人经验分享6.1 从单机到多机的平滑演进一开始用一台机器把所有服务塞一起是最省事的做法。但当用户变多、知识库变大单机迟早会扛不住。这时候可以考虑把推理层单独拆到一台带显卡的机器编排层和向量库留在另一台。Docker 的好处在这里体现得很明显拆分时只需要改 compose 文件里的服务地址把http://ollama:11434改成http://内网IP:11434其他代码几乎不用动。这种“配置驱动”的架构让扩展变得平滑很多。再往上走如果推理需求很大可以考虑多台推理机 一个负载均衡。但这已经超出“轻松搭建”的范畴了属于生产级集群的领域需要更系统的规划。6.2 我踩过的几个真实坑说几个我印象最深的教训都是文档里不会写、只有自己踩过才知道的。第一个是镜像体积。一开始我用python:3.11完整版做基础镜像构建出来的镜像好几个 GB推送到内网镜像仓库慢得要命。后来换成slim版体积直接砍半。再后来把 pip 缓存清理掉又小了一圈。镜像体积这件事在局域网环境里尤其重要因为内网带宽往往不如公网。第二个是时区问题。容器默认是 UTC 时间日志里的时间戳和本地差好几个小时排查问题时特别容易看错。解决办法是在 Dockerfile 里设置TZAsia/Shanghai或者在 compose 里注入环境变量。这个小细节不注意排查问题时能把你绕晕。第三个是日志膨胀。容器跑久了日志文件能把磁盘占满。一定要配置日志轮转在 compose 里加上logging配置限制单个日志文件大小和保留数量。这个坑我是被磁盘告警叫醒的半夜爬起来清日志的经历实在不想再来一次。6.3 给不同阶段读者的建议如果你是刚接触这块的新手我的建议是先用 Ollama 把“模型能跑、能对话”这件事跑通别一上来就追求 vLLM 的高性能。跑通之后再逐步加上 Agent 编排、向量库、Web UI。每一步都验证通过再往下走比一次性全堆上去然后面对一堆报错要高效得多。如果你已经有一定基础正在为团队搭建平台那重点应该放在可维护性和可复现性上。compose 文件、Dockerfile、配置项全部纳入版本管理写清楚每个参数为什么这么设。这样即使你休假了同事也能照着文档把环境重建起来。如果你是在做技术预研需要快速验证想法那就怎么快怎么来。用现成的镜像用最小的模型先把产品逻辑跑通。等思路验证了再考虑工程化的问题。预研阶段追求的是速度不是完美。这套 Docker 化的局域网 AI Agent 方案我自己在不同项目里反复用过最大的感受就是“确定性”。环境是确定的部署流程是确定的出问题时的排查路径也是确定的。这种确定性在自建平台这件事上比任何性能数字都让人安心。