Python Runtime Deployment (F2.2)
Feature: F2.2 — Python (Django/Flask/FastAPI) Deployment
Status: Completed
Package: System Layer (build_manager.py,docker_manager.py,python.yml), Fastify API (modules/build)
1. Overview
Vexlyx provides zero-config, native runtime deployment for Python web applications, including:
- Django: Auto-detects WSGI modules, runs
python manage.py collectstatic --noinput, and bootsgunicorn <module>.wsgi:application. - Flask: Auto-detects WSGI entry points (
app:app,main:app,wsgi:app,application:app) and runsgunicorn. - FastAPI: Auto-detects ASGI entry points (
main:app,app.main:app,app:app) and runsuvicornwith multiple workers. - Python Version Pinning: Automatically respects
.python-version,runtime.txt,pyproject.toml, or project environment variables (PYTHON_VERSION/NIXPACKS_PYTHON_VERSION) to pin Python to 3.10, 3.11, 3.12, or any custom version. - Dual-Phase Environment Injection: Injects all encrypted project environment variables during both Nixpacks image builds and Docker Compose runtime.
2. Architecture & Execution Flow
┌─────────────────────────┐
│ Git Connect / Workspace │
└────────────┬────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Framework Detection Heuristics (`build_manager.py plan`) │
│ - Django: manage.py, requirements.txt, pyproject.toml │
│ - Flask: flask in deps, app.py / main.py / wsgi.py │
│ - FastAPI: fastapi in deps, main.py / app/main.py │
│ - Version Pinning: .python-version, runtime.txt, pyproject │
└────────────┬────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Build Phase (`nixpacks build`) │
│ - Build command (Django): python manage.py collectstatic │
│ - Start command override: gunicorn / uvicorn │
│ - Cache key: `vexlyx-<projectId>` │
│ - Environment variables: `--env NIXPACKS_PYTHON_VERSION=…` │
└────────────┬────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Deploy Phase (`docker_manager.py deploy`) │
│ - Template: `system/templates/docker-compose/python.yml` │
│ - HOST=0.0.0.0, PORT=8000, PYTHONUNBUFFERED=1 │
│ - GUNICORN_CMD_ARGS=--bind=0.0.0.0:8000 │
│ - Traefik dynamic router & load balancer on port 8000 │
└─────────────────────────────────────────────────────────────┘3. Framework Auto-Detection Heuristics
When build_manager.py plan executes, Vexlyx inspects the repository files and dependencies (requirements.txt, pyproject.toml, Pipfile, setup.py):
1. Django
- Detection: Presence of
manage.pyORdjangoin dependency manifests. - WSGI Resolution:
- Scans
manage.pyforDJANGO_SETTINGS_MODULE(e.g.mysite.settings→mysite.wsgi). - Scans first-level directories for
wsgi.py(e.g.config/wsgi.py→config.wsgi,mysite/wsgi.py→mysite.wsgi). - Root
wsgi.py→wsgi.
- Scans
- Suggested Build Command:
python manage.py collectstatic --noinput(ifmanage.pyexists). - Suggested Start Command:
gunicorn <module>.wsgi:application --bind 0.0.0.0:${PORT:-8000} --workers 2. - Identified Framework:
django(displayed asDjango), Project Type:PYTHON.
2. Flask
- Detection:
flaskin dependency manifests, or Python files using Flask. - Entrypoint Discovery:
app.py→app:appmain.py→main:appwsgi.py→wsgi:appapplication.py→application:appsrc/app.py→src.app:appsrc/main.py→src.main:app
- Suggested Start Command:
gunicorn -w 2 -b 0.0.0.0:${PORT:-8000} <entrypoint>. - Identified Framework:
flask(displayed asFlask), Project Type:PYTHON.
3. FastAPI
- Detection:
fastapiin dependency manifests. - Entrypoint Discovery:
main.py→main:appapp/main.py→app.main:appapp.py→app:appsrc/main.py→src.main:appsrc/app.py→src.app:app
- Suggested Start Command:
uvicorn <entrypoint> --host 0.0.0.0 --port ${PORT:-8000} --workers 2. - Identified Framework:
fastapi(displayed asFastAPI), Project Type:PYTHON.
4. Generic Python
- Detection: Repositories containing
requirements.txt,pyproject.toml, or.pyfiles without specific web frameworks. - Suggested Start Command:
python main.pyorpython app.py. - Identified Framework:
python(displayed asPython), Project Type:PYTHON.
4. Python Version Selection (3.10, 3.11, 3.12)
Vexlyx inspects the following sources (in priority order) to resolve the exact Python version:
- Environment Variables: Project setting
PYTHON_VERSIONorNIXPACKS_PYTHON_VERSION(e.g.3.11,3.12). .python-versionFile: Text containing version (e.g.3.11.8→ normalized to3.11).runtime.txtFile: Heroku-style version file (e.g.python-3.12.2→ normalized to3.12).pyproject.toml:requires-python = ">=3.10"orpython = "^3.11".
The resolved version is passed to Nixpacks via --env NIXPACKS_PYTHON_VERSION=<version> during both plan and build operations.
5. Container & Compose Template (python.yml)
The Python container runs with internal port 8000 by default:
yaml
services:
app:
image: "{{image_name}}"
restart: unless-stopped
environment:
PORT: "{{container_port}}"
HOST: "0.0.0.0"
FLASK_RUN_HOST: "0.0.0.0"
FLASK_RUN_PORT: "{{container_port}}"
UVICORN_HOST: "0.0.0.0"
UVICORN_PORT: "{{container_port}}"
GUNICORN_CMD_ARGS: "--bind=0.0.0.0:{{container_port}}"
PYTHONUNBUFFERED: "1"
{{env_block}}
ports:
- "{{host_port}}:{{container_port}}"
deploy:
resources:
limits:
memory: "{{memory_limit}}"
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:{{container_port}}/health || wget -qO- http://localhost:{{container_port}}/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
labels:
- "traefik.enable=true"
- "traefik.http.routers.{{service_name}}.rule=Host(`{{hostname}}`)"
- "traefik.http.routers.{{service_name}}.entrypoints=web"
- "traefik.http.services.{{service_name}}.loadbalancer.server.port={{container_port}}"
networks:
default:
external: true
name: traefik-net6. How to Test
Run the automated test suite:
bash
python tests/test_python_runtime.pyExpected output:
=== Running Python Runtime (F2.2) Automated Test Suite ===
Testing Django framework auto-detection & WSGI resolution...
[PASS] Django with mysite/wsgi.py detected -> collectstatic & gunicorn mysite.wsgi:application
[PASS] Django with config/wsgi.py in pyproject.toml detected -> gunicorn config.wsgi:application
Testing Flask framework auto-detection & entrypoint discovery...
[PASS] Flask auto-detected with entrypoint 'app.py' -> 'app:app'
[PASS] Flask auto-detected with entrypoint 'main.py' -> 'main:app'
[PASS] Flask auto-detected with entrypoint 'wsgi.py' -> 'wsgi:app'
[PASS] Flask auto-detected with entrypoint 'application.py' -> 'application:app'
Testing FastAPI framework auto-detection & entrypoint discovery...
[PASS] FastAPI auto-detected with entrypoint 'main.py' -> 'main:app'
[PASS] FastAPI auto-detected with entrypoint 'app.py' -> 'app:app'
[PASS] FastAPI auto-detected with entrypoint 'app/main.py' -> 'app.main:app'
Testing Python version detection (3.10, 3.11, 3.12)...
[PASS] .python-version '3.11.8' -> 3.11
[PASS] runtime.txt 'python-3.12.2' -> 3.12
[PASS] pyproject.toml 'requires-python = ">=3.10"' -> 3.10
[PASS] env_vars PYTHON_VERSION '3.12' -> 3.12
Testing python.yml template rendering & parameters...
[PASS] python.yml rendered correctly with all variables & Traefik labels
[SUCCESS] ALL PYTHON RUNTIME TESTS PASSED SUCCESSFULLY!7. How to Extend
- Adding Celery / Background Workers: Extend
python.ymlwith an optionalworkerservice sharing the application image and database/Redis connections. - ASGI Django (Daphne/Uvicorn): If
asgi.pyis present and websocket support is needed, thestart_cmdcan be configured asdaphne -b 0.0.0.0 -p 8000 <module>.asgi:application. - Custom WSGI/ASGI Servers: Users can provide manual start command overrides via the dashboard Build Panel or
startCmdproject setting.