From 98c31bf00a912ef82e2c4c23d561bdb5f18414e2 Mon Sep 17 00:00:00 2001 From: Anton Date: Fri, 1 Dec 2023 01:35:58 +0500 Subject: [PATCH] doc: adding a sandbox --- docs/add-sandbox.md | 131 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 docs/add-sandbox.md diff --git a/docs/add-sandbox.md b/docs/add-sandbox.md new file mode 100644 index 0000000..12b0f05 --- /dev/null +++ b/docs/add-sandbox.md @@ -0,0 +1,131 @@ +# Adding a sandbox + +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. + +## Python + +First, let's create a Docker image capable of running Python with some third-party packages: + +```sh +cd /opt/codapi +mkdir images/python +touch images/python/Dockerfile +touch images/python/requirements.txt +``` + +Fill the `Dockerfile`: + +```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: + +```sh +docker build --file images/python/Dockerfile --tag codapi/python:latest images/python/ +``` + +And register the image as a Codapi _box_ in `boxes.json`: + +```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 edit `commands.json`: + +```json +{ + // ... + "python": { + "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 the `python` sandbox, save their code to the `main.py` file, then run it in the `python` box (Docker container) using the `python main.py` shell command. + +What if we want to add another command (say, `test`) to the same sandbox? Let's edit `commands.json` again: + +```json +{ + // ... + "python": { + "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 `config.json`). + +To apply the changed configuration, restart Codapi (as root): + +```sh +systemctl restart codapi.service +``` + +And try running some Python code: + +```sh +curl -H "content-type: application/json" -d '{ "sandbox": "python", "command": "run", "files": {"": "print(42)" }}' http://localhost:1313/v1/exec +``` + +Which produces the following output: + +```json +{ + "id": "python_run_7683de5a", + "ok": true, + "duration": 252, + "stdout": "42\n", + "stderr": "" +} +```