How to Build a Multi‑User Agent Backend with Docker Isolation
This guide walks through constructing a multi‑user, cloud‑hosted Agent‑as‑a‑Service platform using Docker containers for isolation, detailing the system architecture, required Docker image, container management API, tool implementations such as code execution and web browsing, and provides complete Python code examples for testing and deployment.
The article presents a step‑by‑step prototype for a multi‑user Agent‑as‑a‑Service backend that runs on the cloud and isolates each user in a Docker sandbox. It explains the overall design, required Docker image, container‑management component, tool implementations, and testing procedures, and supplies full Python source code.
System Principles
The core idea is an autonomous multi‑Agent/Tool system where a scheduler Agent delegates tasks to specialized Agents (e.g., a coding Agent and a web‑browsing Agent). Each logged‑in user gets a dedicated "manus" Agent with its own virtual machine (Docker container) to execute code, browse the web, create files, etc., ensuring isolation and security.
Architecture Overview
The architecture consists of four main components:
A pre‑built Docker image that provides a Python execution environment, common libraries (e.g., pandas), and tools such as Chromium for web automation.
A container manager that creates, starts, stops, and interacts with per‑user containers.
A ReAct‑style Agent that performs step‑wise reasoning and task scheduling.
Four executable Tools (which can also be Agents): CodeGenerator (generates Python code), WebpageCrawler (fetches web pages), CodeExecutor (runs code inside the container), and Browser (automates browsing).
The shared workspace stores input/output files for each task.
Preparing the Docker Image
The Docker image includes:
A basic Python execution environment.
Common third‑party libraries (e.g., pandas).
Tools needed in the sandbox, such as Chromium for headless browsing.
Startup scripts (e.g., start.sh) that launch a virtual X server (Xvfb) so Chromium can run without a display.
Pre‑built Python modules like agent_browser.py that implement the Web Agent.
#!/bin/bash
Xvfb :99 -screen 0 1024x768x16 &
sleep 1
exec "$@"After editing Dockerfile to install playwright (which provides Chromium) and copy the scripts, the image is built with:
docker build -t python-data-analysis:3.11 .Docker Container Management API
A lightweight Python wrapper abstracts Docker commands. The key class is DockerContainer with methods to start, stop, set the working directory, and execute code inside the container.
class DockerContainer:
"""Manage a Docker container"""
def __init__(self, image: str = "python-data-analysis:3.11", container_name: str = "llamaindex-executor", base_work_dir: str = "/Users/pingcy/workspace", auto_remove: bool = True):
...
def start(self):
"""Start the Docker container"""
...
def set_work_dir(self, work_dir: str) -> None:
"""Set the current working directory"""
...
def execute(self, code: str, language: str = "python", work_dir: Optional[str] = None) -> Dict[str, str]:
"""Execute code inside the container and return output and error"""
...Global helper functions maintain a mapping from user IDs to container instances, ensuring each user has a single dedicated container.
# Global mapping of user ID to DockerContainer
_docker_containers: Dict[str, DockerContainer] = {}
BASE_WORK_DIR = "/Users/"
def get_docker_container(user_id: str = "default", image: str = "python_code_executor:3.11", container_name: Optional[str] = None) -> DockerContainer:
"""Get or create a Docker container for a specific user"""
global _docker_containers
if container_name is None:
container_name = f"llamaindex-executor-{user_id}"
if user_id not in _docker_containers or _docker_containers[user_id] is None:
_docker_containers[user_id] = DockerContainer(image=image, container_name=container_name, base_work_dir=os.path.join(BASE_WORK_DIR, user_id))
_docker_containers[user_id].start()
os.makedirs(os.path.join(BASE_WORK_DIR, user_id), exist_ok=True)
return _docker_containers[user_id]
def close_docker_container(user_id: str = "default"):
global _docker_containers
if user_id in _docker_containers:
_docker_containers[user_id].stop()
del _docker_containers[user_id]
def close_all_docker_containers():
global _docker_containers
for c in _docker_containers.values():
c.stop()
_docker_containers.clear()Testing the Setup
A simple test function demonstrates dynamic container creation, code execution, and cleanup.
def test_docker_container():
# Start a container for a test user
container = get_docker_container(user_id="test_user")
code = """
import sys
print("Testing Docker container...")
print(f"Python version: {sys.version}")
"""
try:
result = container.execute(code, "python")
print("Execution result:")
print(f"Output: {result['output']}")
print(f"Error: {result['error']}")
finally:
# Clean up
close_docker_container("test_user")Running the test prints the expected output and confirms that the container can execute Python code safely.
Next Steps
The article ends by indicating that the next part will cover building the actual Tools and integrating them with the ReAct Agent, inviting readers to continue following the series.
AI Large Model Application Practice
Focused on deep research and development of large-model applications. Authors of "RAG Application Development and Optimization Based on Large Models" and "MCP Principles Unveiled and Development Guide". Primarily B2B, with B2C as a supplement.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
