← Blog

Fazendo deploy de Django sem escrever um Procfile à mão

Railyard

9 de outubro de 2026 · 2 min de leitura

Uma aplicação Django já sabe quase tudo que um host precisa pra rodá-la: o requirements.txt diz se o Celery existe, o psycopg diz que ela precisa de Postgres, o manage.py diz o que migrar. A maioria dos onboardings de PaaS pede essa informação de novo mesmo assim, como um arquivo de configuração ou um formulário no dashboard — um segundo lugar pra ela ficar fora de sincronia com o código real.

O que é detectado, não configurado

  • O próprio Django é detectado a partir do requirements.txt, do pyproject.toml, ou de um manage.py que o importa — nenhuma flag de framework pra definir.
  • python manage.py migrate --no-input roda como etapa de release, antes da nova versão receber tráfego.
  • python manage.py collectstatic --noinput roda na etapa de build automaticamente — a mesma convenção que o buildpack Python do Heroku usava, então o WhiteNoise ou qualquer configuração de STATIC_ROOT simplesmente funciona, sem linha de Dockerfile pra adicionar. Uma aplicação que não usa django.contrib.staticfiles simplesmente não é afetada.
  • psycopg nas dependências provisiona Postgres e injeta DATABASE_URL; um cliente Redis (redis, django-redis, rq) faz o mesmo pro REDIS_URL.
  • Celery, Celery Beat, RQ, Huey, Dramatiq e Django-Q são cada um oferecidos como processo worker automaticamente quando são uma dependência — não algo pra conectar num Procfile do zero.
railyard create my-app https://github.com/me/my-app --addons postgres,redis

ou a mesma URL colada no dashboard depois que o GitHub estiver conectado.

Processos, do jeito 12-factor

web, worker e um processo beat agendado são o mesmo build, cada um iniciado com um comando diferente — não três aplicações separadas pra manter sincronizadas à mão:

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

Pule o Procfile por completo e a detecção oferece o worker por conta própria, baseada em qual biblioteca de job já é uma dependência. Escale qualquer um deles independentemente:

railyard scale my-app worker=2

A única coisa que vale a pena checar antes do primeiro deploy

A suposição padrão do Gunicorn é um módulo WSGI em wsgi:application — se o layout do projeto colocar isso em outro lugar, essa é a única linha que vale a pena definir explicitamente no comando de start em vez de confiar no chute. Tudo o que vem depois disso (migrations, arquivos estáticos, workers) segue automaticamente uma vez que o processo web de fato inicializa.

Configuração e secrets

DJANGO_SETTINGS_MODULE, SECRET_KEY, e qualquer feature flag vivem em Variables, ou em railyard env:set my-app KEY=VALUE — variáveis de ambiente simples, não embutidas na imagem, então o mesmo build roda sem mudanças do staging até a produção. DATABASE_URL e REDIS_URL se resolvem por ambiente automaticamente a partir do que estiver conectado no canvas.

Referência completa: Django docs, Workers and scheduled jobs.

Suba uma aplicação Django agora mesmo.

O requirements.txt é lido automaticamente — gunicorn, migrations e Postgres já ficam todos conectados.

Plano grátis, sem cartão, e 14 dias de Pro para cada equipe nova. Um preço fixo por equipe.