Python
zbpack compila aplicaciones Python que tengan requirements.txt, pyproject.toml (Poetry, uv, PDM) o Pipfile. Detecta FastAPI, Django y Flask, y elige un servidor de producción para cada uno.
| Framework | Comando de arranque que usa zbpack |
|---|---|
| FastAPI | uvicorn main:app --host 0.0.0.0 --port 8080 |
| Django | gunicorn --bind :8080 <project>.wsgi |
| Flask | gunicorn --bind :8080 main:app |
La versión de Python por defecto es la 3.13; indica otra en .python-version, en pyproject.toml o con ZBPACK_PYTHON_VERSION. Para arrancar la aplicación de otra forma, define ZBPACK_START_COMMAND en Settings → Build → zbpack options.
FastAPI
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "Hello from FastAPI"}# requirements.txt
fastapi
uvicorn[standard]zbpack toma el primero que exista de main.py, app.py, server.py y app/__init__.py, y la variable a la que se asigna FastAPI(...) en él (app arriba). Con otra estructura, como app/main.py, define el comando de arranque:
ZBPACK_START_COMMAND=uvicorn app.main:app --host 0.0.0.0 --port 8080Django
El proyecto necesita manage.py y gunicorn en requirements.txt:
django
gunicornLee los ajustes de producción de las variables en settings.py:
import os
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "")
DEBUG = os.environ.get("DJANGO_DEBUG") == "1"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")
CSRF_TRUSTED_ORIGINS = os.environ.get("DJANGO_CSRF_TRUSTED_ORIGINS", "").split(",")y defínelas en la pestaña Variable:
DJANGO_SECRET_KEY=${PASSWORD}
DJANGO_ALLOWED_HOSTS=${ZENAVO_WEB_DOMAIN}
DJANGO_CSRF_TRUSTED_ORIGINS=${ZENAVO_WEB_URL}(WEB es el nombre del puerto del servicio; usa el nombre que aparece en su pestaña Networking.)
Archivos estáticos
Cuando settings.py define tanto STATIC_URL como STATIC_ROOT, zbpack ejecuta python manage.py collectstatic --noinput durante la compilación y sirve los archivos con nginx delante de gunicorn, o se los deja a WhiteNoise cuando su middleware está en settings.py:
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"La compilación no tiene ninguna de las variables del servicio, así que settings.py debe cargar sin ellas: lee DJANGO_SECRET_KEY con os.environ.get(...) como arriba, no con os.environ[...].
Migraciones
Las migraciones necesitan la base de datos, a la que la compilación no llega, así que ejecútalas al arrancar:
ZBPACK_START_COMMAND=python manage.py migrate --noinput && gunicorn --bind :8080 mysite.wsgiConecta una base de datos
Añade PostgreSQL al proyecto y usa su cadena de conexión, por ejemplo con dj-database-url o SQLAlchemy:
DATABASE_URL=${POSTGRESQL_CONNECTION_STRING}import dj_database_url
DATABASES = {"default": dj_database_url.config(conn_max_age=600)}Instala también un driver: psycopg[binary] para PostgreSQL, mysqlclient o PyMySQL para MySQL y MariaDB.
Problemas habituales
| Síntoma | Causa |
|---|---|
ModuleNotFoundError al arrancar | Falta el paquete en requirements.txt (o en pyproject.toml). |
Django responde 400 Bad Request | El dominio no está en ALLOWED_HOSTS. |
Los formularios de Django fallan con CSRF verification failed | La dirección https:// no está en CSRF_TRUSTED_ORIGINS. |
| El despliegue de FastAPI nunca está sano | El objeto de la aplicación no está en main:app. Define ZBPACK_START_COMMAND. |
| Los workers mueren con carga | La memoria del servicio es poca para el número de workers de gunicorn. Baja --workers o dale más memoria al servicio. |