← Blog

Desplegar Django sin escribir un Procfile a mano

Railyard

9 de octubre de 2026 · 2 min de lectura

Una app de Django ya sabe casi todo lo que un host necesita para correrla: requirements.txt dice si existe Celery, psycopg dice que necesita Postgres, manage.py dice qué migrar. La mayoría de los onboarding de PaaS piden esa misma información de todos modos, como un archivo de configuración o un formulario en el panel — un segundo lugar donde puede desincronizarse del código real.

Qué se detecta, no se configura

  • Django mismo se detecta a partir de requirements.txt, pyproject.toml, o un manage.py que lo importa — sin ningún flag de framework que definir.
  • python manage.py migrate --no-input corre como el paso de release, antes de que la versión nueva reciba tráfico.
  • python manage.py collectstatic --noinput corre en el paso de build automáticamente — la misma convención que usaba el buildpack de Python de Heroku, así que WhiteNoise o cualquier configuración de STATIC_ROOT simplemente funciona sin agregar una línea al Dockerfile. Una app que no usa django.contrib.staticfiles sencillamente no se ve afectada.
  • psycopg en las dependencias aprovisiona Postgres e inyecta DATABASE_URL; un cliente de Redis (redis, django-redis, rq) hace lo mismo para REDIS_URL.
  • Celery, Celery Beat, RQ, Huey, Dramatiq y Django-Q se ofrecen cada uno automáticamente como proceso worker en cuanto son una dependencia — no algo que conectar a un Procfile desde cero.
railyard create my-app https://github.com/me/my-app --addons postgres,redis

o la misma URL pegada en el panel una vez que GitHub está conectado.

Procesos, a la manera de los 12 factores

web, worker y un proceso beat programado son el mismo build, cada uno iniciado con un comando distinto — no tres apps separadas que mantener sincronizadas a mano:

web:    gunicorn myproject.wsgi:application --bind 0.0.0.0:$PORT
worker: celery -A myproject worker --loglevel=info
beat:   celery -A myproject beat --loglevel=info

Salta el Procfile por completo y la detección ofrece el worker solo, según la librería de jobs que ya sea una dependencia. Escala cualquiera de ellos de forma independiente:

railyard scale my-app worker=2

Lo único que vale la pena revisar antes del primer despliegue

La suposición por defecto de Gunicorn es un módulo WSGI en wsgi:application — si la estructura del proyecto lo pone en otro lado, esa es la única línea que vale la pena definir explícitamente en el comando de arranque en vez de confiar en la suposición. Todo lo demás, río abajo de eso (migraciones, archivos estáticos, workers), sigue automáticamente en cuanto el proceso web de verdad arranca.

Configuración y secretos

DJANGO_SETTINGS_MODULE, SECRET_KEY, y cualquier feature flag viven en Variables, o con railyard env:set my-app KEY=VALUE — variables de entorno simples, no horneadas en la imagen, así que el mismo build corre sin cambios desde staging hasta producción. DATABASE_URL y REDIS_URL se resuelven por entorno automáticamente según lo que esté conectado en el canvas.

Referencia completa: Documentación de Django, Workers y jobs programados.

Despliega una app de Django ahora mismo.

requirements.txt se lee automáticamente — gunicorn, migraciones y Postgres quedan conectados solos.

Plan gratis, sin tarjeta, y 14 días de Pro para cada equipo nuevo. Un precio fijo por equipo.