Container runtime
Each sandbox runs in an isolated Linux container with Python, Node.js, and common development tools pre-installed. For a complete list of pre-installed software and how to customize the container image, see Dockerfile reference.
Install additional software at runtime using standard package managers:
# Python packagespip install scikit-learn tensorflow
# Node.js packagesnpm install express
# System packages (requires apt-get update first)apt-get update && apt-get install -y redis-serverThe container provides a standard Linux filesystem. You can read and write anywhere you have permissions.
Standard directories:
/workspace- Default working directory for user code/tmp- Temporary files/home- User home directory/usr/bin,/usr/local/bin- Executable binaries
Example:
await sandbox.writeFile('/workspace/app.py', 'print("Hello")');await sandbox.writeFile('/tmp/cache.json', '{}');await sandbox.exec('ls -la /workspace');Processes run as you'd expect in a regular Linux environment.
Foreground processes (exec()):
const result = await sandbox.exec('npm test');// Waits for completion, returns outputBackground processes (startProcess()):
const process = await sandbox.startProcess('node server.js');// Returns immediately, process runs in backgroundThe container runtime includes optimizations for long-running sandboxes with many processes:
- Active processes are kept in memory for fast access
- Completed processes are persisted to disk (
/tmp/sandbox-internal/processes/) and freed from memory to prevent unbounded growth - Stream listeners are automatically cleaned up when streaming operations complete or are cancelled
These optimizations ensure stable memory usage even for sandboxes that execute hundreds or thousands of processes over their lifetime. Process history remains queryable after completion via the standard process APIs.
Outbound connections work:
curl https://api.example.com/datapip install requestsnpm install expressInbound connections require port exposure:
const { hostname } = new URL(request.url);await sandbox.startProcess('python -m http.server 8000');const exposed = await sandbox.exposePort(8000, { hostname });console.log(exposed.exposedAt); // Public URLLocalhost works within sandbox:
redis-server & # Start serverredis-cli ping # Connect locallyBetween sandboxes (isolated):
- Each sandbox is a separate container
- Filesystem, memory and network are all isolated
Within sandbox (shared):
- All processes see the same files
- Processes can communicate with each other
- Environment variables are session-scoped
To run untrusted code, use separate sandboxes per user:
const sandbox = getSandbox(env.Sandbox, `user-${userId}`);Cannot:
- Load kernel modules or access host hardware
- Run nested containers (no Docker-in-Docker)
- Architecture - How containers fit in the system
- Security model - Container isolation details
- Sandbox lifecycle - Container lifecycle management
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Directory
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- © 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark