Quickstart
Five minutes from here you’ll have a Python app running as an auto-scaled pod, published as an immutable version, and answering invokes — over both the API and the app’s own direct FQDN.
We’ll use the managed Python runtime: you write one file with a handler function, the platform compiles it and runs the HTTP server for you. (For bring-your-own-image — your own FastAPI/Flask server in a container — see Concepts → Code source.)
Prerequisites
- The
dodilCLI installed and authenticated — set your token and endpoint withdodil ignite config set token <token>anddodil ignite config set api_endpoint rpc.dev.dodil.io:443(orexport DODIL_TOKEN=<token>). See CLI Basics. - Your org name. App IDs are
org:nameon the CLI (theorg:prefix is optional once your org is in config). We’ll useacme-corpbelow.
1. Write the handler
The managed runtime loads a top-level handler from handler.py. The contract is:
def handler(payload: bytes, ctx: dict) -> Anypayloadis the raw request body (bytes) — you parse JSON yourself.ctxcarries the execution context:execution_id,function_id(org/name),organization_id.- The return value is encoded for you: a
dict/listbecomes JSON, astrbecomes UTF-8 text,bytesare sent as-is.
Create handler.py:
import json
from datetime import datetime, timezone
def handler(payload, ctx):
# The runtime hands you the raw body; parse it yourself.
try:
event = json.loads(payload) if payload else {}
except (TypeError, ValueError):
event = {}
name = event.get("name", "world")
return {
"greeting": f"Hello, {name}!",
"execution_id": ctx.get("execution_id", ""),
"received_at": datetime.now(timezone.utc).isoformat(),
}That’s the whole app. You do not write an HTTP server, bind a port, or import an SDK — the managed runtime wraps handler in its own server and binds $PORT for you.
Only packages pre-installed in the runtime (numpy, pandas, requests, httpx, pydantic, boto3, …) are importable in the default pool mode. To add your own dependencies, see Recipes → Deploy a Python app.
2. Create the app
This registers the app’s metadata (name, runtime, resources) — no code yet.
dodil ignite app create greet --runtime pythonThe app id is now acme-corp:greet. Use that ID for every command that follows.
3. Save the code to the draft slot
draft save uploads your code into the mutable draft (version 0):
dodil ignite draft save acme-corp:greet -c ./handler.py4. Publish
Publishing snapshots the draft into an immutable, numbered version and points the app’s active_version at it. Python needs no separate compile step.
dodil ignite draft publish acme-corp:greetAfter the first publish the app gets a direct FQDN — `greet-acme-corp.ignite.dodil.cloud` (port 80). Confirm it landed:
dodil ignite app get acme-corp:greet -o json | jq '{active_version, public_urls}'5. Invoke
dodil ignite invoke acme-corp:greet -p '{"name": "Ada"}'You’ll get back the handler’s JSON:
{
"greeting": "Hello, Ada!",
"execution_id": "01J...",
"received_at": "2026-05-28T12:00:00+00:00"
}You can also hit the direct FQDN with any HTTP client — still Bearer-authed:
curl -sS -X POST "https://greet-acme-corp.ignite.dodil.cloud/" \
-H "Authorization: Bearer $DODIL_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Ada" }'First call may pause. Idle apps scale to zero. The first request to a cold app waits while a pod starts (0→1), then proceeds — it isn’t rejected. Details in API Reference → Cold starts vs warm pods.
6. Check the execution
Every invoke produces an execution record with status and metrics. dodil ignite invoke prints the execution id; fetch its details:
dodil ignite execution get <exec-id>You’ll see the status (COMPLETED), the result, and metrics (including cold_start_ms and billed_duration_ms).
What you just built
| Step | CLI command | What happened |
|---|---|---|
| 2 | app create | App metadata created (version 0, no code) |
| 3 | draft save | Code uploaded to the draft slot |
| 4 | draft publish | Draft snapshotted into immutable version 1, set active, FQDN assigned |
| 5 | invoke / FQDN curl | Pod ran the active version, returned the response |
| 6 | execution get | Per-invoke status + metrics |
Next steps
- Core Concepts — App, code sources, runtimes, scaling, lifecycle states, executions
- API Reference — every ComputeService RPC, with gRPC + HTTP contracts
- Recipes → Deploy a Python app — the same flow with custom dependencies, cold-start tuning, and scaling
- Recipes → Expose an app as an MCP tool — turn this app into an agent tool