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?