DeepAgents 使用 Docker 沙箱执行 Shell 命令:从 0 到生产部署
DeepAgents 使用 Docker 沙箱执行 Shell 命令从 0 到生产部署一、为什么需要 Docker 沙箱DeepAgents 的execute工具只有在后端实现SandboxBackendProtocol时才会真正执行 Shell 命令。项目里默认使用的FilesystemBackend只负责文件读写不支持执行命令。所以当 Skill 里出现下面这类指令时Agent 无法真正运行脚本python skills/bank-asset-allocation-report/scripts/generate_report.py...直接换成LocalShellBackend虽然简单但它会在宿主机上执行任意命令存在安全风险不适合作为 Web API 的生产方案。更稳妥的做法是使用 Docker 沙箱把命令执行、文件读写都隔离到容器里。二、DeepAgents 沙箱实现原理DeepAgents 已经提供了BaseSandbox它基于两个核心能力实现了大部分文件操作execute()在沙箱里执行 Shell 命令upload_files()把文件传入沙箱download_files()从沙箱取回文件id沙箱唯一标识ls、read、write、edit、grep、glob这些方法都由BaseSandbox自动实现不需要我们重写。三、Docker 镜像准备新建app/docker/DockerfileFROM python:3.12-slim RUN apt-get update \ apt-get install -y --no-install-recommends grep \ rm -rf /var/lib/apt/lists/* WORKDIR /workspace # 如果沙箱里要运行项目脚本就安装项目依赖 RUN pip install --no-cache-dir reportlab python-docx markdown openpyxl pypdf # 容器必须有一个长驻进程否则启动后会立即退出 CMD [python3, -c, import time; time.sleep(1e9)]构建镜像dockerbuild-tdeepagents-sandbox:latest-fapp/docker/Dockerfile.说明python:3.12-slim和项目要求一致。项目pyproject.toml要求3.12,3.13本地.venv也是 Python 3.12。CMD里的time.sleep(1e9)大约 31.7 年对开发环境来说等于常驻而且不占用 CPU。如果容器启动后显示Exited (0)多半是启动命令是裸的python3Python 解释器没有输入就退出了。四、实现 DockerSandbox这里推荐使用 Docker CLI 实现不依赖 Python 的docker包。这样做有两个好处避免项目根目录docker/文件夹和 pip 包docker重名。不需要额外安装 Python SDK生产环境只需要 Docker CLI。新建app/docker/docker_sandbox.pyfrom__future__importannotationsimportioimportsubprocessimporttarfileimporttimeimportuuidfromdeepagents.backends.protocolimport(ExecuteResponse,FileDownloadResponse,FileUploadResponse,)fromdeepagents.backends.sandboximportBaseSandboxclassDockerSandbox(BaseSandbox):def__init__(self,*,image:strpython:3.12-slim,workdir:str/workspace,timeout:int120,volumes:dict|NoneNone,)-None:self._workdirworkdir self._timeouttimeout namefdeepagents-{uuid.uuid4().hex[:8]}cmd[docker,run,-d,--name,name,--workdir,workdir]forhost_path,cfgin(volumesor{}).items():cmd[-v,f{host_path}:{cfg[bind]}:{cfg.get(mode,rw)}]cmd[image,python3,-c,import time; time.sleep(1e9)]procsubprocess.run(cmd,capture_outputTrue,textTrue)ifproc.returncode!0:raiseRuntimeError(fdocker run failed:{proc.stderr})self._container_idproc.stdout.strip()propertydefid(self)-str:returnself._container_id[:12]defexecute(self,command:str,*,timeout:int|NoneNone)-ExecuteResponse:procsubprocess.run([docker,exec,-w,self._workdir,self._container_id,/bin/sh,-c,command,],capture_outputTrue,encodingutf-8,errorsreplace,timeouttimeoutiftimeoutisnotNoneelseself._timeout,)returnExecuteResponse(outputproc.stdoutproc.stderr,exit_codeproc.returncode,)defupload_files(self,files:list[tuple[str,bytes]])-list[FileUploadResponse]:responses[]forpath,contentinfiles:ifnotpath.startswith(/)or..inpath:responses.append(FileUploadResponse(pathpath,errorinvalid_path))continuebufio.BytesIO()withtarfile.open(fileobjbuf,modew)astar:infotarfile.TarInfo(path.lstrip(/))info.sizelen(content)info.mtimeint(time.time())tar.addfile(info,io.BytesIO(content))procsubprocess.run([docker,cp,-,f{self._container_id}:/],inputbuf.getvalue(),capture_outputTrue,)ifproc.returncode0:responses.append(FileUploadResponse(pathpath))else:responses.append(FileUploadResponse(pathpath,errorproc.stderr.decode(errorsreplace).strip()orupload_failed,))returnresponsesdefdownload_files(self,paths:list[str])-list[FileDownloadResponse]:responses[]forpathinpaths:ifnotpath.startswith(/)or..inpath:responses.append(FileDownloadResponse(pathpath,errorinvalid_path))continueprocsubprocess.run([docker,cp,f{self._container_id}:{path},-],capture_outputTrue,)ifproc.returncode!0:errproc.stderr.decode(errorsreplace)errorfile_not_foundifnot foundinerr.lower()orno suchinerr.lower()elseerr.strip()[:200]responses.append(FileDownloadResponse(pathpath,errorerror))continuetry:withtarfile.open(fileobjio.BytesIO(proc.stdout),moder:*)astar:membertar.next()ifmemberisNoneormember.isdir():responses.append(FileDownloadResponse(pathpath,erroris_directory))continuecontenttar.extractfile(member).read()responses.append(FileDownloadResponse(pathpath,contentcontent))exceptExceptionasexc:responses.append(FileDownloadResponse(pathpath,errorstr(exc)[:200]))returnresponses核心实现说明docker run -d创建长驻容器。docker exec在容器里执行命令。docker cp - 容器:/从标准输入接收 tar 包并解压到容器实现文件上传。docker cp 容器:路径 -把容器文件打包成 tar 输出到标准输出实现文件下载。五、接入主 Agent修改app/agent/main_agent.pyfromapp.docker.docker_sandboximportDockerSandbox project_root_pathPath(__file__).parents[1].resolve()(project_root_path/output).mkdir(parentsTrue,exist_okTrue)file_backendDockerSandbox(imagedeepagents-sandbox:latest,workdir/workspace,timeout120,volumes{str(project_root_path):{bind:/workspace,mode:ro},str(project_root_path/output):{bind:/workspace/output,mode:rw},},)这里把app/只读挂载到容器的/workspace把output/单独以可写方式挂载这样Agent 能在容器里读取skills/。生成的文件会写到/workspace/output/session_xxx。宿主机通过app/output/session_xxx直接看到结果。六、验证先验证基础命令dockerrun-dit--namesandbox-test deepagents-sandbox:latest python3-cimport time; time.sleep(1e9)dockerexecsandbox-test python3--version再验证 Python 后端cdD:/AI Learning/financesearch-agents .venv\Scripts\python-B-c from app.docker.docker_sandbox import DockerSandbox s DockerSandbox( imagedeepagents-sandbox:latest, workdir/workspace, volumes{ D:/AI Learning/financesearch-agents/app: {bind: /workspace, mode: ro}, D:/AI Learning/financesearch-agents/app/output: {bind: /workspace/output, mode: rw}, }, ) print(s.execute(python3 --version)) s.write(/workspace/output/test.txt, hello) print(s.read(/workspace/output/test.txt)) 验证完删除测试容器dockerrm-fsandbox-test七、Windows Docker Desktop 常见问题1. 容器启动后立即变成 Exited (0)原因通常是启动命令是裸的python3IMAGE COMMAND STATUS deepagents-sandbox:latest python3 Exited (0)Python 解释器启动后没有 stdin 输入会立即退出。解决Dockerfile 里加CMD [python3, -c, import time; time.sleep(1e9)]。手动运行时使用docker run -dit ... python3 -c import time; time.sleep(1e9)。Docker Desktop 需要处于 Linux 容器模式。2. import docker 指向了项目自己的 docker 目录如果项目根目录有docker/文件夹Python 的import docker会优先解析到这个目录module docker (namespace) from [D:\\AI Learning\\financesearch-agents\\docker]这不是 pip 包docker所以没有from_env()方法。不重命名目录的解决方案就是本文使用的方案不import docker全部改用 Docker CLI。如果一定要用 Python SDK则需要把项目根目录的docker/改名例如infra/否则会一直冲突。3. docker.from_env 需要加载 .env 吗docker.from_env()读取的是进程环境变量不是.env文件。本机 Docker Desktop 默认不需要任何环境变量。远程 Docker 时需要在启动进程前设置DOCKER_HOST、DOCKER_TLS_VERIFY、DOCKER_CERT_PATH等变量。如果这些变量写在.env里需要先调用load_dotenv()再执行docker.from_env()。4. Python 版本不一致有影响吗本地虚拟环境是 Python 3.12.13项目锁定 Python 3.12因此 Docker 镜像使用python:3.12-slim是正确选择。真正需要注意的不是版本而是平台Docker 镜像是 Debian Linux本地是 Windows。脚本里的路径和 Shell 命令要按照 Linux 书写。如果容器里要运行项目脚本必须在 Dockerfile 里安装脚本依赖。八、生产部署建议1. 每个会话使用独立容器当前DockerSandbox每次实例化都会创建新容器。Web 服务里不要让所有用户共用一个容器否则文件会互相污染。建议每个session_id对应一个容器任务结束后dockerstopcontainer_iddockerrmcontainer_id2. 限制挂载权限生产环境不要直接把整个项目目录以可写方式挂载进容器。推荐只挂载必要目录skills/只读挂载。output/可写挂载。数据库配置、密钥、上传文件不要放进容器。3. 远程 Docker部署到远程 Docker 时在服务启动前设置DOCKER_HOSTtcp://192.168.1.10:2375或者DOCKER_HOSTssh://user192.168.1.10使用 Docker CLI 方案时docker run、docker exec、docker cp都会读取同一个环境变量不会出现连接不一致的问题。4. 镜像版本固定生产环境不要使用latest建议固定到具体版本dockerbuild-tregistry.example.com/deepagents-sandbox:2026.08.10.dockerpush registry.example.com/deepagents-sandbox:2026.08.105. 安全控制不要接受不可信用户的任意 Shell 命令。有需要时配合interrupt_on{execute: True}做人工审批。容器内不要安装不必要的网络工具和调试工具。定期清理退出状态的历史容器和未使用的镜像。九、总结这套方案的核心思路是用BaseSandbox继承 DeepAgents 的沙箱接口。只实现execute、upload_files、download_files、id。使用 Docker CLI 替代 Python SDK避免项目目录重名问题。通过只读挂载和独立容器实现生产环境的基本隔离。这样既能让 Agent 真正执行 Skill 里的脚本又比直接在宿主机上执行命令安全得多。

相关新闻

工业通信核心:IEC 104规约原理、报文解析与工程实践指南

工业通信核心:IEC 104规约原理、报文解析与工程实践指南

1. 项目概述:从零开始理解工业通信的“普通话”如果你在电力、轨道交通或者工业自动化领域工作,那么“104规约”这个词你一定不陌生。它就像工业通信世界里的“普通话”,是连接监控主站(调度中心)和远方终端&#xff0…

2026/8/11 3:26:23 阅读更多 →
Unity多人求生游戏开发框架:核心模块、网络同步与性能优化全解析

Unity多人求生游戏开发框架:核心模块、网络同步与性能优化全解析

1. 项目概述:为什么需要一个现成的求生框架?如果你是一个独立开发者或者小型团队,想做一个《森林》、《Rust》或者《英灵神殿》那样的多人求生游戏,那么你肯定知道,从零开始搭建这一切有多让人头疼。资源管理系统、建造…

2026/8/11 3:26:22 阅读更多 →
深度学习进阶:从基础使用到掌握训练循环、数据增强与模型优化

深度学习进阶:从基础使用到掌握训练循环、数据增强与模型优化

1. 从“会用”到“懂用”:深度学习进阶的思维转变很多朋友在入门深度学习时,都走过这样一条路:跟着教程,安装好PyTorch或TensorFlow,跑通一个MNIST手写数字识别的Demo,看着屏幕上跳动的准确率数字&#xff…

2026/8/11 3:26:22 阅读更多 →

最新新闻

5分钟免费iOS激活锁绕过指南:Applera1n解锁iPhone 6s-X完整方案

5分钟免费iOS激活锁绕过指南:Applera1n解锁iPhone 6s-X完整方案

5分钟免费iOS激活锁绕过指南:Applera1n解锁iPhone 6s-X完整方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n Applera1n是一款专为iOS 15-16系统设计的免费激活锁绕过工具,专…

2026/8/11 4:21:50 阅读更多 →
【金仓数据库征文】AI Agent SQL 执行超时与资源保护——在线问数不能把数据库当成“无限工具”

【金仓数据库征文】AI Agent SQL 执行超时与资源保护——在线问数不能把数据库当成“无限工具”

文章目录每日一句正能量1. 背景与问题:SQL 是只读的,也可能把生产库拖慢2. 环境与数据:先定义服务预算,再讨论参数2.1 为什么不能直接照抄一个 30 秒超时3. 复现过程:为什么只设 statement_timeout 仍然会出问题3.1 第…

2026/8/11 4:21:50 阅读更多 →
洛谷P1219、P1784、P11229三题的题解

洛谷P1219、P1784、P11229三题的题解

因为八个皇后位置之间相互制约&#xff0c;所以肯定得记录每个皇后的位置。 我们可以枚举每一个格子的位置&#xff0c;再看它的列、对角线是否与其他皇后相等。&#xff08;dfs传进的参数为行号&#xff0c;不会相重&#xff09; #include <bits/stdc.h> using namespac…

2026/8/11 4:21:50 阅读更多 →
Agent 安全事件成为本周核心风险信号,从三起越界评测到 Hugging Face 入侵

Agent 安全事件成为本周核心风险信号,从三起越界评测到 Hugging Face 入侵

文章目录先把事实说准&#xff1a;两组事件不是同一种“失控”Anthropic 三起事件&#xff1a;一句错误的环境假设如何变成真实入侵事件一&#xff1a;虚构公司撞名真实公司事件二&#xff1a;为了完成依赖混淆&#xff0c;真的把恶意包发到了 PyPI事件三&#xff1a;约 9,000 …

2026/8/11 4:21:50 阅读更多 →
如何在5分钟内用YOLOv8 AI自瞄助手打造你的FPS游戏智能瞄准系统

如何在5分钟内用YOLOv8 AI自瞄助手打造你的FPS游戏智能瞄准系统

如何在5分钟内用YOLOv8 AI自瞄助手打造你的FPS游戏智能瞄准系统 【免费下载链接】yolov8_aimbot Aim-bot based on AI for all FPS games 项目地址: https://gitcode.com/gh_mirrors/yo/yolov8_aimbot 还在为FPS游戏中的瞄准难题而烦恼吗&#xff1f;想要在激烈的枪战中…

2026/8/11 4:21:50 阅读更多 →
3个实用技巧:掌握FanControl风扇控制软件的高级配置

3个实用技巧:掌握FanControl风扇控制软件的高级配置

3个实用技巧&#xff1a;掌握FanControl风扇控制软件的高级配置 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/F…

2026/8/11 4:20:49 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升&#xff1a;AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析&#xff1a;控制台与Apifox的数据差异 最近在调试一个前后端分离项目时&#xff0c;遇到了一个典型问题&#xff1a;后端服务在本地开发环境控制台能正常输出查询数据&#xff0c;但通过Apifox测试时却返回空结果。这种"控制台有数据&#xff0c;接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友&#xff0c;尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友&#xff0c;都在问我同一个问题&#xff1a;“听说现在用Claude Code这种AI编程工具&#xff0c;小白也能做游戏了&#xff0c;是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑&#xff1a;baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码&#xff08;维护中 rm repo&#xff09; 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片&#xff1a;Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身&#xff0c;而应重视模型外的系统搭建&#xff0c;即Harness。提出AgentModelHarness的实用公式&#xff0c;详细介绍Harness的四个层次&#xff1a;持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速&#xff1a;macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南&#xff1a;3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片&#xff1a;为英语学习 App 打造桌面级学习助手适用平台&#xff1a;HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0&#xff08;API 26 Beta&#xff09;新增了 AgentCard 智能体卡片能力&#xff0c;这是继 HMAF&#xff08;鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →