Skip to main content
SimpleBox runs any OCI container image, so you’re not limited to Python. Use it to run Node.js, Go, Rust, shell scripts, or any CLI tool — just pick the right image and call exec().

What you’ll build

A script that:
  1. Runs Node.js code inside a node:20-slim image
  2. Runs a shell script inside an alpine:latest image
  3. Installs and uses CLI tools
  4. Runs multiple languages in the same box

Prerequisites

pip install boxlite
Requires Python 3.10+.

Step 1: Run Node.js code

Use the node:20-slim image to run JavaScript inside a sandbox.
run_node.py
import asyncio
import boxlite


async def main():
    async with boxlite.SimpleBox(image="node:20-slim") as box:
        result = await box.exec(
            "node", "-e",
            "const data = Array.from({length: 5}, (_, i) => i * i);\n"
            "console.log(JSON.stringify(data));"
        )
        print(f"Output: {result.stdout}")  # [0,1,4,9,16]


if __name__ == "__main__":
    asyncio.run(main())
What’s happening:
  • SimpleBox pulls the node:20-slim image (cached after first use)
  • exec("node", "-e", "...") runs the JavaScript code inside the VM
  • Output is captured in result.stdout just like any other command

Step 2: Run a shell script

Use alpine:latest for a minimal environment, and run multi-line scripts with sh -c.
run_shell.py
import asyncio
import boxlite


async def main():
    async with boxlite.SimpleBox(image="alpine:latest") as box:
        # Run a multi-line shell script
        result = await box.exec("sh", "-c", """
echo "System info:"
echo "  Hostname: $(hostname)"
echo "  Kernel: $(uname -r)"
echo "  Memory: $(free -m | awk '/Mem:/ {print $2}') MB"
echo "  Disk: $(df -h / | awk 'NR==2 {print $4}') available"
""")
        print(result.stdout)


if __name__ == "__main__":
    asyncio.run(main())

Step 3: Install and run tools

Install packages inside the box using the image’s package manager, then use them.
install_tools.py
import asyncio
import boxlite


async def main():
    # Alpine — use apk
    async with boxlite.SimpleBox(image="alpine:latest") as box:
        await box.exec("apk", "add", "--no-cache", "curl", "jq")

        result = await box.exec(
            "sh", "-c",
            "curl -s https://api.github.com/zen"
        )
        print(f"GitHub zen: {result.stdout}")

    # Ubuntu — use apt-get
    async with boxlite.SimpleBox(image="ubuntu:22.04") as box:
        await box.exec(
            "sh", "-c",
            "apt-get update -qq && apt-get install -y -qq curl > /dev/null"
        )

        result = await box.exec(
            "sh", "-c",
            "curl -s https://api.github.com/zen"
        )
        print(f"GitHub zen: {result.stdout}")


if __name__ == "__main__":
    asyncio.run(main())

Common images and package managers

ImagePackage managerInstall command
alpine:latestapkapk add --no-cache curl
ubuntu:22.04apt-getapt-get update && apt-get install -y curl
python:slimpip + apt-getpip install requests
node:20-slimnpm + apt-getnpm install express

Step 4: Mix languages in one box

The node:20-bookworm image includes both Node.js and Python 3, so you can combine languages in a single box without installing anything.
multi_language.py
import asyncio
import boxlite


async def main():
    async with boxlite.SimpleBox(image="node:20-bookworm") as box:
        # Run Python — already included in the bookworm image
        py_result = await box.exec(
            "python3", "-c", "print('Hello from Python')"
        )
        print(f"Python: {py_result.stdout.strip()}")

        # Run Node.js
        node_result = await box.exec(
            "node", "-e", "console.log('Hello from Node.js')"
        )
        print(f"Node.js: {node_result.stdout.strip()}")

        # Use Python to generate data, Node.js to process it
        await box.exec("sh", "-c",
            "python3 -c \"import json; print(json.dumps([1,2,3,4,5]))\" > /tmp/data.json"
        )

        result = await box.exec("sh", "-c",
            "node -e \"const d = require('/tmp/data.json'); console.log('Sum:', d.reduce((a,b) => a+b, 0))\""
        )
        print(f"Cross-language: {result.stdout.strip()}")


if __name__ == "__main__":
    asyncio.run(main())
Use slim or minimal images for faster startup. Full images like ubuntu:latest work but are larger and slower to pull on first use. After the first pull, images are cached locally.

Choosing the right image

I want to run…Recommended imageWhy
Node.js / JavaScriptnode:20-slimNode.js pre-installed, minimal size
Pythonpython:slimPython pre-installed (or use CodeBox)
Shell scriptsalpine:latestSmallest image (~5 MB), fast boot
System tools (curl, git, etc.)alpine:latest or ubuntu:22.04Alpine for size, Ubuntu for compatibility
Multiple languagesnode:20-bookwormPython 3 + Node.js pre-installed
Compiled binariesalpine:latestCopy your binary in, run it

What’s next?

Run services with port forwarding

Start HTTP servers, databases, or APIs inside a box and access them from the host.

Upload & download files

Copy files into the box, process them, and retrieve results.

Handle errors and debug

Catch exceptions, handle timeouts, and debug failures.

SimpleBox API reference

Full API docs for SimpleBox constructor options and methods.