AgentRun Sandbox 的 AIO(All-In-One)镜像内置了 Code Interpreter 和 BrowserTool 两类能力。如果您需要在同一沙箱实例中运行自己的服务(例如自定义 API、数据处理进程),可以通过扩展 AIO 基础镜像的方式实现,无需修改 AIO 原有代码。
本文以一个简单的 Python Echo Server 为例,介绍如何将自定义服务集成到 AIO 沙箱中。同样的方式适用于 CodeInterpreter、Browser 等其他基础镜像。
工作原理
AIO 镜像内置了两个核心组件:
-
Process Compose:进程编排工具,负责管理沙箱内所有自启动进程。
-
OpenResty(Nginx):反向代理服务,负责将外部请求路由到内部各服务。
由于 AgentRun 的运行环境限制,沙箱实例对外只暴露一个端口(5000)。所有外部请求都通过 OpenResty 按路径分发到内部的不同服务。
AIO 镜像的启动脚本(entrypoint.sh)在容器启动时会自动扫描以下目录,加载用户扩展的服务配置:
|
配置类型 |
扫描目录 |
作用 |
|
进程配置 |
|
自动启动并管理自定义进程 |
|
Nginx Upstream |
|
注册后端服务地址 |
|
Nginx 路由 |
|
将 URL 路径映射到对应服务 |
因此,扩展 AIO 镜像只需要做一件事:向正确目录放置配置文件。
前提条件
开始前,请确认以下条件已满足:
-
已完成 AgentRun SLR 服务角色授权(首次使用时在控制台根据提示完成)。
-
已在控制台创建 AIO 沙箱模板。
-
本地已安装 Docker,能够构建和运行容器镜像。
-
熟悉 Docker、Nginx 基本概念。
操作步骤
以下示例将一个 Python Echo Server 集成到 AIO 沙箱中,通过/echo路径对外提供服务。
您可以下载完整的示例代码包:echoserver.zip
文件结构
新建echoserver/目录,按以下结构组织文件:
echoserver/
├── echo_server.py
└── config/
├── process-compose.echoserver.yaml
├── nginx-echoserver-upstream.conf
└── nginx-echoserver-routes.conf
步骤一:编写服务代码
创建 echo_server.py,实现一个简单的 HTTP 服务,GET 请求返回ok:
#!/usr/bin/env python3
import os
from http.server import HTTPServer, BaseHTTPRequestHandler
DEFAULT_PORT = 9000
class EchoHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-Type', 'text/plain; charset=utf-8')
self.end_headers()
self.wfile.write(b'ok\n')
def main():
port = int(os.environ.get('ECHO_SERVER_PORT', DEFAULT_PORT))
host = os.environ.get('ECHO_SERVER_HOST', '0.0.0.0')
server = HTTPServer((host, port), EchoHandler)
print(f"[echoserver] Starting echo server on {host}:{port}")
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
if __name__ == '__main__':
main()
步骤二:配置Process Compose
创建process-compose.echoserver.yaml,定义服务的启动方式、健康检查和日志:
version: "0.5"
log_level: info
environment:
- PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
processes:
echoserver:
command: "python3 /usr/local/bin/echo_server.py"
availability:
restart: "always"
backoff_seconds: 2
max_restarts: 5
readiness_probe:
http_get:
host: localhost
port: ${ECHO_SERVER_PORT:-9000}
path: /
initial_delay_seconds: 1
period_seconds: 5
timeout_seconds: 2
success_threshold: 1
failure_threshold: 3
environment:
- ECHO_SERVER_HOST=0.0.0.0
- ECHO_SERVER_PORT=9000
- PYTHONUNBUFFERED=1
- PYTHONDONTWRITEBYTECODE=1
log_configuration:
disable_json: true
no_metadata: false
add_timestamp: true
timestamp_format: "2006-01-02 15:04:05.000"
fields_to_append:
- level=INFO
步骤三:配置Nginx
Upstream 配置:创建nginx-echoserver-upstream.conf,定义后端服务地址:
upstream echoserver {
server localhost:9000;
keepalive 16;
}
路由配置:创建nginx-echoserver-routes.conf,将/echo路径代理到 echo server:
location /echo {
proxy_pass http://echoserver;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
步骤四:编写Dockerfile
创建Dockerfile,以 AIO 基础镜像为基础,将服务代码和配置文件复制到对应目录:
FROM serverless-registry.cn-hangzhou.cr.aliyuncs.com/functionai/sandbox-all-in-one:v0.9.29
USER root
# 复制服务代码
COPY echo_server.py /usr/local/bin/echo_server.py
RUN chmod +x /usr/local/bin/echo_server.py
# Process Compose 配置(entrypoint.sh 自动扫描 /etc/sandbox/config/ 目录)
COPY config/process-compose.echoserver.yaml /etc/sandbox/config/process-compose.echoserver.yaml
# Nginx 配置(entrypoint.sh 自动扫描并加载)
RUN mkdir -p /etc/sandbox/config/nginx/http.d /etc/sandbox/config/nginx/conf.d
COPY config/nginx-echoserver-upstream.conf /etc/sandbox/config/nginx/http.d/echoserver-upstream.conf
COPY config/nginx-echoserver-routes.conf /etc/sandbox/config/nginx/conf.d/echoserver-routes.conf
ENV ECHO_SERVER_HOST=0.0.0.0 \
ECHO_SERVER_PORT=9000
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["process-compose", "up", "--tui=false", "--no-server"]
步骤五:构建并运行
cd echoserver
# 构建镜像
docker build -f Dockerfile -t echoserver-extension:latest .
# 本地运行(将容器的 5000 端口映射到本地 5000)
docker run --rm \
-p 5000:5000 \
--name echoserver-test \
echoserver-extension:latest
步骤六:验证
# 通过 Nginx 代理访问 echo server
curl http://localhost:5000/echo
# 预期返回: ok
在 AgentRun 上部署后,访问地址格式如下:
https://{账号ID}.agentrun-data.cn-hangzhou.aliyuncs.com/sandboxes/{沙箱ID}/echo
配置参考
Process Compose 配置
process-compose.*.yaml支持以下核心配置项:
|
配置项 |
说明 |
|
|
服务启动命令 |
|
|
重启策略, |
|
|
HTTP 健康检查,服务提供 |
|
|
进程健康检查,服务未提供 HTTP 端点时使用 |
|
|
服务运行所需的环境变量 |
|
|
日志格式配置 |
Nginx Upstream 配置
定义后端服务地址,放置在/etc/sandbox/config/nginx/http.d/目录:
upstream your_service {
server localhost:9001; # 自定义服务内部端口
keepalive 16;
}
Nginx 路由配置
定义 URL 路径到 upstream 的映射,放置在/etc/sandbox/config/nginx/conf.d/目录。
基本路由:
location /your-service {
proxy_pass http://your_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
使用 rewrite 转换路径:
如果需要在转发前改写 URL 路径,可以使用rewrite指令。例如,将外部路径/api/v1/echo转换为后端期望的/echo:
location /api/v1/echo {
rewrite ^/api/v1/echo(.*)$ /echo$1 break;
proxy_pass http://echoserver;
proxy_set_header Host $host;
}
rewrite指令说明:
-
^/api/v1/echo(.*)$:匹配路径,(.*)捕获尾部内容。 -
/echo$1:改写后的路径,$1为捕获内容。 -
break:停止后续 rewrite 规则处理,直接将改写后的路径传给proxy_pass。
更多 rewrite 示例:
# 移除路径前缀:/api/echo/xxx → /echo/xxx
location /api/echo {
rewrite ^/api/echo(.*)$ /echo$1 break;
proxy_pass http://echoserver;
}# 添加路径前缀:/echo → /v1/echo
location /echo {
rewrite ^/echo(.*)$ /v1/echo$1 break;
proxy_pass http://echoserver;
}
文件命名规范
建议遵循以下命名约定,保持团队一致性:
|
配置类型 |
命名格式 |
示例 |
|
Process Compose |
|
|
|
Nginx Upstream |
|
|
|
Nginx 路由 |
|
|
注意事项
-
端口冲突:自定义服务的内部端口不能与 AIO 内置服务冲突,建议使用 9000 及以上端口。AIO 内置服务端口:
-
Nginx 内置网关:5000
-
Code Interpreter:5001
-
BrowserTool:3000
-
-
健康检查:如果服务提供 HTTP 健康检查端点(如
/health),建议在process-compose.*.yaml中使用readiness_probe.http_get;否则使用readiness_probe.exec检查进程是否存活。 -
服务命名唯一性:
process-compose.*.yaml中processes下的服务名(key)在同一沙箱内必须唯一。 -
路由路径唯一性:
location路径不能与 AIO 内置路由冲突。AIO 内置路由:-
Code Interpreter 占用:
/、/contexts、/execute等 -
BrowserTool 占用:
/ws/automation、/recordings等
-
故障排查
服务未启动
# 查看 process-compose 日志
docker logs echoserver-test | grep echoserver
# 确认进程是否运行
docker exec echoserver-test pgrep -f echo_server.py
# 确认 Process Compose 配置已加载
docker exec echoserver-test ls -la /etc/sandbox/config/process-compose.*.yaml
Nginx 配置错误
# 验证 Nginx 配置语法
docker exec echoserver-test /usr/local/openresty/nginx/sbin/nginx -t
# 查看 Nginx 错误日志
docker exec echoserver-test tail -f /var/log/nginx/error.log
# 确认 upstream 配置已加载
docker exec echoserver-test cat /etc/sandbox/config/nginx/http.d/echoserver-upstream.conf
# 确认路由配置已加载
docker exec echoserver-test cat /etc/sandbox/config/nginx/conf.d/echoserver-routes.conf
路由不工作
# 确认 Nginx conf.d 目录内容
docker exec echoserver-test ls -la /etc/sandbox/config/nginx/conf.d/
# 直接访问内部服务(绕过 Nginx),确认服务本身是否正常
docker exec echoserver-test curl http://localhost:9000/
# 查看 Nginx 访问日志,确认请求是否到达
docker exec echoserver-test tail -f /var/log/nginx/access.log