https://github.com/sohaibqasem/dockexec
dockexec is a lightweight Go service to safely execute LLM-generated Python (and other languages) inside Docker. It supports ephemeral & pooled containers, utilization-aware schedulers, configurable resource limits, and optional gVisor integration for stronger isolation.
https://github.com/sohaibqasem/dockexec
docker generated-code go llm python sandbox
Last synced: 3 months ago
JSON representation
dockexec is a lightweight Go service to safely execute LLM-generated Python (and other languages) inside Docker. It supports ephemeral & pooled containers, utilization-aware schedulers, configurable resource limits, and optional gVisor integration for stronger isolation.
- Host: GitHub
- URL: https://github.com/sohaibqasem/dockexec
- Owner: sohaibqasem
- License: mit
- Created: 2025-09-12T14:09:49.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2025-09-14T21:13:39.000Z (3 months ago)
- Last Synced: 2025-09-14T21:21:41.468Z (3 months ago)
- Topics: docker, generated-code, go, llm, python, sandbox
- Language: Go
- Homepage:
- Size: 1.31 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# Dockexec




**dockexec** is a lightweight Go service to safely run Python (and future languages) inside Docker.
It supports ephemeral one-off containers, pooled warm containers, utilization-aware scheduling, and optional gVisor isolation.
---
## Features
- **Ephemeral execution** → runs each job in a fresh container (isolated but slower).
- **Pooled execution** → reuses warm containers for faster execution.
- **Scheduling modes** → round-robin (default) or utilization-based.
- **Resource limits** → configurable memory, CPU, and network.
- **Log levels** → off, basic, or verbose with container stats.
- **gVisor support** → syscall-level isolation with `runsc` runtime.
- **Cross-platform** → works on Linux, macOS, and Windows.
- **Extensible** → design allows multi-language execution in the future.
---
## Setup
### 1. Install Go dependencies
```bash
go mod tidy
```
### 2. Build the Docker image
```bash
docker build -t python-executor:latest -f docker/Dockerfile .
```
### 3. Run the service
Ephemeral mode:
```bash
EXECUTOR_MODE=docker PORT=9090 DOCKER_IMAGE=python-executor:latest go run main.go
```
Pool mode (3 containers):
```bash
EXECUTOR_MODE=pool POOL_SIZE=3 PORT=9090 DOCKER_IMAGE=python-executor:latest go run main.go
```
---
## Environment Variables
| Variable | Default | Description |
|------------------|--------------------------|--------------------------------------------------|
| `EXECUTOR_MODE` | `docker` | `docker` (ephemeral) or `pool` (container pool). |
| `DOCKER_IMAGE` | `python-executor:latest` | Docker image used for execution. |
| `DOCKER_RUNTIME` | *(unset)* | `runc` (default) or `runsc` (gVisor). |
| `DOCKER_MEMORY` | `256m` | Memory limit per container (ephemeral). |
| `DOCKER_CPUS` | `0.5` | CPU limit per container (ephemeral). |
| `POOL_SIZE` | `3` | Number of containers in pool mode. |
| `POOL_MEMORY` | `256m` | Memory limit per pooled container. |
| `POOL_CPUS` | `0.5` | CPU limit per pooled container. |
| `SCHEDULER_MODE` | `roundrobin` | `roundrobin` (default) or `utilization`. |
| `DEBUG` | *(unset)* | Log level: `true` (basic) or `verbose` (detailed). |
| `PORT` | `8080` | API port. |
---
## API
**POST** `/run`
### Request
```json
{ "code": "print(2+3)" }
```
### Response
```json
{
"jobId": 1756386494986306000,
"stdout": "5\n",
"stderr": "",
"exitCode": 0,
"timeMs": 200
}
```
---
## Example
```bash
curl -X POST localhost:9090/run \\
-H "Content-Type: application/json" \\
-d '{"code":"print(10*10)"}'
```
Response:
```json
{
"jobId": 1756386494986306000,
"stdout": "100\n",
"stderr": "",
"exitCode": 0,
"timeMs": 215
}
```
---
## Scheduling Modes
When using **pooled executor mode**, you can control how jobs are assigned:
- **Round Robin (default)**
Cycles evenly through containers.
```bash
EXECUTOR_MODE=pool SCHEDULER_MODE=roundrobin go run main.go
```
- **Utilization-Based**
Picks the container with the lowest CPU/memory load (via `docker stats`).
```bash
EXECUTOR_MODE=pool SCHEDULER_MODE=utilization go run main.go
```
Slight overhead (~2s polling interval).
---
## Log Levels
Use the `DEBUG` environment variable to control logging:
Basic:
```bash
DEBUG=true PORT=9090 EXECUTOR_MODE=pool go run main.go
```
Example log:
```
[DEBUG] Job 1757649737223951000 → Goroutine 53 → Container py-pool-a (mem=256m, cpu=0.5)
```
Verbose:
```bash
DEBUG=verbose PORT=9090 EXECUTOR_MODE=pool go run main.go
```
Example log:
```
[DEBUG] Job 1757649737223951000 → Utilization snapshot:
- py-pool-a → CPU=0.00%, Mem=0.00 MiB
- py-pool-b → CPU=12.34%, Mem=45.00 MiB
- py-pool-c → CPU=0.50%, Mem=10.50 MiB
[DEBUG] Job 1757649737223951000 → picked py-pool-b (CPU=12.34%, Mem=45.00 MiB)
```
---
## Using gVisor
This executor supports running containers under **gVisor** for syscall-level isolation.
1. Follow the official installation instructions:
https://gvisor.dev/docs/user_guide/install/
2. Verify:
```bash
docker run --rm --runtime=runsc hello-world
```
3. Run with gVisor:
```bash
EXECUTOR_MODE=docker DOCKER_RUNTIME=runsc go run main.go
```
Notes:
- On macOS, requires Colima or another Linux VM.
- Performance impact:
- CPU-heavy jobs → minimal.
- Network/DB/syscall-heavy jobs → noticeable slowdown.
---
## Windows Support
This project works on Windows as well as Linux/macOS.
The executor uses Go’s `os.TempDir()` automatically, so no manual changes are needed.
- **Environment variables**
- **PowerShell**
```powershell
$env:EXECUTOR_MODE="pool"
$env:POOL_SIZE="3"
$env:DOCKER_IMAGE="python-executor:latest"
go run main.go
```
- **CMD**
```cmd
set EXECUTOR_MODE=pool
set POOL_SIZE=3
set DOCKER_IMAGE=python-executor:latest
go run main.go
```
- **Git Bash**
```bash
export EXECUTOR_MODE=pool
export POOL_SIZE=3
export DOCKER_IMAGE=python-executor:latest
go run main.go
```
---
## What's Next
1. **Session Mode** *(optional)*
- Containers mapped 1:1 to users.
- Preserves imports/variables across requests.
2. **Multi-Language Support** *(optional)*
- Add an `EXECUTOR_CMD` env variable (default: `python`).
- Combined with `DOCKER_IMAGE`, this allows execution of Node.js, Ruby, etc.