Развертывание Django на Lizard
Запустите Django на Lizard с Gunicorn и WSGI-модулем вашего проекта на порту 8000. Подготовьте продакшен-настройки, доступ к базе данных и раздачу статических файлов перед тем, как полагаться на развернутое приложение. manage.py runserver — это сервер разработки.
Задайте команду запуска
В этом руководстве предполагается manage.py, requirements.txt и пакет проекта с именем config, содержащий wsgi.py. Замените config на фактическое имя вашего пакета.
Включите Django, Gunicorn и драйвер базы данных, который использует ваше приложение, в проверенные зависимости. Добавьте Procfile:
web: gunicorn config.wsgi:application --bind 0.0.0.0:8000Явный модуль устраняет неоднозначность, когда настройки находятся во вложенных пакетах. ASGI-приложение с WebSockets требует ASGI-сервер и другую команду запуска; это руководство охватывает WSGI.
| Настройка | Значение |
|---|---|
| Установка | pip install -r requirements.txt |
| Среда выполнения | Gunicorn с вашим WSGI-модулем |
| Порт сервиса | 8000 |
| Рабочая директория | Директория, содержащая manage.py |
Подготовьте продакшен-настройки
Django ожидает словарь DATABASES в settings.py. Установка только DATABASE_URL на сервисе не подключает Django к PostgreSQL. Шаги ниже создают Managed Postgres, передают его URL приложению и преобразуют этот URL в настройки подключения Django.
Добавьте эти пакеты в requirements.txt, сохраняя любые другие зависимости, которые нужны вашему приложению. Это версии, используемые в полном примере:
Django==6.1.1
gunicorn==26.2.0
whitenoise==6.12.0
psycopg[binary]==3.3.5
dj-database-url==3.1.2psycopg — драйвер PostgreSQL. dj-database-url считывает имя базы данных, пользователя, пароль, хост и порт из URL подключения. Замените соответствующие настройки в settings.py вашего проекта на этот блок; сохраните ваши существующие apps, middleware, шаблоны и другие настройки:
import os
from pathlib import Path
import dj_database_url
from django.core.exceptions import ImproperlyConfigured
BASE_DIR = Path(__file__).resolve().parent.parent
def required_env(name):
value = os.environ.get(name, "").strip()
if not value:
raise ImproperlyConfigured(f"Set the {name} environment variable.")
return value
def env_list(name):
values = [item.strip() for item in required_env(name).split(",") if item.strip()]
if not values:
raise ImproperlyConfigured(f"Set at least one value in {name}.")
return values
SECRET_KEY = required_env("SECRET_KEY")
debug_value = os.environ.get("DEBUG", "false").strip().lower()
if debug_value not in {"true", "false"}:
raise ImproperlyConfigured("DEBUG must be true or false.")
DEBUG = debug_value == "true"
ALLOWED_HOSTS = env_list("ALLOWED_HOSTS")
CSRF_TRUSTED_ORIGINS = env_list("CSRF_TRUSTED_ORIGINS")
DATABASES = {
"default": dj_database_url.parse(
required_env("DATABASE_URL"),
conn_max_age=60,
conn_health_checks=True,
)
}Не оставляйте более старые назначения DATABASES, SECRET_KEY или DEBUG ниже в файле: они заменят эти значения. Этот пример требует непустые значения SECRET_KEY, DATABASE_URL, ALLOWED_HOSTS и CSRF_TRUSTED_ORIGINS. Отсутствующие или пустые значения останавливают запуск с именем переменной. DEBUG по умолчанию false; установите его в false на развернутом сервисе.
ALLOWED_HOSTS принимает хостнеймы через запятую без схемы и пути, например app.example.com,www.example.com. CSRF_TRUSTED_ORIGINS принимает origins через запятую со схемой, например https://app.example.com. Укажите порт для локальных origins, которые его используют. Пример требует явный список origins; сам Django допускает пустой список для приложений, не требующих дополнительных доверенных origins. Доверяйте только тем origins, которые должны отправлять формы в это приложение. Эти настройки не заменяют CSRF-токены.
URL берутся из секрета или ссылки сервиса, а не из значения, закоммиченного в исходники. Не используйте локальный SQLite в контейнере как долговечную базу данных для развернутого приложения. См. использование dj-database-url для разбора URL и параметров подключения.
С вашими локальными переменными окружения и доступным PostgreSQL выполните:
python -m pip install -r requirements.txt
python manage.py check --deploy
gunicorn config.wsgi:application --bind 0.0.0.0:8000Просмотрите чек-лист развертывания Django для настроек, актуальных для вашего приложения. Небольшой пример не настраивает каждую продакшен-настройку безопасности. Проверьте обработку прокси и HTTPS с реальным публичным URL перед включением защищённых cookie, HSTS или редиректов. Доверяйте переадресованным HTTPS-заголовкам только тогда, когда прокси ими управляет.
Спланируйте статические файлы и миграции
Gunicorn один не раздаёт статические файлы Django. Выберите middleware для статических файлов, настроенный в приложении, или отдельный статический хост. Соберите ассеты в путь, который обслуживает эта настройка. Python-путь lizardpack на основе requirements не запускает автоматически collectstatic; добавьте его в полную сборку Dockerfile, когда приложению нужен этот шаг.
Для WhiteNoise сохраняйте django.contrib.staticfiles в INSTALLED_APPS и вставьте whitenoise.middleware.WhiteNoiseMiddleware сразу после SecurityMiddleware Django. Добавьте или обновите эти настройки:
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STORAGES = {
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
},
}Сохраняйте ваш существующий бэкенд STORAGES["default"], если приложение уже хранит загрузки в другом месте. WhiteNoise раздаёт собранные статические ассеты, не загрузки пользователей.
Используйте этот Dockerfile в корне проекта:
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN SECRET_KEY=build-only-placeholder \
DATABASE_URL=postgresql://build:build@127.0.0.1:1/build \
ALLOWED_HOSTS=localhost CSRF_TRUSTED_ORIGINS=http://localhost \
python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]Значения в строке RUN существуют только для collectstatic. URL базы данных — это заполнитель, указывающий на неиспользуемый локальный порт; базы данных там не запускается. Загрузка настроек разбирает URL, но сбор ассетов не требует подключения к базе. Не запрашивайте базу данных из импортов модулей или AppConfig.ready(). Пример также передаёт collectstatic с отключённой сетью контейнера.
Эти назначения не становятся переменными окружения runtime. Установите свежий SECRET_KEY и реальную ссылку на базу данных на сервисе перед запуском. Не передавайте продакшен-секреты в Docker-сборку.
Создайте .dockerignore и исключите те же пути из загрузки исходников:
.env*
.venv/
venv/
.git/
__pycache__/
*.pyc
*.sqlite3
staticfiles/Храните загрузки пользователей в долговечном хранилище, таком как Managed Object Storage, а не в статической директории контейнера. Ознакомьтесь с хранилищем и восстановлением.
Относитесь к миграциям базы данных как к отдельному шагу релиза. Сделайте бэкап данных при необходимости, обеспечьте безопасность повторного запуска миграций и примените их до того, как запросы потребуют новую схему. Pre-deploy-команда не заменяет проверку поведения при конкуренции и сбоях.
Разверните и проверьте
После настройки CLI подключите GitHub-сервис, настройте его секреты и продакшен-настройки, и разверните с контейнерным портом 8000. Для нового проекта на основе загрузки:
lizard init --name django-app
lizard add --service webСоздайте Managed Postgres в этом проекте. Если у вас уже есть экземпляр, пропустите add postgres и используйте его имя в ссылке:
lizard add postgres --name postgresЗадайте секреты сервиса приложения. postgres в ${{postgres.DATABASE_URL}} именует сервис базы данных, не псевдоним базы Django. Lizard разрешает ссылку во время деплоя и внедряет получившийся URL в процесс web. Одинарные кавычки не дают оболочке раскрыть ссылку. Блок settings.py выше затем превращает URL в DATABASES["default"].
DJANGO_SECRET_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(48))')"
lizard secrets set SECRET_KEY="$DJANGO_SECRET_KEY" \
DATABASE_URL='${{postgres.DATABASE_URL}}' DEBUG=false \
ALLOWED_HOSTS=localhost CSRF_TRUSTED_ORIGINS=http://localhost \
--service web
lizard up --service web --port 8000
lizard ps --jsonlocalhost — временная настройка хоста, позволяющая процессу запуститься, пока вы получаете его публичный хостнейм; публичные запросы вернут 400. Если вы уже знаете хостнейм, задайте его перед первой загрузкой. Иначе замените эти плейсхолдеры на хостнейм и HTTPS-origin, возвращённые для вашего сервиса:
lizard secrets set ALLOWED_HOSTS=YOUR_PUBLIC_HOST \
CSRF_TRUSTED_ORIGINS=https://YOUR_PUBLIC_HOST --service webОтсутствующая цель ссылки или ключ могут разрешиться в пустую строку. Проверка обязательного значения тогда остановит Django с Set the DATABASE_URL environment variable. Проверьте имя сервиса базы данных и его ключ DATABASE_URL; не выводите URL подключения в логи.
Изменение переменной перезапускает процесс. Исключите локальные виртуальные окружения, секреты и локальные базы данных из загрузок. После запуска процесса примените миграции:
lizard ssh --service web -- python manage.py migrate --noinputЗапустите команду снова, чтобы убедиться, что миграций не осталось. Не считайте успешную проверку порта доказательством существования таблиц.
Проверьте URL приложения, страницу с базой данных, отправку формы и статический ассет. Если приложение использует Django admin, также проверьте его CSS. Читайте lizard logs --service web --json для ошибок импорта или настроек. Ответ 400 часто означает, что ALLOWED_HOSTS неверен; отсутствующий CSS обычно означает, что статические ассеты не были собраны или не раздаются. Проверьте фактическую ошибку перед изменением настроек.
См. проверенные версии и облачные результаты для проверок деплоя 9 сентября 2026 года и их ограничений.
Воспроизведите этот пример
Пример Django включает настройки, Dockerfile, requirements, форму с базой данных и тест-раннер. Скопируйте его в отдельную директорию и запустите python3 tests/verify.py с работающим Docker. Он соберёт образ, запустит локальный PostgreSQL, проверит миграции и HTTP-поведение, и остановит свои тестовые контейнеры. Он не создаёт сервисы Lizard. См. его README для проверок и сохраняемых Docker-ресурсов.
Проверка 14 сентября 2026 года охватывает этот обновлённый пример в локальных Linux-контейнерах. Ранние облачные результаты, на которые ссылаются выше, касаются руководства от 9 сентября; обновлённые настройки ещё не проходили новый облачный деплой.