Skip to content

Latest commit

 

History

History
386 lines (318 loc) · 7.83 KB

File metadata and controls

386 lines (318 loc) · 7.83 KB

🐳 Code Execution Engine

Overview

Secure, isolated code execution using Docker containers with a universal runtime supporting Python, Node.js, Java, and C++. File watching enables automatic code refresh and hot reload.


✨ Key Features

1. Universal Container

  • Single Docker image for all languages
  • Alpine Linux base (lightweight)
  • Pre-installed runtimes
  • Fast startup (<1s)

2. Secure Sandboxing

  • Container isolation
  • Non-root user execution
  • Resource limits (CPU, memory, time)
  • Network isolation
  • Read-only filesystem

3. File Watching & Hot Reload

  • Monitors file changes
  • Auto-detects modifications
  • Refreshes code in container
  • Preserves running state
  • 300ms debounce

4. Multi-Language Support

  • Python 3.11: Full standard library
  • Node.js 18: NPM packages included
  • Java 17: JDK with javac
  • C++ (GCC 12): g++ compiler

🎯 Usage

Quick Execution

# Click "Run" button or Ctrl+Enter
# Automatically detects language and executes

Python    → python3 main.py
JavaScript → node app.js
Java       → javac Main.java && java Main
C++        → g++ main.cpp -o main && ./main

Manual Execution

# Python
python3 script.py

# Node.js with packages
npm install express
node server.js

# Java
javac HelloWorld.java
java HelloWorld

# C++ with flags
g++ -std=c++17 -o program main.cpp
./program

🔧 Technical Details

Docker Image

FROM alpine:3.18

# Install runtimes
RUN apk add --no-cache \
    python3 py3-pip \
    nodejs npm \
    openjdk17 \
    g++ make

# Create non-root user
RUN adduser -D -u 1000 coderunner

# Set working directory
WORKDIR /workspace
USER coderunner

Container Configuration

// Resource limits
{
  memory: '512m',        // 512MB RAM
  cpus: '1.0',          // 1 CPU core
  pidsLimit: 100,       // Max 100 processes
  networkMode: 'none',  // No internet
  readonlyRootfs: false // Allow file creation
}

// Security options
{
  securityOpt: ['no-new-privileges'],
  user: '1000:1000',    // Non-root
  privileged: false
}

Execution Flow

┌─────────────────┐
│  File Changed   │
│  (Editor Save)  │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  File Watcher   │
│  (300ms delay)  │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  Copy to        │
│  Container      │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  Execute Code   │
│  (Auto-detect)  │
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│  Stream Output  │
│  (WebSocket)    │
└─────────────────┘

🚀 Features in Detail

1. Container Lifecycle

// Create container
const container = await docker.createContainer({
  Image: 'ai-ide-universal-runner',
  WorkingDir: '/workspace',
  User: 'coderunner',
  HostConfig: {
    Memory: 536870912,  // 512MB
    NanoCpus: 1000000000, // 1 CPU
    NetworkMode: 'none'
  }
});

// Start container
await container.start();

// Execute command
const exec = await container.exec({
  Cmd: ['python3', 'script.py'],
  AttachStdout: true,
  AttachStderr: true
});

// Stream output
const stream = await exec.start();
stream.pipe(terminalOutput);

// Cleanup
await container.stop();
await container.remove();

2. File Watching

// Monitor file changes
const watcher = chokidar.watch('/workspace', {
  ignored: /(^|[\/\\])\../, // Ignore hidden files
  persistent: true,
  ignoreInitial: true,
  awaitWriteFinish: {
    stabilityThreshold: 300,
    pollInterval: 100
  }
});

// On change
watcher.on('change', async (path) => {
  console.log(`File changed: ${path}`);
  await syncToContainer(path);
  await reloadCode();
});

3. Language Detection

const detectLanguage = (filename) => {
  const ext = path.extname(filename);
  const languages = {
    '.py': {
      runtime: 'python3',
      command: (file) => `python3 ${file}`
    },
    '.js': {
      runtime: 'node',
      command: (file) => `node ${file}`
    },
    '.java': {
      runtime: 'java',
      command: (file) => {
        const className = path.basename(file, '.java');
        return `javac ${file} && java ${className}`;
      }
    },
    '.cpp': {
      runtime: 'g++',
      command: (file) => {
        const output = file.replace('.cpp', '');
        return `g++ ${file} -o ${output} && ./${output}`;
      }
    }
  };
  return languages[ext];
};

⚙️ Configuration

Build Docker Image

# Windows
cd runner-images\universal
docker build -t ai-ide-universal-runner .

# Linux/Mac
cd runner-images/universal
docker build -t ai-ide-universal-runner .

# Or use script
scripts\build-runners.bat   # Windows
./scripts/build-runners.sh  # Linux/Mac

Adjust Resource Limits

// backend/src/services/execution.service.js
const containerConfig = {
  memory: '1g',        // Increase to 1GB
  cpus: '2.0',        // Use 2 CPU cores
  pidsLimit: 200      // Allow 200 processes
};

Enable Network Access

// WARNING: Security risk!
HostConfig: {
  NetworkMode: 'bridge'  // Allow internet
}

📦 Package Management

Python Packages

# Install in container
pip install requests pandas numpy

# Or create requirements.txt
# File: requirements.txt
requests==2.31.0
pandas==2.0.0

# Install
pip install -r requirements.txt

Node.js Packages

// Create package.json
npm init -y

// Install packages
npm install express axios lodash

// Use in code
const express = require('express');
const app = express();

Java Dependencies

// Maven or Gradle not included by default
// Manual JAR management required
javac -cp "lib/*:." Main.java
java -cp "lib/*:." Main

📊 Performance

Language Startup Time Execution Time (Hello World)
Python ~150ms ~50ms
Node.js ~100ms ~30ms
Java ~300ms ~100ms (compile) + 50ms (run)
C++ ~200ms ~150ms (compile) + 10ms (run)

Container Reuse

  • Containers persist between executions
  • 5-minute idle timeout
  • Faster subsequent runs
  • Shared filesystem

🔒 Security Considerations

Isolation Layers

1. Docker container isolation
2. Non-root user (UID 1000)
3. No network access
4. Resource limits
5. Read-only system files
6. Process limits

Prevented Attacks

✅ Network attacks (no internet) ✅ Fork bombs (PID limit) ✅ Memory bombs (memory limit) ✅ CPU hogging (CPU limit) ✅ Privilege escalation (non-root) ✅ File system attacks (user permissions)


🐛 Troubleshooting

Issue: Container not starting

Solution:

# Check Docker is running
docker ps

# Check image exists
docker images | grep ai-ide-universal-runner

# Build image if missing
cd runner-images/universal
docker build -t ai-ide-universal-runner .

Issue: Code not executing

Solution:

  • Check file syntax errors
  • Verify language runtime installed in container
  • Check container logs: docker logs <container_id>
  • Ensure file permissions are correct

Issue: Timeout errors

Solution:

// Increase timeout
const EXECUTION_TIMEOUT = 30000; // 30 seconds (default: 10s)

📖 References