首页 / 资讯中心 / 文章详情

Docker+DeepSeek Harness本地部署AI Agent平台实践指南

Docker+DeepSeek Harness本地部署AI Agent平台实践指南 ★ FEATURED ARTICLE
1. 为什么我最终选了 Docker DeepSeek Harness 这条路先交代一个背景。我在本地有台性能还说得过去的工作站平时跑点模型推理、处理数据都靠它。最近团队里有个需求要把大模型能力做成一个局域网内可用的服务让前端、测试甚至产品同事都能直接对话调用而不是每个人各自摆弄本地的 Python 脚本。一开始我也想过直接装个裸的推理框架跑模型但很快发现不值得。我要的不是“一个人能跑通”而是“所有人点开就能用”。这就牵扯到环境隔离、依赖版本、启动脚本、端口管理、权限控制一堆事。手搓环境一人一套配置版本一多就乱排查起来非常头疼。后来我决定上 Docker配合 DeepSeek Harness 这套封装好的框架。简单说Harness 本身就是围绕大模型部署与 Agent 应用做的一套服务化方案Docker 则是把它钉在一个干净、可复现的运行环境里。两者结合我能把模型服务、API 网关、Agent 调度都给端起来局域网内任何设备通过浏览器或接口就能访问。这篇内容就是把我从零搭建到跑通整个流程的记录写下来。包括我为什么这么选、目录怎么规划、compose 文件怎么写、首次启动会遇到什么坑、局域网访问怎么配置、还有 Agent 功能怎么用。如果你也想在本地或公司内网搞一个 AI Agent 平台这篇文章应该能帮你省下不少试错时间。2. 核心思路拆解Docker Compose 还是裸跑2.1 Docker 解决的核心矛盾裸跑大模型服务的典型烦恼是环境一换寸步难行。你今天在本机装好了 Python 依赖明天换台机器或者别人接手大概率要重新折腾一遍。明面上的报错还好处理最怕的是 CUDA 版本和 PyTorch 编译参数的隐性不兼容有时能卡你大半天。Docker 的思路是把整个运行时快照下来。镜像里面自带 Python 环境、系统库、甚至 CUDA 运行时不管跑到哪台机器上行为都一致。你不需要知道部署机具体装了什么系统、改过哪些全局配置你只需要确保 Docker 能跑起来。而且我这次还要搭一个平台不是跑一个进程就完事。平台意味着有前端界面、有后端 API、有调度服务可能还有数据库。裸跑这些组件的维护成本会指数级上升但用 Compose 把它们编排在一起一条命令起来、一条命令停掉谁依赖谁一目了然。2.2 为什么选择 DeepSeek Harness 而不是其他方案选择 Harness 这件事我说一下自己的考量。市面上有不少开源框架可以把模型包装成 API也有很多 Agent 框架可以做工具调用和任务编排。但 Harness 比较特别的地方在于它把两者做了整合——模型推理、服务暴露、Agent 能力是一条链路而不是两个独立系统拼起来。这对我这种在局域网里搭平台的人来说很重要。我不希望前端同事去调模型推理 API后端同事再去调另一套 Agent 框架中间还要自己写胶水代码处理协议转换。Harness 直接给我一个统一的入口模型和 Agent 是同一套体系。另外它对 DeepSeek 系列模型的支持比较原生。DeepSeek 的模型文件结构、词表、上下文处理方式Harness 都有现成的适配。我不用自己写预处理逻辑也不用担心模型版本升级后 API 不兼容。选择这个组合更多是图省心和稳定。2.3 Compose 编排的模块规划整体规划如图我不用画图直接说模块。整个平台分三层最底层是模型推理服务中间是 Harness 的 Agent 调度和 API 服务最上层是给用户访问的 Web 界面。我用一个 compose 文件同时管理这几个容器。模块划分上做得很干净。模型推理服务单独跑一个容器这样如果我要换模型或者调参数只需要动这个容器不碰上层服务。API 服务是另一个容器负责对外提供统一接口。Web 界面也是容器化的好处是升级前端不用重装后端环境。数据库我建议用单独的容器跑持久化存储记录对话历史、Agent 任务状态这些数据。这样就算应用容器重新创建数据也不会丢相当于把状态和应用分离后续维护舒坦很多。3. 部署前的准备工作与目录规划3.1 硬件要求和镜像选择先说实话跑 DeepSeek 模型不是随便找台机器就行。模型参数量在那摆着推理需要的显存和内存都有门槛。我这边用的是单张消费级显卡显存 24G选的是量化后的中等大小模型跑起来比较流畅上下文长度也够用。如果你手头显存只有 8G 到 12G也不是不能玩但要降低预期——选更小的量化版本并且控制上下文长度。好消息是 Harness 对量化模型的支持做得比较完善常见的量化格式都能直接加载不需要额外转换。镜像方面关键是要确认版本匹配。模型推理服务的镜像要和模型文件的格式兼容API 服务的镜像要和推理服务的接口协议兼容。我最开始没仔细看版本对应关系导致 API 服务连不上推理服务排查了半天才发现是版本不匹配。这个写在前面提醒大家先花十分钟看版本说明。3.2 目录结构设计与持久化思考我在正式部署之前先把目录结构定了。Docker 容器是易失的删除重建太常见了如果模型文件、日志、数据库全放在容器里一次容器重建全没了。所以持久化目录必须提前规划好。我采用的是这种方式项目根目录下建 data、models、logs 三个目录。models 下面放模型文件data 里放数据库和对话记录logs 用于收集各个容器的输出日志。然后通过 bind mount 的方式挂载到容器内。这样做的好处是我升级版本或者重新创建容器的时候数据和模型文件完全不受影响。如果哪天容器跑挂了把 bind mount 的目录备份出来换台机器重新部署一样能恢复原来的状态。这种部署方式在正式环境里几乎是标配所以从一开始就按这个标准来省得后面返工。3.3 端口规划与网络模式端口方面我建议别直接用默认的随机端口自己规划一套避免和局域网内其他服务冲突。我分配是这样的Web 界面用 8888 端口API 服务用 8899 端口。这两个端口都要映射到宿主机方便局域网其他设备访问。容器之间内部通信用 8000 和 9000不映射到宿主机只靠 Docker 内部网络互通。网络模式我用的是 Compose 默认的 bridge 网络。容器之间通过服务名互相访问这样即使 IP 变化也不影响配置。需要注意的是如果跑的是多机分布式那就得换 overlay 网络但局域网单机场景用不到那么复杂。提示端口映射是很容易犯迷糊的地方。容器内的 8000 端口和宿主机的 8000 端口不是一回事compose 文件里要写成宿主机端口:容器内部端口写反了会导致配置错误。4. 实操过程编写 Compose 文件并启动服务4.1 Compose 文件的核心片段我先写一版相对通用的 compose 配置标注关键位置然后逐行解释。version: 3.8 services: llm-server: image: harness-llm:latest container_name: harness-llm ports: - 8900:8900 volumes: - ./models:/models - ./logs:/logs environment: - MODEL_PATH/models/DeepSeek-Q4.gguf - CONTEXT_LENGTH8192 - GPU_LAYERS35 deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] restart: unless-stopped harness-api: image: deepseek-harness-api:latest container_name: harness-api depends_on: - llm-server ports: - 8899:8000 volumes: - ./data:/data - ./logs:/app/logs environment: - LLM_SERVER_URLhttp://llm-server:8900 - AGENT_LOG_PATH/app/logs restart: unless-stopped harness-web: image: deepseek-harness-web:latest container_name: harness-web depends_on: - harness-api ports: - 8888:80 environment: - API_BASE_URLhttp://harness-api:8000 restart: unless-stopped这里面有几个地方值得展开说。depends_on的作用是控制启动顺序。容器不是并行启动的harness-api会等llm-server起来之后再启动前端界面则会等 API 就绪后再起来。不过要注意depends_on只保证启动顺序不保证服务内部完全就绪所以后面还要配合健康检查或者简单的等待机制。GPU_LAYERS这个参数值得单独说。DeepSeek 模型层数比较多把所有层都放在显存里效果最好但显存不够时要把一部分层放到内存计算。这个参数就是控制放在 GPU 的层数。我设 35 层是因为实测下来这个值刚好能塞进显存同时速度和效果都在可接受范围。不同的模型和显卡型号需要自己试一次不行就多试几次。restart: unless-stopped也很重要。意味着宿主机重启之后容器会自动跟着起来不用再手动启动。对局域网服务来说这个设置基本等于无人值守很省心。4.2 首次启动的完整流程与实测记录配置写好之后首次启动有几个动作要注意。第一步是检查镜像是否已经拉到本地没拉到就手动拉避免启动时才去下载导致超时或失败。我用docker pull把两个核心镜像提前准备好。第二步是确认模型文件确实放在了指定目录。因为容器启动后就从这个路径读模型文件不完整或者路径不对容器会直接反复崩溃。我的做法是启动前先跑一次ls -lh检查文件大小确认和预期一致。第三步才是真正的docker compose up -d。加-d参数是后台运行这样终端退出了服务也不会停。启动后不要急着看界面先看日志。docker compose up -d docker compose logs -f日志输出会告诉你当前走到哪一步。正常情况下先是模型加载日志能看到一些加载进度的信息然后是 API 服务注册成功的提示最后是 Web 服务监听的地址信息。我第一次启动的时候卡在模型加载这一步很久。原因是模型文件比较大磁盘读取速度一般而且首次加载还需要做一些格式解析所以耗时比较长。你以为卡死了其实多等一会儿就好了。等待期间可以做一次快速验证——换一个终端检查容器状态是否健康docker compose ps看到所有容器状态都是Up基本就没问题。然后再用curl试一下 API 端口是否响应curl http://localhost:8899/health返回正常状态码和 JSON 信息说明整个链路已经通了。4.3 局域网访问的两处关键配置容器内服务跑通了不代表局域网就能访问这里还有两件事必须做对。第一件事是宿主机防火墙要放行对应端口。这个步骤容易被忽略尤其是习惯了本机调试的人没意识到宿主机防火墙会拦住外部设备的流量。我这边把 8888 和 8899 两个端口加进放行列表局域网内其他设备才访问得到。第二件事是配置文件的监听地址。有的服务默认只绑定127.0.0.1只接受本地回环访问外部设备就算防火墙放行了也连不上。需要在环境变量或配置里改成本虚拟机的局域网 IP或者直接监听0.0.0.0。我用的是0.0.0.0简单粗暴可以接受所有网卡的访问请求。改完之后局域网内另一台设备打开浏览器输入http://宿主机的局域网IP:8888就能看到前端界面了。手机在同一局域网下也可以直接访问实测下来速度取决于网络环境内网延迟一般都不高。5. 让平台真正跑出“Agent”能力5.1 Agent 的配置思路光能对话还谈不上 Agent 平台。Agent 的核心是让模型能调用工具、执行任务、处理多轮上下文。Harness 在这个层面的设计值得聊一聊。系统里内置了一套 Agent 调度机制你可以为模型配置“工具集合”比如检索本地文档、调用业务 API、查询数据库等。配置完成后用户在对话框里提出的问题系统会自动判断要不要调用工具然后根据工具返回结果组织答案。我在部署过程中踩过最典型的坑是“工具循环”。模型在某个任务上反复调用同一个工具得不到有效进展也一直不退出疯狂消耗算力。原因在模型的能力边界和工具返回结果的表达方式上。解决办法有两个方向一是给工具增加超时时间和最大调用次数限制二是在系统提示词里更明确地告知模型“如果工具返回结果不足就基于现有信息作答”不要强行调用。5.2 多用户与权限隔离的落地局域网平台不只是一个人用所以权限问题不能回避。Harness 的系统里管理员可以创建多个账号每个账号有独立的历史记录和 Agent 配置。这点做得好的是不同用户之间的上下文是隔离的不会出现 A 用户对话突发地被 B 用户的数据污染的情况。我在实际使用时给团队成员分成了三个角色普通用户只能对话和查看自己的历史开发者可以配置工具和调试 Agent管理员负责全局管理。权限控制粒度还算细基本满足一个中小团队的使用需求。如果你只是个人用权限这块不用太操心默认管理员账号直接用即可。但我在类似场景里跑过一阵子建议还是顺手分一下账号免得日志里所有记录都堆在同一个账号下面后期追溯麻烦。5.3 性能调优和参数调整的实战心得说几个我自己试出来的调整方向给不想翻源码的朋友参考。批次大小和并发数。默认配置偏保守适合低配机器。但如果你机器够好把并发数调大一点多人同时使用时体验会好很多不会出现一个人占用推理、其他人全部排队等待的尴尬。上下文长度。这是一个双刃剑。太短模型记不住前文太长显存压力大响应速度变慢。我这边 8192 的长度表现适中日常对话够用Agent 做多步任务也不至于丢失关键状态。如果你的显卡更强可以尝试更长的上下文但响应速度会有下降需要自己权衡。量化精度。Q4 量化是我在效果和资源之间的平衡点。Q8 的效果更好但显存占用几乎翻倍Q2 速度飞快但效果有明显下降。如果你的场景对效果要求高特别是处理专业领域问题时建议至少上到 Q6 级别别在量化上省资源。6. 常见问题与排查技巧实录6.1 问题速查表下面这张表是我在实际部署和使用中真实遇到的全部记录过处理过程。现象可能原因排查方法对策容器反复重启模型路径错误或文件不完整查日志中的加载报错检查 models 目录下文件确认路径与环境变量一致API 服务一直Unhealthy推理服务未就绪或端口内部不通进入 API 容器内 curl 推理服务地址确认服务名和端口正确必要时调整 depends_on局域网无法访问防火墙未放行或监听地址不对在宿主机 curl 本机端口验证放行端口服务监听改为 0.0.0.0首次加载极慢大模型进行格式解析观察日志是否持续输出耐心等待后续启动会因系统缓存加速Agent 反复调用工具工具返回结果表达模糊查看工具输出日志优化工具提示词或增加最大调用次数限制一阵子后响应变慢历史对话太长导致上下文膨胀查看当前上下文长度缩短上下文或手动清理会话历史6.2 两个真正值得分享的排查细节这里单独说两个我花了比较久才搞明白的问题。第一个是“模型加载成功但对话时一直报错”。当时日志显示模型文件加载没问题请求也进来了但一生成回复就报异常。排查到最后是显存分配的问题GPU 上还有其他进程占用了显存新模型在加载的时候显存不够最终触发了底层错误。这个问题的检查方法很简单在宿主机上跑一下显存占用命令看看你是否真的把它当作独占使用。我清理掉后台其他进程之后问题就消失了。显存占用还有一个容易忽视的场景如果你设置了GPU_LAYERS为全部层数模型加载就需要一次性分配一大块显存这时候哪怕只占用了一小块也会导致后续请求失败。第二个是前端界面正常但 API 调用报 CORS 错误。这个问题只出现在直接调用 API 的场景。原因是前端容器和 API 服务的跨域配置默认是关闭的。如果只通过前端界面访问不会触发这个问题但如果要写脚本或者接其他系统就必须处理。解决办法是在 AGAIL 服务上允许指定域名的跨域请求否则浏览器会拦截。6.3 备份与升级的实践经验容器化部署最大的好处是升级方便但也有自己的讲究。我在实际维护中总结出几个原则。升级前必须备份数据和模型配置。这里的数据不单指数据库还包括 Harness 的配置文件和工具定义这些是你针对自己环境调过的东西没了就得重新调一遍。我惯用的做法是把整个数据目录打包压缩升级完再对比差异确认无异常再清理旧包。镜像的升级也建议一份新的打标签而不是直接覆盖旧的。旧的镜像留着不占多少空间但回滚时超级有用。我第一次升级的时候就直接覆盖了结果新版本有个兼容性问题想退回旧版本却发现镜像已经被覆盖了只能翻开历史记录重建容器浪费了不少时间。升级完成之后先不要急着通知其他人使用自己跑几个典型场景验证一下。我会先问一个普通对话跑一个带工具的 Agent 任务再确认历史记录没有被重置三个都通过再开放给团队。7. 最后的几条个人体会整个平台搭好之后日常使用体验比预期好很多。局域网内的响应速度非常快不存在调用远程服务时的网络瓶颈数据也完全在自己手里。从运维角度说Docker 化带来的稳定性提升是明显可感知的。以前跑裸程序最怕系统更新或者装别的软件搞坏了依赖库现在容器隔离之后宿主机怎么折腾都不影响平台运行。一个典型的场景是我后来在宿主机上装了其他开发环境平台一点没受影响这在没有容器化之前想都不敢想。还有一点想提醒大家的是大模型能力是一个工具不是万能的。我在给团队用的时候反复强调Agent 在处理可验证、有明确规则的任务时表现很好但在开放式问题上仍然需要人来判断结果。把预期管理好整个平台的实用价值才会真正发挥出来而不是变成一个什么都接不住的玩具。如果你按照这个流程把平台搭起来了剩下的就是多试试不同模型和参数组合找到最适合你硬件和应用场景的配置。这个过程会有不少试错成本但最终的效果一定值得。
阅读完成 · 觉得有帮助?
咨询建站