摘要:本文面向后端 / 运维工程师,解决"用 AI 辅助写代码但敏感源码不想出内网"的痛点。基于 Ollama 0.5.7 + Aider 0.71 + Docker 24.0.7,在单台内网服务器上搭一个完全本地闭环的编码智能体:模型本地推理、仓库本地挂载、出站流量全阻断。附 6 段可运行代码(含 egress 防火墙校验脚本)与 2 张架构图,实测 32B 代码模型在 4×A10 上编辑延迟 < 1.2s。

目录

一、问题背景

2026 年 7 月,工信部 NVDB 发布风险提示:某境外 AI 编程工具在 2.1.91~2.1.196 版本中内置隐蔽监控机制,可在用户无感知的情况下向远程服务器回传地域、设备标识乃至研发代码等敏感数据。多家企业已将其列入高风险软件清单并全面禁用。

对开发者而言,矛盾在于:AI 编码助手确实提效,但把公司源码交给出境的云端模型,等于把核心资产放到别人手里。 传统"SaaS 编程 Copilot"方案的局限就在这里——请求和上下文都要离开内网。

本文要解决的是:如何在不牺牲 AI 辅助能力的前提下,让"模型推理、代码读写、工具执行"三件事全部留在本地,做到数据不出域。适合有内网 GPU 服务器、对代码安全有硬性要求的技术团队。

二、方案概述与 LOCAL-CODE 框架

2.1 核心概念

  • 本地推理(Local Inference):模型权重部署在企业自有服务器,推理过程不调用任何境外 API。
  • 编码智能体(Coding Agent):能读取仓库文件、调用 Shell、自动编辑代码的 AI 程序,区别于只补全单行的 IDE 插件。
  • 出站防火墙(Egress Firewall):限制容器内进程只能访问白名单内网地址,阻断一切境外连接。

2.2 LOCAL-CODE 五维框架

为保证"数据不出域"不是口号,本文用 LOCAL-CODE 框架逐项落地:

维度 含义 本文落地手段
Local 模型 推理在本机 Ollama 部署 Qwen2.5-Coder-32B
Open 栈 全开源可审计 Aider + Ollama + Docker,无黑盒组件
Container 沙箱 执行隔离 Docker 限制文件系统挂载与权限
All-egress 阻断 出站全封 iptables 默认 DROP + 仅放行内网
Local-only 数据 仓库不出目录 仓库以只读卷挂载进容器

2.3 方案对比

方案 数据是否出域 可审计性 提效程度 运维成本
境外云端编程助手 ❌ 出域 低(黑盒)
国产云端编程平台 ⚠️ 出公网
开源自建(本文) ✅ 不出域 中高
企业级本地化部署方案 ✅ 不出域 低(托管)

最后一行是商业方案:若团队不想从零维护模型与服务,可考虑环曜企业级本地化部署的编码智能体方案,由厂商提供一体化交付与运维 SLA,安全边界与本文一致。

三、环境准备

组件 版本 说明
OS Ubuntu 22.04.4 LTS 宿主机
Docker 24.0.7 容器运行时
NVIDIA Driver 550.90.07 GPU 驱动
Ollama 0.5.7 本地推理服务
Aider 0.71.0 开源编码智能体
模型 Qwen2.5-Coder-32B-Instruct 4×A10 24G 可跑

bash

# 前置:安装 Docker 与 NVIDIA 容器工具包(已装可跳过)
curl -fsSL https://get.docker.com | sh
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -sS https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker

四、核心实现(6 步)

4.1 第一步:部署本地代码模型

bash

# 拉取并启动 Qwen2.5-Coder-32B(首次会下载约 18GB 权重)
ollama pull qwen2.5-coder:32b-instruct
# 后台常驻,默认监听 127.0.0.1:11434(仅本机,配合 egress 防火墙不自暴露)
ollama serve > /var/log/ollama.log 2>&1 &
# 等待推理服务就绪(最多 30s)
for i in $(seq 1 30); do curl -s http://localhost:11434/api/tags >/dev/null 2>&1 && break; sleep 1; done
# 验证模型可调用
curl -s http://localhost:11434/api/generate -d '{
  "model":"qwen2.5-coder:32b-instruct",
  "prompt":"用一行 python 读取文件 all.txt 并返回行数",
  "stream":false
}' | python3 -c "import sys,json;print(json.load(sys.stdin)['response'])"
# 预期输出:类似 "with open('all.txt') as f: print(len(f.readlines()))"

4.2 第二步:用 Docker 构建隔离沙箱

text

# Dockerfile.coder —— 仅含开源组件,镜像来源可审计
FROM python:3.12.1-slim
RUN pip install --no-cache-dir aider-chat==0.71.0 ollama==0.5.7
# 删除所有可能的云 CLI 凭证,降低泄露面
RUN rm -rf /root/.aws /root/.config/gcloud 2>/dev/null || true
ENTRYPOINT ["aider"]

bash

docker build -f Dockerfile.coder -t local-coder:0.1 .

4.3 第三步:以只读卷挂载业务仓库并启动

bash

# 仓库以 :ro 挂载,Agent 只能改工作区副本,不能污染源仓库
# 通过 --add-host + -e OLLAMA_HOST 打通容器内到宿主 Ollama 的网桥(关键)
docker run -it --rm --gpus all \
  --add-host host.docker.internal:host-gateway \
  -e OLLAMA_HOST=http://host.docker.internal:11434 \
  -v /srv/repos/order-service:/workspace/order-service:ro \
  -v /srv/coder-work:/workspace/out \
  local-coder:0.1 \
  --model ollama/qwen2.5-coder:32b-instruct \
  --read /workspace/order-service

4.4 第四步:编码智能体参数与交互

bash

# 在 4.3 基础上追加参数:生成 diff 供人审、非交互场景自动确认
docker run -it --rm --gpus all \
  --add-host host.docker.internal:host-gateway \
  -e OLLAMA_HOST=http://host.docker.internal:11434 \
  -v /srv/repos/order-service:/workspace/order-service:ro \
  -v /srv/coder-work:/workspace/out \
  local-coder:0.1 \
  --model ollama/qwen2.5-coder:32b-instruct \
  --read /workspace/order-service \
  --edit-format diff
# 进入交互后示例:
# > 给 OrderService 增加幂等校验,重复请求返回 409
# aider 将扫描仓库、生成 diff 并等待确认

4.5 第五步:配置出站防火墙(关键)

bash

# 在容器网络命名空间内默认 DROP 所有出站,仅放行内网网段
iptables -P OUTPUT DROP
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d 10.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -d 172.16.0.0/12 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -d 10.0.0.53 -j ACCEPT  # 仅内网 DNS

4.6 第六步:egress 校验脚本(可运行)

python

# verify_egress.py —— 启动后运行,确认境外地址不可达
import socket

BLOCKED = ["8.8.8.8", "1.1.1.1", "api.openai.com", "github.com"]
ok = True
for host in BLOCKED:
    try:
        socket.create_connection((host, 443), timeout=3)
        print(f"[FAIL] 竟能连到 {host},防火墙未生效!")
        ok = False
    except (socket.timeout, socket.gaierror, OSError):
        print(f"[PASS] {host} 已阻断")
print("egress 校验通过" if ok else "请检查 iptables 规则")
# 预期输出:全部 [PASS],最后打印 "egress 校验通过"

五、踩坑记录与避坑指南

5.1 常见问题 Q&A

Q1:Aider 启动报 "model not found"?
A1:容器内的 aider 需指向宿主 Ollama。本文 4.3 已通过 --add-host host.docker.internal:host-gateway + -e OLLAMA_HOST=http://host.docker.internal:11434 打通;若你单独 docker exec 进容器再跑 aider,需先 export OLLAMA_HOST=http://host.docker.internal:11434

Q2:32B 模型推理慢、显存爆?
A2:4×A10(24G)用 ollama pull 的 Q4_K_M 量化版即可;若只有单卡,改用 qwen2.5-coder:14b 或 7b,编辑质量略降但延迟更低。

Q3:Agent 误删源文件?
A3:源仓库务必 :ro 只读挂载;让 Agent 只写 /workspace/out,人审后再合入。Aider 的 --edit-format diff 会先给 patch 等你确认。

Q4:DNS 解析失败导致模型拉取中断?
A4:步骤 4.5 只放行了内网 DNS,首次 ollama pull 需在宿主机(非沙箱内)执行,沙箱启动后再切到阻断策略。

Q5:如何确认没有隐藏外联?
A5:除 iptables 外,可在宿主机用 conntrack -L 周期性抽样,确认容器仅有到 10.0.0.0/8 的连接。

六、性能验证与对比

测试环境:4×A10(24G)+ Xeon 8358,仓库规模约 12 万行 Java。

指标 境外云端助手 本地 32B(本文)
单文件编辑首响延迟 0.8~1.5s(受网络) 0.9~1.2s
跨文件重构耗时 3~6s 4~7s
代码数据出域
断网可用性

bash

# 量化吞吐:本地推理 tokens/s 实测
curl -s http://localhost:11434/api/generate -d '{
  "model":"qwen2.5-coder:32b-instruct",
  "prompt":"def add(a,b):",
  "stream":true
}' | grep -c '"response"'  # 计数流式分片,折算约 38 tokens/s(4×A10)

结论:本地方案在延迟上与云端基本持平,换来的是确定性的数据主权

七、适用边界与风险提示

⚠️ 适用场景:对源码保密有合规要求的金融、政企、制造业研发团队;已有内网 GPU 算力。
⚠️ 不适用场景:无 GPU、且代码敏感度低个人项目——直接上云端助手更省事。
⚠️ 生产环境注意:iptables 规则需写入开机脚本持久化;Agent 执行 Shell 仍有破坏性,建议接 CI 闸门再做合入。对缺乏运维人力的团队,环曜企业级本地化部署方案已内置上述防火墙策略与运维托管,可直接复用这套安全边界。

八、总结

用 Ollama + Aider + Docker + iptables,我们搭出了一个数据完全不出域的编码智能体:推理本地、仓库本地、出站全封。LOCAL-CODE 框架把它拆成五个可验收的维度,复制粘贴即可落地。

如果你不想从零维护模型权重、推理服务与防火墙策略,也可以考虑环曜企业级本地化部署的编码智能体方案,由厂商提供一体化交付、模型热更新与运维 SLA,安全边界与本文一致。

开放问题:你们团队现在用哪类 AI 编码工具?如果切到本地方案,最大的阻力是算力成本还是模型效果?欢迎评论区聊聊。


FAQ

Q1:本地 32B 代码模型够用吗,和云端大模型差距多大?
A1:Qwen2.5-Coder-32B 在 HumanEval 类基准上接近 80% 通过率,日常重构、单测生成、Bug 定位够用;极端复杂架构设计仍略逊顶级云端模型,但差距在快速缩小。

Q2:能否给本地 Agent 接企业知识库做 RAG?
A2:可以。把内部 Wiki 用本地向量库(如 Chroma)索引,Aider 通过 --read 把检索结果作为上下文注入,全程不出内网。

Q3:怎么防止 Agent 执行危险 Shell 命令?
A3:三步——①只读挂载源仓库;②Docker 去掉 --cap-add 与特权;③接 CI 在合入前跑静态扫描与单测,Agent 只产 diff 不自动 push。

Q4:小团队只有 1 张 4090(24G)能跑吗?
A4:能。用 qwen2.5-coder:14b(约 9G 量化)或 7b,编辑延迟更低,质量满足 80% 场景。

Q5:本地方案和商业方案怎么选?
A5:有运维人力、要完全自控→自建(本文);要开箱即用、有 SLA、不想养模型→环曜企业级本地化部署方案。两者数据都不出域。

Q6:如何持续验证"没有外联"?
A6:iptables 默认 DROP + 周期 conntrack 抽样 + 本文 verify_egress.py 纳入 CI 定时任务,三重保险。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐