FastAPI-приложение выкладывается в интернет без аренды сервера: загружаете папку с кодом, платформа распознаёт Python по requirements.txt, ставит зависимости и отдаёт публичную HTTPS-ссылку. Решающих деталей три: приложение должно читать порт из переменной PORT, слушать 0.0.0.0 и запускаться через uvicorn, а не через python main.py. Зато FastAPI сам отдаёт интерактивную документацию на /docs — по ней проще всего убедиться, что API действительно живой. Ниже — путь от папки с кодом до рабочей ссылки на Dockbox.
Почему FastAPI-проект по умолчанию тащат на VPS
Привычный сценарий начинается с аренды сервера: поставить Python, собрать виртуальное окружение с зависимостями, придумать, как поднимать uvicorn после падения и перезагрузки, поставить перед ним nginx и выпустить сертификат. Сам FastAPI пишется за вечер — сложно всё, что вокруг него.
Обратный прокси и сертификат. Uvicorn отдаёт обычный HTTP, а наружу нужен HTTPS. Значит, nginx, конфиг с proxy_pass и сертификат, который надо продлевать каждые три месяца.
Автозапуск и перезапуск. Чтобы процесс вернулся в строй после сбоя и перезагрузки, нужен systemd-юнит, а его отладка — отдельный навык, не связанный с вашим кодом.
Оплата независимо от нагрузки. Сервер стоит денег все 30 дней, даже если эндпоинты дёргают раз в сутки.
Платформа деплоя снимает эту часть: вы загружаете код, она находит requirements.txt, ставит пакеты и отдаёт публичную HTTPS-ссылку. Ни сервера, ни nginx, ни ручного сертификата.
Шаг 1. Положите requirements.txt в корень проекта
Файл зависимостей в корне — это и есть признак Python-проекта. Перечислите в нём то, что реально импортирует код, фиксируя версии: минимально это fastapi и uvicorn — сервер, который принимает запросы и передаёт их вашему приложению.
fastapi==0.115.6
uvicorn[standard]==0.34.0
Если приложение ходит в базу или во внешние API, добавьте httpx, sqlalchemy, pydantic-settings — по факту импортов. Папку venv с библиотеками в архив класть не нужно: пакеты ставятся во время сборки. Если рядом лежит ещё и pyproject.toml, оставьте один манифест — с двумя платформа может определить окружение неверно.
Шаг 2. Читайте порт из переменной PORT и слушайте 0.0.0.0
Порт задаёт платформа, а не вы. Значение приходит в переменных окружения, поэтому берите его оттуда, а не пишите число руками. Слушать нужно 0.0.0.0: адрес localhost виден только самому приложению изнутри, и публичная ссылка останется пустой. Жёстко зашитый порт — причина номер один, по которой сборка проходит, а страница потом не открывается.
Так делать не стоит:
uvicorn main:app --host 0.0.0.0 --port 8000
Так — правильно, порт подставляется из окружения:
import os
import uvicorn
if __name__ == "__main__":
port = int(os.environ["PORT"])
uvicorn.run("main:app", host="0.0.0.0", port=port)
main:app здесь означает «файл main.py, объект приложения app». Если у вас app/main.py с app = FastAPI(), импорт-строка будет app.main:app.
Шаг 3. Решите, сколько нужно воркеров uvicorn
FastAPI асинхронный, и один воркер обычно держит сотни одновременных запросов — этого хватает большинству API. Флаг --workers поднимает несколько процессов, и каждый из них импортирует приложение целиком, то есть умножает потребление памяти. На тарифе с 2 ГБ RAM четыре воркера с тяжёлыми зависимостями легко упираются в лимит, и контейнер перезапускается по памяти, а не по нагрузке.
uvicorn main:app --host 0.0.0.0 --port $PORT --workers 1
Практическое правило: начинайте с одного воркера и добавляйте следующий только под реальную нагрузку. И не оставляйте в продакшене --reload — он следит за файлами и лишний раз перезапускает процесс.
Шаг 4. Вынесите секреты в переменные окружения
Ключи сторонних сервисов, токены и строку подключения к базе читайте из окружения, а не держите константами в коде:
import os
DATABASE_URL = os.environ["DATABASE_URL"]
API_TOKEN = os.environ["API_TOKEN"]
Код вы почти наверняка зальёте в Git или кому-то покажете, а вместе с ним уедут и секреты. В настройках проекта Dockbox запрашивает такие значения и передаёт их в контейнер, поэтому в архиве и в репозитории они не появляются.
Шаг 5. Загрузите код и получите ссылку
Проект попадает на платформу двумя способами: архивом с исходниками или импортом репозитория GitHub, в том числе приватного. Указывать язык, писать Dockerfile и готовить сборку заранее не нужно — платформа сама видит requirements.txt, ставит Python и пакеты. Статус сборки и логи видны в панели в реальном времени. Когда сборка закончится, вы получите публичную HTTPS-ссылку — она остаётся той же при обновлении кода.
Шаг 6. Проверьте API и автодокументацию
FastAPI генерирует документацию по вашему коду сам, без единой строчки настроек. Откройте <ваша-ссылка>/docs — это Swagger UI со списком всех эндпоинтов, схемами запросов и кнопкой Try it out, которой можно отправить тестовый запрос прямо из браузера. Рядом — /redoc и /openapi.json с машинной схемой для фронтенда и клиентов.
Если /docs открылся и эндпоинты отвечают — API работает в интернете. Полезно добавить лёгкий эндпоинт /health с ответом {"status": "ok"}: по нему видно, что живо всё приложение, а не один эндпоинт.
Сколько это стоит и как работают контейнеры
Ни администрировать сервер, ни следить за процессом не нужно: контейнеры работают постоянно, без ограничения по часам и без «засыпания». Упавший контейнер платформа перезапускает сама, и API возвращается в строй без вашего участия.
Starter — 990 ₽/мес. 1 vCPU, 2 ГБ RAM, один проект. Первый месяц бесплатный. Для одного FastAPI-сервиса этого достаточно, и лимита по времени работы у тарифа нет.
Pro — 2 490 ₽/мес. Больше ресурсов и до пяти проектов — вариант, если у вас несколько API или бэкенд плюс фронтенд.
Team — 4 990 ₽/мес — для команд, которым нужен запас ресурсов и SLA.
Свой Dockerfile поддерживается, но не обязателен. Если он нужен, берите официальный образ Python и не забывайте про порт из окружения:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["sh", "-c", "uvicorn main:app --host 0.0.0.0 --port $PORT"]
Файлы, которые пишет приложение, сохраняются между деплоями только в постоянной папке /data — туда же стоит положить SQLite-базу, если она у вас есть. Всё, что создано рядом с кодом, пересоздаётся при следующей публикации.
Частые вопросы
Приложение собралось, а ссылка возвращает 502 — почему?
Три причины покрывают почти все случаи: приложение слушает localhost вместо 0.0.0.0, порт вписан числом вместо значения из переменной PORT, либо uvicorn запущен не на том объекте приложения (неверная строка вида main:app). Откройте логи запуска в панели — там будет либо строка о старте сервера с портом, либо traceback с причиной.
Сколько воркеров uvicorn ставить для FastAPI?
Для большинства API достаточно одного: FastAPI асинхронный, и один процесс держит сотни одновременных запросов. Каждый дополнительный воркер — отдельный процесс со своей копией приложения и зависимостей, то есть рост потребления RAM. Ориентируйтесь на доступную память.
Обязателен ли Dockerfile для FastAPI-проекта?
Нет. Достаточно requirements.txt в корне — платформа определит Python и соберёт окружение сама. Dockerfile нужен, если вы хотите зафиксировать системные пакеты, нестандартную версию Python или шаги сборки. Если Dockerfile есть, он главнее автоопределения.
Ошибка «KeyError: 'PORT'» при старте — что делать?
Приложение читает переменную PORT, которой нет в окружении. На платформе она подставляется автоматически, поэтому чаще всего проблема в коде, который выполняется до инициализации сервера. Используйте os.environ.get("PORT", 8000) для локальной отладки, но в продакшене полагайтесь на значение платформы.
Сохранится ли SQLite-база между деплоями?
Только если файл лежит в постоянной папке /data. Файл, созданный рядом с кодом, исчезнет при следующей публикации, потому что образ контейнера собирается заново. Для серьёзных данных лучше внешняя база, а /data подойдёт для небольших проектов и загруженных пользователями файлов.