A sandbox is an isolated execution environment for running code snippets. A sandbox is typically implemented as one or more Docker containers. A sandbox supports at least one command (usually the run
one), but it can support more (like test
or any other).
Codapi comes with a single sh
sandbox preinstalled, but you can easily add others. Let's see some examples.
First, let's create a Docker image capable of running Python with some third-party packages:
cd /opt/codapi
mkdir images/python
touch images/python/Dockerfile
touch images/python/requirements.txt
Fill the Dockerfile
:
FROM python:3.11-alpine
RUN adduser --home /sandbox --disabled-password sandbox
COPY requirements.txt /tmp
RUN pip install --no-cache-dir -r /tmp/requirements.txt && rm -f /tmp/requirements.txt
USER sandbox
WORKDIR /sandbox
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
And the requirements.txt
:
numpy==1.26.2
pandas==2.1.3
Build the image:
docker build --file images/python/Dockerfile --tag codapi/python:latest images/python/
And register the image as a Codapi box in configs/boxes.json
:
{
// ...
"python": {
"image": "codapi/python"
}
}
Finally, let's configure what happens when the client executes the run
command in the python
sandbox. To do this, we create configs/commands/python.json
:
{
"run": {
"engine": "docker",
"entry": "main.py",
"steps": [
{
"box": "python",
"command": ["python", "main.py"]
}
]
}
}
This is essentially what it says:
When the client executes the
run
command in thepython
sandbox, save their code to themain.py
file, then run it in thepython
box (Docker container) using thepython main.py
shell command.
What if we want to add another command (say, test
) to the same sandbox? Let's edit configs/commands/python.json
again:
{
"run": {
// ...
},
"test": {
"engine": "docker",
"entry": "test_main.py",
"steps": [
{
"box": "python",
"command": ["python", "-m", "unittest"],
"noutput": 8192
}
]
}
}
Besides configuring a different shell command, here we increased the maximum output size to 8Kb, as tests tend to be quite chatty (you can see the default value in configs/config.json
).
To apply the changed configuration, restart Codapi (as root):
systemctl restart codapi.service
And try running some Python code:
curl -H "content-type: application/json" -d '{ "sandbox": "python", "command": "run", "files": {"": "print(42)" }}' http://localhost:1313/v1/exec
Which produces the following output:
{
"id": "python_run_7683de5a",
"ok": true,
"duration": 252,
"stdout": "42\n",
"stderr": ""
}