README.md•5.18 kB
# Isolator CLI
`isolator` is a command-line tool written in Go designed to execute code snippets (Python, Go, JavaScript) within secure, ephemeral Docker containers. It enforces resource limits, timeouts, and security constraints, making it suitable as a backend for code execution sandboxing environments like the `isolator-mcp` server.
## Features
*   Executes code for specified languages (Python, Go, JavaScript).
*   Uses Docker containers for strong isolation.
*   Copies code files into the container using `docker cp` (via tar stream) rather than bind mounts to avoid common permission issues.
*   Enforces security constraints:
    *   Network isolation (`--network=none` by default).
    *   Read-only root filesystem (`--read-only=true` by default).
    *   Dropped Linux capabilities (`--cap-drop=ALL` by default).
    *   No new privileges (`no-new-privileges:true`).
*   Enforces resource limits:
    *   Timeout (`--timeout`).
    *   Memory limit (`--memory`).
    *   CPU limit (`--cpus`).
    *   Process limit (`--pids-limit`).
*   Returns results (status, exit code, stdout, stderr, duration) in JSON format.
*   Optional: Can commit the container to a new image on success (`--save-image`).
*   Optional: Can output a basic Dockerfile used (`--save-dockerfile`).
## Installation
1.  Ensure Go is installed (version 1.18+ recommended).
2.  Clone the repository (or ensure source code is present).
3.  Navigate to the project directory: `cd /path/to/isolator`
4.  Build the binary:
    ```bash
    go build -o isolator github.com/user/isolator
    ```
5.  Place the resulting `isolator` binary in a location accessible via your system's `PATH`, or call it directly using its full path.
## Usage
The primary command is `run`.
```
isolator run [flags]
```
### Flags
*   `--language, -l` (string, **required**): Language of the code (python, go, javascript).
*   `--dir, -d` (string, **required**): Path to the host directory containing input files. This directory's contents will be copied into the container.
*   `--entrypoint, -e` (string, **required**): Filename of the entrypoint script *within* the directory specified by `--dir`.
*   `--container-workdir` (string, **required**): Absolute path inside the container where files will be copied and execution will happen (e.g., `/workspace`).
*   `--timeout, -t` (duration, optional, default: 60s): Maximum execution time (e.g., `30s`, `1m`).
*   `--memory, -m` (int, optional, default: 256): Memory limit in MB.
*   `--cpus, -c` (float, optional, default: 0.5): CPU limit (e.g., 0.5 for half a core, 1 for a full core).
*   `--pids-limit` (int, optional, default: 64): Maximum number of processes allowed in the container.
*   `--network` (string, optional, default: "none"): Container network mode (e.g., "none", "bridge"). **Use "none" for maximum security unless network access is explicitly required.**
*   `--read-only` (bool, optional, default: true): Mount container root filesystem as read-only. The working directory where files are copied is still writable.
*   `--cap-drop` (string slice, optional, default: ["ALL"]): Linux capabilities to drop.
*   `--runtime` (string, optional, default: "docker"): Container runtime (currently only "docker" is implicitly supported).
*   `--save-image` (string, optional): Tag to save the container image as on success (e.g., `my-image:v1`).
*   `--save-dockerfile` (string, optional): Path to save the base Dockerfile used.
### Example
```bash
# Assuming /path/to/code contains main.py
./isolator run \
  --language python \
  --dir /path/to/code \
  --entrypoint main.py \
  --container-workdir /app \
  --timeout 30s
```
### Output
The command prints a JSON object to `stdout` containing the execution result:
```json
{
  "status": "success", // "success", "timeout", or "error"
  "exitCode": 0,
  "stdout": "Output from the script...\n",
  "stderr": "",
  "durationMs": 520,
  "error": null, // or error message string if status is "error" or "timeout"
  "imageTag": null // or the tag if --save-image was used and successful
}
```
## Architecture
*   Built using Go and the Cobra CLI library.
*   Uses the official Docker Go SDK (`github.com/docker/docker/client`) to interact with the Docker daemon.
*   Creates a container based on the specified language's base image.
*   Creates an in-memory tar archive of the source directory provided via `--dir`.
*   Uses the `CopyToContainer` Docker API to copy the tar archive into the specified `--container-workdir` within the container *after* the container is created but *before* it is started.
*   Starts the container.
*   Waits for container completion or timeout.
*   Retrieves container logs (stdout/stderr).
*   Removes the container automatically.
*   Formats and prints the result as JSON.
This `CopyToContainer` approach avoids common permission issues associated with bind mounts when the host user differs from the container user.
**Note:** This tool expects the required Docker base images (e.g., `python:3.11-alpine`, `golang:1.21-alpine`) to be already pulled on the host system. It does not automatically pull missing images. You can pull images using `docker pull <image_name>`.