{ "cells": [ { "cell_type": "markdown", "id": "3c52f346", "metadata": {}, "source": [ "# 03 – Using Dockyter with an API backend\n", "\n", "This notebook demonstrates how to use Dockyter through a **remote HTTP API**\n", "instead of talking directly to the local Docker daemon.\n", "\n", "From the notebook user’s point of view, the interface stays the same:\n", "\n", "- `%%docker` – run a whole cell in a single container (but via the API).\n", "- `%docker` – configure Docker mode for `!` commands (via the API).\n", "- `%docker_backend api ` – switch Dockyter to the API backend.\n", "- `%docker_status` – inspect the current configuration.\n", "\n", "**Prerequisites**\n", "\n", "- `dockyter` installed in this environment (`pip install dockyter`).\n", "- The example Dockyter API server running locally, for example:\n", "\n", "```bash\n", "uv run uvicorn docs.api_example.server:app --host 127.0.0.1 --port 8000\n", "```" ] }, { "cell_type": "code", "execution_count": 2, "id": "942d9e7b", "metadata": {}, "outputs": [], "source": [ "# Load the Dockyter IPython extension\n", "%load_ext dockyter" ] }, { "cell_type": "markdown", "id": "6b22eecb", "metadata": {}, "source": [ "## 1. Switch Dockyter to the API backend\n", "\n", "By default, Dockyter uses the **local Docker daemon** backend.\n", "\n", "Here we switch to the **API backend** pointing to the example server\n", "running on `http://127.0.0.1:8000`.\n", "\n", "The `%docker_backend` magic:\n", "\n", "- `%docker_backend docker` → use local Docker daemon\n", "- `%docker_backend api ` → use HTTP API at the given URL\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "5830c804", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Switched backend to APIBackend (http://127.0.0.1:8000).\n", "=== Dockyter Backend Status ===\n", "Dockyter backend type: API\n", "Dockyter backend status: available\n", "Dockyter backend status: API backend reachable at http://127.0.0.1:8000\n", "Dockyer redirection for '!': off\n" ] } ], "source": [ "%docker_backend api http://127.0.0.1:8000" ] }, { "cell_type": "markdown", "id": "a5aeb87e", "metadata": {}, "source": [ "## 2. `%%docker` cells executed via the API backend\n", "\n", "`%%docker` still works exactly the same from the notebook:\n", "\n", "- the cell is executed in a **single container**,\n", "- the image and arguments are passed as in the local Docker example,\n", "- but the actual `docker run ...` happens on the **API server side**.\n", "\n", "Below we run a simple Ubuntu container via the API backend." ] }, { "cell_type": "code", "execution_count": 8, "id": "ef1c5940", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello from the API backend inside ubuntu:22.04\n", "/\n", "bin\n", "boot\n", "dev\n", "etc\n", "home\n", "lib\n", "lib32\n", "lib64\n", "libx32\n", "media\n", "mnt\n", "opt\n", "proc\n", "root\n", "run\n", "sbin\n", "srv\n", "sys\n", "tmp\n", "usr\n", "var\n", "\n" ] } ], "source": [ "%%docker ubuntu:22.04\n", "echo \"Hello from the API backend inside ubuntu:22.04\"\n", "pwd\n", "ls /" ] }, { "cell_type": "markdown", "id": "730dac10", "metadata": {}, "source": [ "## 3. `%docker` + `!` commands routed through the API backend\n", "\n", "`%docker` configures Dockyter to:\n", "\n", "- remember the Docker image/arguments,\n", "- and reroute all `!` shell commands through the selected backend\n", " (here: the API backend).\n", "\n", "From the notebook user perspective:\n", "\n", "- `!` still looks like a local shell command,\n", "- but in reality it runs **inside a container on the API server host**." ] }, { "cell_type": "code", "execution_count": 9, "id": "5d00e6af", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected\n", "\n", "This was executed via Dockyter's API backend\n", "\n", "Linux 4cd02e6b1adc 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux\n", "\n" ] } ], "source": [ "%docker ubuntu:22.04\n", "\n", "!echo \"This was executed via Dockyter's API backend\"\n", "!uname -a" ] }, { "cell_type": "markdown", "id": "8f93c0f2", "metadata": {}, "source": [ "## 4. Notes on security and deployment\n", "\n", "In this example, the API backend is:\n", "\n", "- running on `127.0.0.1:8000`,\n", "- started manually with `uvicorn docs.api_example.server:app ...`,\n", "- and is intended for **local / trusted** environments only.\n", "\n", "A real-world deployment should:\n", "\n", "- put the API behind authentication and transport security (HTTPS),\n", "- restrict which images/arguments can be used,\n", "- and run on a hardened host.\n", "\n", "From Dockyter’s point of view, the only requirement is that the API:\n", "\n", "- exposes `GET /health` returning a 2xx status when available,\n", "- exposes `POST /execute` with a JSON body:\n", "\n", " ```json\n", " {\n", " \"cmd\": \"echo hello\",\n", " \"args\": \"-v /tmp:/tmp ubuntu:22.04\"\n", " }\n", "```\n", "\n", "and returns JSON of the form:\n", "\n", "```json\n", "{\n", " \"stdout\": \"hello\",\n", " \"stderr\": \"\"\n", "}\n", "```\n", "\n", "Everything else (auth, routing, logging, etc.) is up to the API implementation." ] } ], "metadata": { "kernelspec": { "display_name": "dockyter", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.0" } }, "nbformat": 4, "nbformat_minor": 5 }