资讯动态

Docker Compose 部署 DeepSeek Agent:局域网私有化 AI 平台实战

发布时间:2026/10/14 7:25:15 来源:尧图企业网站定制
最近在给内部环境搭 AI Agent 平台的时候我选了 Docker 部署 DeepSeek Harness 这套组合。所谓 Harness 其实是我对“模型服务 Agent 编排 Web 管理界面”整套容器化方案的内部代号它解决的痛点是团队多人共用同一套 Agent 能力、数据不出内网、模型可以随时换。这篇文章不打算讲虚的直接把我踩过的坑、写过的配置、验证过的方法都摊开来说适合那些想在局域网里快速落地一个 AI Agent 平台的开发者或运维同学参考。1. 为什么要在局域网里部署一套 AI Agent 平台1.1 从“调接口”到“自托管”的转变很多项目一开始都是直接调外部模型 API确实省事但用一段时间就会发现几个绕不开的问题数据要出网敏感信息不放心调用有频率和并发限制团队一多人就排队成本跟着 token 走测试环境随便跑几个任务账单就看懂。尤其当 Agent 要连内部数据库、读内部文档、执行一些自动化操作时把模型推理放在局域网里是更稳妥的选择。DeepSeek 这一类开源权重模型的价值就在这里——模型权重可以下载到本地推理服务跑在自己的机器上。配合 Docker我不用为每个成员都配一套 Python 环境也不用担心某个人把模型版本搞乱。整个 Agent 平台收敛成一组容器有统一的入口、统一的数据存储、统一的日志这对团队协作来说太重要了。Harness 在整个系统里做的是“编排层”的工作用户通过界面创建 Agent给 Agent 配置系统提示词、选择模型、挂载工具Agent 收到任务后决定调用什么工具再通过模型服务完成理解和生成。如果只有模型但缺少这一层本质上你还是在跟“一个纯 Chatbot”对话谈不上 Agent。1.2 Docker 在这套方案里的角色我一开始也犹豫过是不是直接在宿主机上用 Python 虚拟环境 Shell 脚本就行了后来发现维护成本实在太高。模型推理服务依赖一堆 CUDA 库Agent 编排服务需要特定版本的 Python/Node数据库又要单独管理任何一个依赖升级都可能牵连其他组件。用 Docker 以后每个服务变成独立容器彼此通过网络通信坏了一个就单独重启不影响其他服务。Docker Compose 则是这套方案里最划算的编排工具。它不需要像 Kubernetes 那样搭建一整套控制平面一条docker compose up -d就能把模型服务、Agent 服务、数据库、缓存全部拉起。对于单机或少量机器组成的局域网环境Compose 的功能边界刚好够用。方案优点缺点手动脚本直观、灵活依赖冲突多、回滚困难Docker Compose一键编排、可复现、易回滚需要理解容器网络和数据卷Kubernetes弹性强、适合大规模部署和维护成本高小团队会淹没在 YAML 里我选择 Compose 的另一个原因是后续升级特别方便。之前模型推理服务从 CPU 版本切到 GPU 支持我只需要改 compose 文件里的设备参数和镜像标签然后docker compose up -d重建相关容器整个过程十分钟内搞定宿主机上没有任何残留依赖。2. 部署前的准备硬件、软件与整体架构2.1 硬件最低要求与推荐配置先想清楚你要跑多大的模型再决定硬件。DeepSeek 开源模型有不同参数规模的版本量化之后体积差异很大。我的经验是如果只是给三五个人做内部工具测试一个 7B 量级的量化模型配合 16GB 内存也能跑起来但要给到十几个人同时用还是建议上 GPU 并把内存提到 32GB 以上。组件最低要求推荐配置CPU8 核16 核及以上内存16GB跑 7B 量化会比较吃力32GB 或 64GBGPU可选显存 12GB 及以上磁盘20GB 可用SSD 预留 100GB用于模型和日志网络千兆局域网千兆局域网我实际测试下来纯 CPU 跑 7B 模型单轮对话可能要等十几秒但如果任务只是批量处理文档摘要吞吐量还能接受。GPU 的作用主要是把单次推理延迟压到一两秒以内Agent 在做多轮工具调用时体感差距会非常明显。还有一个容易忽略的点容器里的共享内存大小。模型推理服务有时会用到/dev/shm做缓存默认 64MB 可能不够我会在 compose 文件里给模型服务加上shm_size: 2gb避免一些奇怪的运行时崩溃。2.2 软件环境与端口规划宿主机我推荐 LinuxDebian 或 Ubuntu 都行。需要安装 Docker Engine 和 Docker Compose 插件版本不要太老因为新版 compose 支持 GPU 资源声明和更完善的健康检查。Windows 和 macOS 也能跑但文件挂载性能和网络模式会有差异生产环境不建议。端口规划上我习惯让 Web 界面、Agent API、模型推理 API 分别占用不同端口数据库和缓存只走容器内部网络不绑定到宿主机端口。这样最外层只需要暴露两个端口攻击面小很多。服务默认端口绑定方式Web UI8000宿主机 0.0.0.0:8000Agent Core API8080宿主机 0.0.0.0:8080模型推理 API11434宿主机 127.0.0.1:11434 或内部网络PostgreSQL5432仅容器内部网络Redis6379仅容器内部网络端口规划最怕的是一套服务里好几个子服务都默认监听 80 端口然后互相冲突。把权限边界想清楚后续加 Nginx 反向代理或者改防火墙规则都会更容易。2.3 整体架构拆解整个平台本质上是一条请求链路。用户打开 Web UI 后输入任务浏览器把任务交给 Agent Core。Agent Core 负责理解任务、拆解步骤、调用工具并在需要语言理解或生成时请求模型推理服务。PostgreSQL 保存用户、Agent 配置、会话记录Redis 用来做缓存和轻量级任务队列。如果还要做知识库问答我会在架构里加一个向量数据库比如 Qdrant 或类似组件用来存文档切块后的向量。这一步不是必须的但一旦加上Agent 就能基于内部文档回答而不是只能靠模型本身的记忆。Harness 的价值就是把模型、工具、记忆这三块拼起来。我做一个生活化的类比Agent Core 像是项目负责人模型是随叫随到的专家PostgreSQL 是档案室Redis 是白板工具集是团队手里的工具箱。Docker Compose 则像是一个标准化的办公室布局所有东西摆到固定位置谁要用直接去拿。3. 用 Docker Compose 编排核心服务3.1 服务清单与镜像选择先确定需要哪些镜像。模型服务我用的是 ollama 镜像因为它支持把 DeepSeek 模型一键拉取并暴露 HTTP API对容器环境很友好。Agent Core 和 Web UI 我是从 Dockerfile 构建出来的因为后面要集成自定义工具和插件官方镜像往往满足不了需求。数据库和缓存则直接用官方 alpine 版本体积小启动快。服务镜像/构建来源说明model-service本地推理服务镜像加载 DeepSeek 模型并暴露 APIagent-core自定义 Dockerfile 构建提供 Agent 编排 APIagent-web自定义 Dockerfile 构建浏览器管理界面postgrespostgres:16-alpine存储业务数据redisredis:7-alpine缓存与任务队列镜像尽量锁定具体版本号不要用 latest。之前我就吃过亏某天重建容器时 latest 变了模型服务启动方式也变了导致线上姑且能跑但监控告警一堆。锁定版本之后至少能保证“昨天能跑今天也能跑”。3.2 compose 文件关键配置解析下面是一份我经过几轮修补后的核心配置去掉了敏感信息只保留结构。你不需要一字不差地抄重点是理解每个服务为什么这么配。services: model-service: image: ollama/ollama:0.1.48 container_name: harness-model shm_size: 2gb ports: - 11434:11434 volumes: - ./data/models:/root/.ollama environment: - OLLAMA_KEEP_ALIVE5m deploy: resources: reservations: devices: - capabilities: [gpu] restart: unless-stoppedshm_size前面说过是给模型推理留共享内存余量。OLLAMA_KEEP_ALIVE5m的意思是模型在内存里保持加载 5 分钟避免每次请求都重新加载。GPU 那段deploy.resources是标准声明方式如果宿主机没有 GPU把整个deploy块删掉即可模型服务会回落到 CPU 模式。Agent Core 的配置要复杂一点它需要知道模型服务、数据库、Redis 的地址。在 Compose 网络里我直接用服务名作为主机名所以环境变量里写的是http://model-service:11434而不是写某个 IP。agent-core: build: ./harness image: harness-core:latest container_name: harness-core ports: - 8080:8080 environment: - MODEL_ENDPOINThttp://model-service:11434 - DATABASE_URLpostgresql://harness:harnesspostgres:5432/harness - REDIS_URLredis://redis:6379/0 - TOOL_WHITELISTweb_search,calculator,db_query volumes: - ./config:/app/config - ./logs:/app/logs depends_on: model-service: condition: service_healthy postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stoppedTOOL_WHITELIST是我后面加的一个安全配置用来控制 Agent 默认可以调用哪些工具不在白名单里的工具即使注册了也不会被启用。这个做得比较保守避免某个 Agent 被提示词注入后乱调内部工具。数据库和缓存相对简单把数据目录挂载出来就好。尤其数据库如果不挂载数据卷重建容器等于删库。postgres: image: postgres:16-alpine container_name: harness-postgres environment: - POSTGRES_USERharness - POSTGRES_PASSWORDharness - POSTGRES_DBharness volumes: - ./data/postgres:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U harness] interval: 5s timeout: 3s retries: 10 restart: unless-stopped redis: image: redis:7-alpine container_name: harness-redis command: [redis-server, --appendonly, yes] volumes: - ./data/redis:/data restart: unless-stoppedWeb UI 我习惯用容器内 Nginx 托管静态页面再反代到 Agent Core。镜像构建时把前端代码复制到 Nginx 目录运行时只需要暴露 80 端口映射到宿主机 8000。这样多一层的好处是后面想加 HTTPS 证书可以直接在 Nginx 层处理不用改 Agent Core。3.3 数据持久化与网络配置要点Compose 默认会创建一个桥接网络服务之间通过服务名互相访问这是最省事的方案。我没有手动指定静态 IP因为服务名解析已经足够稳定。真正要注意的是数据卷模型、PostgreSQL、Redis、日志、配置全部挂载到宿主机目录。容器可以随时删数据得留住。我记得第一次部署时只挂了模型目录和数据库目录日志没挂结果某个 Agent 半夜循环执行任务把容器日志写到内部磁盘容器文件系统被写满。后来我统一规划了宿主机目录~/harness-deploy/ ├── config/ ├── data/ │ ├── models/ │ ├── postgres/ │ └── redis/ ├── logs/ └── docker-compose.yml离线环境也是需要考虑的场景。如果目标机器无法直接拉取镜像可以在一台能拉镜像的机器上执行docker compose pull然后用docker save把镜像打包成 tar 文件拷贝到目标机器后用docker load导入。这个过程不复杂但建议把镜像版本固定否则导入和导出之间的镜像 ID 对不上容易白折腾。4. 一步步完成部署与初始化4.1 目录初始化与镜像准备我建议先创建目录结构再复制项目代码。假设你的 Agent Core 代码和 Web UI 代码已经放在./harness和./harness-web目录下那么顶层只有docker-compose.yml和一堆数据目录。mkdir -p ~/harness-deploy/{config,data,logs} cd ~/harness-deploy # 把 agent-core 代码放到 harness 目录web 代码放到 harness-web 目录 # 然后拉取基础镜像和构建自定义镜像 docker compose build docker compose pullbuild和pull分开做是有原因的数据库、缓存、模型推理这类第三方镜像从仓库拉取自定义镜像则在本机构建。如果构建过程依赖外部包的下载建议先把构建缓存做好避免每次docker compose up -d都重新构建。4.2 启动服务与健康检查启动服务这一步看起来简单但第一次启动时我习惯不用-d而是用前台模式看日志方便及时发现配置错误。docker compose up看到所有服务都正常启动后再按 CtrlC 停掉重新用docker compose up -d在后台运行。确认运行状态docker compose ps如果某个容器显示 unhealthy不要急着重启先看日志。我用得最多的命令是docker compose logs -f agent-core模型服务也需要尽快验证。假设模型推理服务暴露在 11434 端口可以先请求一下本地标签接口确认服务在线curl http://localhost:11434/api/tags接着拉取 DeepSeek 模型。不同来源可能命名不同我示例里使用deepseek-r1:7b你也可以根据自己的模型源调整名称。这一步会下载几百 MB 到几 GB 的文件根据网络环境耐心等一下。docker exec -it harness-model ollama pull deepseek-r1:7b拉取完成后再请求一次标签接口应该能看到模型已经在列表里。到这里模型推理链路基本通了。4.3 创建 Agent 并接入工具打开 Web UI 后第一件事是创建一个管理员账号。然后创建 Agent需要填的内容通常包括Agent 名称、系统提示词、基础模型、温度参数、启用的工具列表。系统提示词是 Agent 行为的核心比如我内部有个“日志分析助手”系统提示词会写清楚“只分析指定目录下的日志文件不执行任何写操作”。工具接入采用白名单机制。在 Agent Core 的环境变量里已经设置了TOOL_WHITELIST但每个 Agent 还可以再单独勾选。工具本身以插件的形式注册注册信息用 JSON 描述简单示例{ name: db_query, description: 对内部业务数据库执行只读 SQL 查询, parameters: { type: object, properties: { sql: { type: string, description: 要执行的只读 SQL } } }, readonly: true }配置完成后我通常会做一个端到端测试问 Agent“统计最近一小时的 ERROR 日志数量并按模块分组”。正常情况下Agent 会先调用工具查询日志再把结果交给模型整理成可读结论。这一步能验证工具链路、模型服务和数据存储是否全部打通。4.4 让局域网里的其他设备访问服务跑通后局域网访问是最后一步。核心是把宿主机的防火墙放行 Web UI 和 Agent API 端口。我用的是 8000 和 8080所以需要保证这两个端口的 TCP 流量能进来。如果你用的是带防火墙的 Linux要注意只放行业务端口别把数据库端口也放出来。我在实践中会直接限制来源网段比如只允许办公网段访问 8080 端口其他网段一律丢弃。这样即使有人扫描到宿主机也无法直接触碰 Agent API。访问地址就是http://宿主机IP:8000。如果在浏览器里能打开登录页面说明 Web UI 和 Agent Core 之间的通信正常。如果页面打不开优先检查容器状态和防火墙规则不要一开始就去改代码。5. 常见问题排查与实战心得5.1 模型服务启动失败的排查顺序我遇到的模型服务问题大多数出在启动阶段。最快的排查路径是先看容器状态再按顺序检查端口、显存、模型文件。现象可能原因处理方式容器反复重启端口被占用或配置错误docker compose logs model-service看具体报错释放端口后重启日志里出现 GPU 相关错误容器无法访问 GPU确认宿主机 GPU 容器运行时已安装compose 中保留完整设备声明模型调用很慢或超时模型仍在加载或配置过低查看OLLAMA_KEEP_ALIVE必要时调大同时检查 CPU/内存占用拉取模型失败模型名称错误或磁盘不足检查模型名称、磁盘剩余空间确认路径挂载正确有一次模型服务一直报“connection refused”我以为是端口映射出了问题后来才意识到是服务还没启动完成Agent Core 已经尝试连接。所以我在depends_on里加了健康检查条件确保模型服务真正就绪后才启动 Agent Core。这是 Compose 里最容易忽略的细节。5.2 显存与内存不足时的处理跑模型最怕资源不够。如果是显存不足常见结果不是直接报错而是容器被杀掉。排查时用dmesg或者docker inspect能看到容器退出信号但最直观的还是看日志。我的处理顺序是先看看有没有更低精度的量化版本换一个小一点的模型如果模型不能换就把并发量降下来。Agent Core 通常会并发处理多个任务我通过给 Agent 配置任务队列上限来控制同时打到模型服务的请求数。另外把OLLAMA_KEEP_ALIVE从 5 分钟调到 15 分钟可以减少反复从磁盘加载模型的开销虽然会增加常驻内存但实际体验会顺很多。还有一个内存亮点PostgreSQL 和 Redis 也会占用内存。如果宿主机总内存只有 16GB光跑 7B 模型和数据库就会很紧张。我建议在 compose 文件里限制数据库和缓存的可用内存例如给 Redis 加上mem_limit: 512m避免某个组件吃光内存后拖垮整机。5.3 配置与日志里容易被忽略的细节有几个细节我几乎每次部署都要重新确认一遍。容器时区非常重要。Agent 生成的日志时间如果和宿主机差 8 小时排查问题时你会很痛苦。我在所有业务容器环境变量里加上了TZAsia/Shanghai如果不是这个时区记得按自己的时区修改。数据库连接串里的密码如果直接写在 compose 文件里会有泄露风险。我的做法是使用.env文件存储环境变量并且把.env加入.gitignore。Compose 会自动读取.env文件填充${POSTGRES_PASSWORD}之类的变量代码仓库里则完全不出现明文密码。镜像标签也不要偷懒用latest。我在离线导入导出镜像时吃过两次“latest 不可复现”的亏。现在所有第三方镜像都固定到具体版本自定义镜像构建时也顺手打上构建日期回滚的时候非常有底。日志方面建议统一日志格式。Agent Core 打印日志默认是自由文本后来我改成 JSON 结构方便在日志系统里按字段检索。如果是自建日志采集这一步能省下很多解析成本。5.4 一些使用上的实战心得整套系统跑起来之后有几条经验我想重点说一下。第一不要一上来就接一堆工具。先跑一个最小闭环模型 一个搜索类工具 数据库存储验证链路稳定后再加知识库和更多工具。我见过同事一口气配置了十几个工具结果 Agent 经常选错工具最后排查了半天发现是工具描述写得不够清晰。工具不在多描述清楚更重要。第二Agent 的系统提示词决定行为边界。一定不要为了追求“智能”就把权限放得太开。比如让 Agent 能够执行 Shell 命令就非常危险如果必须使用工具实现里至少要做白名单命令校验和危险命令拦截。我内部实际部署时所有写操作默认禁用只读操作也只在受控的测试环境开放。第三备份和恢复要提前演练。PostgreSQL 数据卷里的会话记录虽然不常看但一旦丢失所有 Agent 的调试历史都没了。我每周会定时导出数据库到一个归档目录恢复时只需要用 PostgreSQL 官方工具从备份文件恢复即可。整个过程我可以在一小时内完成这个能力平时用不上但真出问题时能救命。最后再说一个小技巧如果想快速验证新模型不要直接替换默认模型而是新建一个 Agent选择新模型跑同一组测试任务。这样能同时对比多个模型的表现不影响正在跑的正式任务。我最后选择的模型配置就是这么一轮一轮测出来的而不是只看理论参数。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑