Деплой Python-приложения
Эта статья дополняет общие правила из «Что нужно, чтобы деплой прошёл» конкретикой для Python. Если вкратце: нужны два файла в корне репозитория — список зависимостей и команда запуска.
Шаг 1. Зависимости — requirements.txt
Все пакеты, которые использует приложение, должны быть перечислены в requirements.txt (или в pyproject.toml / Pipfile) в корне репозитория. Nixpacks определит Python по этому файлу и установит указанное.
Частая причина провала: пакет установлен локально через pip install, но не записан в файл. Зафиксируйте зависимости командой:
pip freeze > requirements.txt
Отдельно проследите, чтобы в списке был сервер запуска, если это Web-сервис: gunicorn или uvicorn. Локально вы могли запускать приложение встроенным сервером, а на платформе его нужно объявить явно.
Шаг 2. Команда запуска — Procfile
Nixpacks не угадывает, чем запускать Python-приложение. Укажите это в файле Procfile (без расширения) в корне репозитория — одна строка вида <имя>: <команда>. Переменная $PORT в команде подставляется автоматически.
Дальше — готовые примеры под два типа сервисов.
Пример: Web-сервис
Web-сервис принимает HTTP-запросы и получает домен. Приложение обязано слушать порт из переменной PORT на адресе 0.0.0.0 (иначе домен вернёт 502 — см. общую статью). Продакшн-серверы gunicorn и uvicorn делают это через параметры запуска, приведённые ниже.
FastAPI
requirements.txt:
fastapi
uvicorn
main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"status": "ok"}
Procfile:
web: uvicorn main:app --host 0.0.0.0 --port $PORT
Flask
requirements.txt:
flask
gunicorn
app.py:
from flask import Flask
app = Flask(__name__)
@app.get("/")
def root():
return {"status": "ok"}
Procfile:
web: gunicorn app:app --bind 0.0.0.0:$PORT
Запись
app:appозначает «файлapp.py, объектapp». Дляgunicornвmain.pyэто было быmain:app.Встроенный сервер Flask (
app.run()) для продакшена не предназначен, но если вы его используете — привязка к порту обязательна:app.run(host="0.0.0.0", port=int(os.environ["PORT"])).
Пример: Worker-сервис (Telegram-бот)
Worker работает в фоне, не принимает HTTP и не имеет домена. Порт слушать не нужно, а токены и ключи читаются из переменных окружения сервиса.
requirements.txt:
python-telegram-bot
bot.py:
import os
from telegram.ext import Application, CommandHandler
async def start(update, context):
await update.message.reply_text("Привет")
app = Application.builder().token(os.environ["BOT_TOKEN"]).build()
app.add_handler(CommandHandler("start", start))
app.run_polling()
Procfile:
worker: python bot.py
Значение BOT_TOKEN задаётся в переменных окружения сервиса — см. «Переменные окружения и секреты».
Версия Python
По умолчанию берётся актуальная стабильная версия. Если нужна конкретная, задайте переменную окружения сервиса NIXPACKS_PYTHON_VERSION (например, 3.12).
Частые ошибки
| Симптом | Причина | Решение |
|---|---|---|
ModuleNotFoundError при запуске | Пакет не указан в requirements.txt | Добавьте его и пересоберите |
| Сборка прошла, но контейнер сразу останавливается | Нет Procfile или неверная команда | Проверьте имя объекта приложения (app:app) и путь к файлу |
| Домен отдаёт 502 | Приложение слушает 127.0.0.1 или фиксированный порт | Слушайте $PORT на 0.0.0.0 |
| Бот не отвечает, в логах ошибка про токен | Токен захардкожен или не задан | Задайте BOT_TOKEN в переменных окружения |