Python-сайт поднимается локально за пару минут — flask run, python manage.py runserver или uvicorn main:app — а публикация в интернет превращается в отдельную задачу: сервер, нужная версия Python, зависимости, production-сервер, nginx перед ним, сертификат для HTTPS и присмотр за всем этим. Шагов много, и до появления сайта по ссылке проходит не один вечер. Платформа деплоя убирает эту часть: вы загружаете код, она определяет, что перед ней Python-проект, ставит библиотеки из requirements.txt и выдаёт публичный адрес с HTTPS. На Dockbox это работает так — ниже разберём, что подготовить в проекте, чтобы сайт открылся с первого раза.
Что вообще нужно, чтобы Python-сайт оказался в интернете
Независимо от фреймворка, публикация требует одного и того же набора вещей — и именно на них спотыкаются чаще всего.
Код, который уже работает локально. Сначала сайт должен открываться на вашей машине. Если он падает в разработке, деплой ничего не исправит — только спрячет ошибку в логи сборки.
Файл зависимостей. Без requirements.txt сервер не знает, какие библиотеки ставить. Это же и признак, по которому платформа понимает: перед ней Python-проект.
Production-сервер. Встроенный сервер разработки (flask run, runserver) для интернета не годится: он однопоточный и предназначен для отладки. В бой идёт gunicorn, а для асинхронных приложений — uvicorn.
Адрес 0.0.0.0 и порт из переменной PORT. Приложение должно слушать не 127.0.0.1, иначе снаружи оно недоступно, и брать номер порта из окружения, а не из кода.
Секреты вне репозитория. Ключи API, строки подключения к базе, SECRET_KEY — всё это живёт в переменных окружения, а не в исходниках.
Flask, Django или FastAPI: что подойдёт для сайта
Все три фреймворка выкладываются одинаково — разница только в мелочах запуска.
Flask — минималистичный и самый быстрый на старте: подходит для небольших сайтов, лендингов с формами, внутренних панелей. Обратите внимание, что в продакшене Flask запускает не flask run, а gunicorn; подробнее — в разборе Flask-приложения.
Django — если нужны админка, ORM, миграции и аутентификация «из коробки». Это фреймворк для сайтов с базой и пользователями, и у него свои грабли: статику надо собирать вручную, а DEBUG — выключать. Об этом — в статье про сайт на Django.
FastAPI — для API и асинхронных сервисов, к которым потом подключается фронтенд. Он держит схему OpenAPI автоматически и запускается под uvicorn. Нюансы — в разборе FastAPI в интернете.
Общее правило для всех: у приложения должна быть внятная точка входа и оно должно читать порт из окружения.
requirements.txt: по нему платформа понимает, что это Python-проект
Файл кладётся в корень проекта, рядом с кодом. В нём — библиотеки, которые код реально импортирует. Для сайта на Flask это выглядит так:
Flask==3.0.3
gunicorn==22.0.0
python-dotenv==1.0.1
Версии фиксируйте: сборка получится воспроизводимой, и однажды новая мажорная версия библиотеки не сломает проект на ровном месте. Если сайт работает с базой или картинками, добавьте SQLAlchemy, psycopg2-binary, Pillow — по факту импортов.
Папку venv в архив не кладите. Зависимости всё равно ставятся заново из списка, а лишние мегабайты только замедлят загрузку. __pycache__ и .pytest_cache тоже не нужны.
Точка входа и порт: почему ссылка не открывается
Это причина номер один, по которой приложение собралось, но сайт не открывается. Порт задаёт платформа, он приходит в переменной окружения PORT, и читать его надо в рантайме.
Плохой вариант — номер и адрес вписаны в код:
app.run(host="127.0.0.1", port=5000)
127.0.0.1 означает «слушать только внутри контейнера»: снаружи приложение недоступно. Рабочий вариант — адрес 0.0.0.0 и порт из окружения:
import os
port = int(os.environ.get("PORT", 5000))
app.run(host="0.0.0.0", port=port)
Для production-сервера то же правило: gunicorn запускается на интерфейсе 0.0.0.0 и подставляет $PORT. Для ASGI-проекта на FastAPI вместо gunicorn указывается uvicorn с теми же параметрами.
Секреты — в переменные окружения, а не в код
По умолчанию секреты оказываются в исходниках, и это опасно: код вы будете показывать, отдавать или заливать в Git.
OPENAI_API_KEY = "sk-***"
DATABASE_URL = "postgres://app:***@db:5432/app"
Правильно — значения приходят извне, а код только читает их:
import os
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
DATABASE_URL = os.environ["DATABASE_URL"]
Секрет в коде = секрет утёк. На платформе значения задаются отдельно, в настройках проекта, и подставляются при запуске:
OPENAI_API_KEY=***
SECRET_KEY=***
DATABASE_URL=postgres://app:***@db:5432/app
В панели видны только имена переменных, значения остаются скрытыми.
Как залить проект и что происходит после загрузки
Код попадает на платформу двумя способами: ZIP-архивом или импортом репозитория — подойдёт и приватный GitHub. Никакой build-конфигурации писать не нужно: платформа сама определяет Python, ставит зависимости, собирает и запускает приложение.
Во время настройки нужно ответить на пару вопросов — в первую очередь про переменные окружения с секретами. Указать их лучше сразу, а не после первого падения с ошибкой «переменная не найдена».
Когда сборка закончится, у сайта появится публичный адрес с HTTPS. Дальше логи и статус видны в панели в реальном времени, а для новой версии достаточно обновить код и запушить изменения — платформа пересоберёт проект. Чтобы выкладывать обновления автоматически при git push, удобно держать проект в репозитории, а не в ZIP.
Сколько это стоит и как работают контейнеры
Администрировать сервер не нужно — контейнеры работают постоянно, без ограничения по часам и без «засыпания». Упавший контейнер платформа перезапускает сама.
Starter — 990 ₽/мес. 1 vCPU, 2 GB RAM, 20 GB SSD, один проект. Первый месяц бесплатный. Для одного Flask- или Django-сайта этого достаточно, и лимита по времени работы нет.
Pro — 2 490 ₽/мес. 2 vCPU, 4 GB RAM, до пяти проектов — если рядом живут база, фоновая очередь и воркер.
Team — 4 990 ₽/мес — для команд, которым нужен запас ресурсов и SLA.
Тарифы и подробности — на dockbox.host.
Частые вопросы
Приложение собралось, а ссылка не открывается — почему?
Почти всегда виноват порт и адрес: приложение слушает 127.0.0.1:5000 вместо порта из PORT и интерфейса 0.0.0.0. Платформа направляет трафик только на выданный ею порт, поэтому жёстко прописанный номер — причина номер один. Вторая — встроенный сервер разработки вместо gunicorn или uvicorn.
Какой фреймворк выбрать для несложного сайта?
Если нужно быстро и без лишних сущностей — Flask. Если сайту нужны база, админка и пользователи — Django. Если вы делаете API для отдельного фронтенда — FastAPI. Все три загружаются и запускаются на платформе одинаково, так что выбор можно спокойно сделать по задаче, а не по сложности деплоя.
Нужно ли класть venv в архив?
Нет. Виртуальное окружение содержит файлы вашей машины и не переносимо; зависимости всё равно устанавливаются заново по requirements.txt. Папка venv (или .venv) в архиве только увеличит время загрузки и сборки.
Что делать, если в коде остались ключи и пароли?
Перенесите их в переменные окружения проекта и задайте значения в настройках, а из исходников удалите. Если секрет уже попадал в Git-репозиторий, считайте его утёкшим и сгенерируйте новый — история коммитов сохранит его навсегда.
Сайт работает локально, но падает после деплоя — с чего начать?
С логов сборки и запуска: настоящая ошибка почти всегда написана в них прямым текстом. Три типичные причины — не заданы переменные окружения, не хватает зависимости из requirements.txt или приложение использует локальные пути и файлы, которых на сервере нет.