Learn web development

Django Руководство часть 11: Разворачивание сайта на сервере

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Теперь, когда вы создали (и протестировали) свой шикарный сайт LocalLibrary, то у вас, скорее всего, есть желание разместить его на публичном веб-сервере, таким образом, чтобы он стал доступен через интернет персоналу  и посетителям библотеки. Данная статья предоставляет обзор возможных хостингов для развертывания сайта, а также рассматривает воспросы о том, что нужно сделать с сайтом, чтобы он был готов к публикации.

Требования: Завершить изучение всех предыдущих частей руководства, включая Django Руководство часть 10:  Тестирование веб-приложений в Django.
Цель: Изучить вопросы, где и как вы можете развернуть приложение Django для публичного доступа.

Обзор

Даже когда разработка вашего сайта завершена (или "достаточно" завершена для начала публичного тестирования), то для публичного доступа вам надо его где-то разместить.

До сего момента вы работали в каком-то рабочем окружении - чтобы получать отладочную и другую частную информацию, вы использовали веб-сервер Django в локальной сети при этом запускали сайт с (небезопасными) настройками разработки. Перед тем как разместить сайт публично, вы должны сделать следующее:

  • Сделать несколько изменений в настройках проекта.
  • Выбрать/Настроить окружение для хостинга приложения Django.
  • Выбрать/Настроить окружение для размещения статических файлов.
  • В целях обслуживания сайта настроить инфраструктуру для его развертывания.

Данное руководство предоставляет небольшой обзор выбора хостинга, приготовления сайта к публичному размещению, а также практический пример установки сайта LocalLibrary на облачный сервис Heroku.

Что такое окружение развертывания?

Окружение развертывания - это среда, которое предоставляет сервер, на котором вы будете размещать свой веб-сайт для публичного запуска и доступа. Данное окружение включает в себя:

  • Железо на котором будет запускаться сайт.
  • Операционную систему (Linux, Windows).
  • Языки программирования времени выполнения (скриптовые) и библотеки, которые использует ваш сайт.
  • Веб-сервер, используемый для обслуживания страниц и другого контента (Nginx, Apache).
  • Сервер приложений, который передает "динамические" запросы между сайтом Django и веб-сервером.
  • Базу данных, от которой зависит ваш сайт.

Примечание: У вас может быть потребность в обратном прокси, балансировщике загрузки и так далее.

Сервер может быть вашим собственным с подключением к интернету по скоростному каналу, но более общим подходом является применение "облачных решений". Что действительно имеет значение, так это то, что ваш код запускается на некотором удаленном компьютере (возможно и "виртуальном"), в хостинговом дата-центре. Удаленный сервер обычно предоставляет определенный доступ к компьютерным ресурсам (процессору, оперативной памяти, памяти на жестких носителях и так далее) и соединение с интернетом за некоторую цену.

Такой тип удаленного доступа к вычислительному/сетевому железу называется Инфраструктура как Сервис (Infrastructure as a Service - IaaS). Множество IaaS поставщиков предлагают услуги по предустановке какой-либо операционной системы, на которую вы можете установить необходимые для вашего рабочего окружения компоненты. Другие поставщики предлагают вам выбрать уже готовые полноценные рабочие окружения, возможно, включающие в себя Django и настроенный веб-сервер.

Примечание: Готовые окружения могут сделать настройку вашего веб-сайта очень простой задачей, поскольку они имеют минимальную конфигурацию, однако, либо количество доступных опций может быть недостаточным, или они будут соответствовать устаревшей операционной системе. Часто, более предпочтительно установить необходимые компоненты самостоятельно, таким образом вы получите то, что вам необходимо, а в последующем, при обновлении системы, уже будете знать что нужно делать!

Некоторые провайдеры поддерживают Django как часть своего предложения Платформа как Сервис (Platform as a Service - PaaS). При данном виде хостинга вам не нужно беспокоиться о большей части окружения (веб-сервере, сервере приложений, балансировщике загрузки), так как сама платформа берет это на себя (включая все моменты, касающиеся роста и развития вашего приложения). В данном случае развертывание приложения является достаточно простой задачей, - вам нужно сконцентрироваться только на вашем приложении, а не на инфраструктуре.

Некоторые разработчики выбирают более гибкое решение, предоставляемое IaaS, в то время как другие предпочитают иметь наименьшие накладные расходы и простое масштабирование, предоставляемое PaaS. Когда вы только начинаете, то система типа PaaS является предпочтительной и это именно то, что мы будем использовать в данном руководстве.

Примечание: Если вы выбираете хостинг с поддержкой Python/Django, то он должен иметь инструкцию по установке веб-сайта Django, учитывающую различные конфигурации веб-сервера, сервера приложений, обратного прокси и так далее (это не имеет значение, если вы выбрали PaaS). Например, существует множество инструкций "шаг-за-шагом" для различный конфигураций в Документации Цифрового Сообщества Океана Django.

Выбор хостинг провайдера

Существует более 100 хорошо известных хостинг провайдеров, которые либо активно поддерживают, или работают с Django (их список можно увидеть в Django-дружественные хостинги). Данные поставщики предоставляют различные типы окружений (IaaS, PaaS), и различные уровни доступа к вычислительным и сетевым ресурсам, за разную цену.

Некоторые вещи на которые надо обратить внимение при выборе хостинга:

  • Насколько требовательным к вычислительным ресурсам является ваш сайт.
  • Уровень поддержки горизовантального (добавление большего количества машин) и вертикального масштабирования (переход на более мощное железо), а также стоимость всего этого.
  • Где расположены дата-центры и, следовательно, откуда будет более быстрый доступ.
  • Время непрерывной работы хостинга, а также время и количество простоя.
  • Инструменты, которые предоставляются для управления сайтом — простота и безопастность их использвания (SFTP и FTP).
  • Встроенные фреймворки для мониторинга вашего сервера.
  • Ограничения. Некоторые хостинги могут блокировать некоторые сервисы (например, электронную почту) . Другие предлагают только определенное количество часов "живого времени" за определенную цену, или небольшое количество места для данных.
  • Преимущества. Некоторые провайдеры могут предложить бесплатные доменные имена и поддержку сертификатов SSL, которые, в других случаях, должны были бы купить.
  • Что будет при истечении времени использования "бесплатного" хостинга, какова "стоимость" миграции на более "дорогие" тарифы и так далее?

Хорошей новостью является то, что для того, чтобы начать существует достаточное количество компаний, которые предоставляют пробные "бесплатные" тарифы типа "evaluation" (для пробы), "developer" (разработка), или "hobbyist" (хобби). Всегда существуют ресурсы с ограниченым окружением, при использовании которых вам надо беспокоиться лишь о том, что они могут быть доступны лишь в течении определенного периода времени. Тем не менее, они являются отличным решением для тестирования сайтов с небольшим трафиком в реальном окружении, а также могут предоставлять простой доступ к платным ресурсам, в случае необходимости. Наиболее популярными провайдерами являются Heroku, Python Anywhere, Amazon Web Services, Microsoft Azure и так далее.

Многие провайдеры имеют "basic" (базовый) тариф, предоставляющий достаточный уровень вычислительной мощности с небольшим количеством ограничений. Digital Ocean и Python Anywhere являются примерами провайдеров, которые предлагают относительно недорой базовый тариф (от $5 до $10USD в месяц).

Примечание: Необходимо помнить, что цена не является единственным критерием выбора. Если ваш сайт успешен, то может так случиться, что масштабирование станет самым важным элементом вашего внимания при выборе услуг хостинга.

Подготовка веб-сайта к публикации

Скелет сайта был создан при помощи инструментов django-admin и manage.py, которые настроены таким образом, чтобы сделать разработку проще. Многие настройки файла проекта (определенных в settings.py) должны быть изменены перед публикацией сайта, либо из-за вопросов безопастности, либо производительности.

Примечание: Общепринятым решением является иметь отдельный файл settings.py для публикации, который импортирует важные настройки из внешних файлов, или из переменных окружения. Доступ к данному файлу должен быть ограничен, даже если остальная часть исходного кода доступна в публичном репозитории.

Критически важные настройки файла settings.py:

  • DEBUG. При развертывании сайта должен быть установлен в False (DEBUG = False). Тем самым, прекратится вывод  важной отладочной информации.
  • SECRET_KEY. Это большое случайное число, применяемое для защиты от CRSF. Важно, чтобы ключ, используемый в продакшине, не указывался в исходном коде, и/или не запрашивался с другого сервера. Django рекомендует размещать значение ключа либо в переменной окружения, или в файле с доступом только на чтение.
    # Чтение SECRET_KEY из переменной окружения
    import os
    SECRET_KEY = os.environ['SECRET_KEY']
    
    #ИЛИ
    
    #Чтение ключа из файла
    with open('/etc/secret_key.txt') as f:
        SECRET_KEY = f.read().strip()

Давайте изменим приложение LocalLibrary таким образом, чтобы читать SECRET_KEY и DEBUG из переменных окружения, если те определены, иначе использовать значения по умолчанию.

Откройте /locallibrary/settings.py, закомментируйте исходное значение SECRET_KEY и добавьте новые строки, как указано ниже жирным. В течении разработки, никаких переменных окружения определено не было, таким образом будут использоваться значения по умолчанию (не имеет значения какое ключ вы используете в процессе разработки, поскольку при развертывании проекта вы будете использовать другой).

# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag'
import os
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag')

Затем закоментируйте строку с настройкой DEBUG, а затем, добавьте новую, указанную ниже.

# SECURITY WARNING: don't run with debug turned on in production!
# DEBUG = True
DEBUG = bool( os.environ.get('DJANGO_DEBUG', True) )

Значение DEBUG будет True по умолчанию и станет False, в том случае, если переменная окружения DJANGO_DEBUG будет проинициализирована пустой строкой, то есть, DJANGO_DEBUG=''.

Примечание: Было бы более интуитивно понятным, если бы мы могли просто установить и отключить переменную среды DJANGO_DEBUG непосредственно на True и False , вместо того, чтобы использовать "любую строку" или "пустую строку" (соответсвенно). К сожалению, значения переменных среды сохранены как строки Python, и только строка что оценивается как False является пустой строкой (например, bool('')==False).

Весь перечень настроек для разворачивания вашего сайта находится по ссылке Deployment checklist (Django docs). Кроме того, вы можете получить список настроек, выполнив в терминале команду:

python3 manage.py check --deploy

Пример: Установка LocalLibrary на Heroku

Данный раздел предоставляет демонстрацию того, как установить LocalLibrary на Heroku PaaS cloud.

Почему Heroku?

Heroku - один из самых продолжительных и популярных облачных сервисов PaaS. Первоначально он поддерживал только приложения Ruby, но теперь его можно использовать для размещения приложений из многих сред программирования, включая Django!

Мы выбираем для использования Heroku по нескольким причинам:

  • У Heroku есть свободный уровень, который действительно свободен (хотя и с некоторыми ограничениями)
  • Как PaaS, Heroku заботится о большой веб-инфраструктуре для нас. Это значительно облегчает работу, потому что вы не беспокоитесь о серверах, балансирах нагрузки, обратных прокси или любой другой веб-инфраструктуре, которую Heroku предоставляет нам под капотом.
  • Хотя у этого есть некоторые ограничения, это не повлияет на это конкретное приложение. Например:
    • Heroku предоставляет только недолговечное хранилище, поэтому загруженные пользователем файлы нельзя безопасно хранить на самом Heroku.
    • Свободный уровень будет спать с неактивным веб-приложением, если в течение получаса не будет запросов. После этого сайт может занять несколько секунд, чтобы ответить, когда он проснулся.
    • Свободный уровень ограничивает время, в течение которого ваш сайт работает до определенного количества часов каждый месяц (не включая время, когда сайт «спит»). Это нормально для сайта с низким уровнем использования / демонстрации, но не подходит, если требуется 100% время безотказной работы.
    • Другие ограничения перечислены в Limits (документы Heroku).
  • В основном это просто работает, и если вы в конечном итоге полюбите его, масштабирование вашего приложения будет очень простым.

Хотя Heroku идеально подходит для проведения этой демонстрации, она может быть не идеальна для вашего реального сайта. Heroku упрощает настройку и масштабирование за счет меньшей гибкости и, возможно, обойдется намного дороже, когда вы выходите из свободного уровня.

Как работает Heroku?

Heroku запускает сайты Django внутри одного, или более,  изолированых друг от друга "Dynos", которые являются виртуальными Unix-контейнерами, предоставляющими необходимое окружение для вашего приложения. Данные dynos полностью изолированы и имеют эфемерную файловую систему ("короткоживущая" файловая система, которая полностью очищается и обновляется каждый раз, когда dyno перезапускается). Единственной сущностью, которую предоставляет dynos по умолчанию, является приложение по конфигурации переменных. Heroku внутри себя применяет балансировщик загрузки для распределения веб-трафика среди всех "веб"-dynos. Поскольку dynos изолированы, Heroku может масштабировать приложение горизонтально, просто добавляя больше dynos (хотя, конечно, у вас может появиться необходимость расширить базу данных для обработки дополнительных соединений).

Файловая система эфемерна, поэтому вы не можете напрямую установить необходимые для вашего приложения сервисы (то есть, базы данных, очереди, системы кэширования, хранения, сервисы электронной почты и так далее). Взамен этого, Heroku предоставляет сервисы, доступные как независимые "дополнения" ("add-ons") либо от самой Heroku, или от сторонних разработчиков. В тот момент когда ваше приложение запускается в системе, dynos получает доступ к сервисам, используя информацию, содержащуюся в переменных настройки вашего приложения.

Для того, чтобы выполнить ваше приложение Heroku необходимо иметь возможность установить соответствующее окружение и зависимости, а также понимать как его (приложение) запустить. В случае приложений Django мы предоставляем соответствующую информацию в нескольких текстовых файлах:

  • runtime.txt: язык программирования и его версию.
  • requirements.txt: необходимые для Python компоненты, включая Django.
  • Procfile: Список процессов, которые будут выполнены для старта веб-приложения. Для Django это обычно сервер веб-приложений Gunicorn (скрипт .wsgi).
  • wsgi.py: конфигурация WSGI для вызова нашего приложения Django в окружении Heroku.

Разработчики Developers взаимодействуют с Heroku при помощи специального клиентского приложения/терминала, который сильно похож на bash-скрипт Unix. Оно позволяет вам загружать код, находящийся в git-репозитории, контроллировать выполняемые процессы, смотреть логи, устанавливать конфигурационные переменные и многое другое!

Для того, чтобы заставить ваше приложение работать с Heroku, нам нужно разместить наше веб-приложение в git-репозитории, добавить, перечисленные ранее, файлы, подключить дополнение (add-on) базы данных и выполнить настройки для правильной работы со статическими файлами.

Когда мы выполним все, что необходимо для нашего сайта мы можем создать аккаунт Heroku, получить доступ к клиенту Heroku и использовать его, для установки нашего веб-сайта.

Примечание: Инструкции, перечисленные ниже, соответствуют процессу работы с Heroku во время написания данной статьи (английской версии - прим. перев.). Если Heroku значительно изменит этот процесс, вы можете воспользоваться соответствующим описанием: Heroku начало работы с Django.

На этом завершается краткий обзор начала работы с Heroku (более подробное руководство Как работает Heroku).

Создание репозитория приложения на Github

Heroku тесно интегрирована с системой управления версиями исходного кода git, используя ее для загрузки / синхронизации любых изменений, которые вы вносите в живую систему. Он делает это, добавляя новый «удаленный» репозиторий heroku с именем heroku, указывающий на репозиторий для вашего источника в облаке Heroku. Во время разработки вы используете git для хранения изменений в вашем «master» репозитории. Когда вы хотите развернуть свой сайт, вы синхронизируете свои изменения в репозитории Heroku.

Примечание: Если вы привыкли следовать хорошей практике разработки программного обеспечения, вы, вероятно, уже используете git или какую-либо другую систему SCM. Если у вас уже есть git-репозиторий, вы можете пропустить этот шаг.

Существует множество способов работы с git, но одним из самых простых является создание учетной записи в Github, создание репозитория там, а затем синхронизация с ним локально:

  1. Посетите https://github.com/ и создайте аккаунт.
  2. Once you are logged in, click the + link in the top toolbar and select New repository.
  3. Fill in all the fields on this form. While these are not compulsory, they are strongly recommended.
    • Enter a new repository name (e.g. django_local_library), and description (e.g. "Local Library website written in Django".
    • Choose Python in the Add .gitignore selection list.
    • Choose your preferred license in the Add license selection list.
    • Check Initialize this repository with a README.
  4. Press Create repository.
  5. Click the green "Clone or download" button on your new repo page.
  6. Copy the URL value from the text field inside the dialog box that appears (it should be something like: https://github.com/<your_git_user_id>/django_local_library.git).

Now the repository ("repo") is created we are going to want to clone it on our local computer:

  1. Install git for your local computer (you can find versions for different platforms here).
  2. Open a command prompt/terminal and clone your repository using the URL you copied above:
    git clone https://github.com/<your_git_user_id>/django_local_library.git
    
    This will create the repository below the current point.
  3. Navigate into the new repo.
    cd django_local_library.git

The final step is to copy in your application and then add the files to your repo using git:

  1. Copy your Django application into this folder (all the files at the same level as manage.py and below, not their containing locallibrary folder).
  2. Open the .gitignore file, copy the following lines into the bottom of it, and then save (this file is used to identify files that should not be uploaded to git by default).
    # Text backup files
    *.bak
    
    #Database
    *.sqlite3
  3. Open a command prompt/terminal and use the add command to add all files to git.
    git add -A
    
  4. Use the status command to check all files that you are about to add are correct (you want to include source files, not binaries, temporary files etc.). It should look a bit like the listing below.
    > git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            modified:   .gitignore
            new file:   catalog/__init__.py
            ...
            new file:   catalog/migrations/0001_initial.py
            ...
            new file:   templates/registration/password_reset_form.html
  5. When you're satisfied commit the files to your local repository:
    git commit -m "First version of application moved into github"
  6. Then synchronise your local repository to the Github website, using the following:
    git push origin master

When this operation completes, you should be able to go back to the page on Github where you created your repo, refresh the page, and see that your whole application has now been uploaded. You can continue to update your repository as files change using this add/commit/push cycle.

Tip: This is a good point to make a backup of your "vanilla" project — while some of the changes we're going to be making in the following sections might be useful for deployment on any platform (or development) others might not.

The best way to do this is to use git to manage your revisions. With git you can not only go back to a particular old version, but you can maintain this in a separate "branch" from your production changes and cherry-pick any changes to move between production and development branches. Learning Git is well worth the effort, but is beyond the scope of this topic.

The easiest way to do this is to just copy your files into another location. Use whichever approach best matches your knowledge of git!

Update the app for Heroku

This section explains the changes you'll need to make to our LocalLibrary application to get it to work on Heroku. While Heroku's Getting Started on Heroku with Django instructions assume you will use the Heroku client to also run your local development environment, our changes here are compatible with the existing Django development server and ways of working we've already learned.

Procfile

Create the file Procfile (no extension) in the root of your GitHub repository to declare the application's process types and entry points. Copy the following text into it:

web: gunicorn locallibrary.wsgi --log-file -

The "web:" tells Heroku that this is a web dyno and can be sent HTTP traffic. The process to start in this dyno is gunicorn, which is a popular web application server that Heruko recommends. We start Gunicorn using the configuration information in the module locallibrary.wsgi (created with our application skeleton: /locallibrary/wsgi.py).

Gunicorn

Gunicorn is the recommended HTTP server for use with Django on Heroku (as referenced in the Procfile above). It is a pure-Python HTTP server for WSGI applications that can run multiple Python concurrent processes within a single dyno (see Deploying Python applications with Gunicorn for more information).

While we won't need Gunicorn to serve our LocalLibrary application during development, we'll install it so that it becomes part of our requirements for Heroku to set up on the remote server.

Install Gunicorn locally on the command line using pip (which we installed when setting up the development environment):

pip3 install gunicorn

Database configuration

We can't use the default SQLite database on Heroku because it is file-based, and it would be deleted from the ephemeral file system every time the application restarts (typically once a day, and every time the application or its configuration variables are changed).

The Heroku mechanism for handling this situation is to use a database add-on and configure the web application using information from an environment configuration variable, set by the add-on. There are quite a lot of database options, but we'll use the hobby tier of the Heroku postgres database as this is free, supported by Django, and automatically added to our new Heroku apps when using the free hobby dyno plan tier.

The database connection information is supplied to the web dyno using a configuration variable named DATABASE_URL. Rather than hard-coding this information into Django, Heroku recommends that developers use the dj-database-url package to parse the DATABASE_URL environment variable and automatically convert it to Django’s desired configuration format. In addition to installing the dj-database-url package we'll also need to install psycopg2, as Django needs this to interact with Postgres databases.

dj-database-url (Django database configuration from environment variable)

Install dj-database-url locally so that it becomes part of our requirements for Heroku to set up on the remote server:

$ pip3 install dj-database-url
settings.py

Open /locallibrary/settings.py and copy the following configuration into the bottom of the file:

# Heroku: Update database configuration from $DATABASE_URL.
import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)

Note:

  • We'll still be using SQLite during development because the DATABASE_URL environment variable will not be set on our development computer.
  • The value conn_max_age=500 makes the connection persistent, which is far more efficient than recreating the connection on every request cycle. However, this is optional and can be removed if needed.
psycopg2 (Python Postgres database support)

Django needs psycopg2 to work with Postgres databases and you will need to add this to the requirements.txt for Heroku to set this up on the remote server (as discussed in the requirements section below).

Django will use our SQLite database locally by default, because the DATABASE_URL environment variable isn't set in our local environment. If you want to switch to Postgres completely and use our Heroku free tier database for both development and production then you can. For example, to install psycopg2 and its dependencies locally on a Linux-based system you would use the following bash/terminal commands:

sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib
pip3 install psycopg2

Installation instructions for the other platforms can be found on the psycopg2 website here.

However, you don't need to do this — you don't need PostGreSQL active on the local computer, as long as you give it to Heroku as a requirement, in requirements.txt (see below).

Serving static files in production

During development we used Django and the Django development web server to serve our static files (CSS, JavaScript, etc.). In a production environment we instead typically serve static files from a content delivery network (CDN) or the web server.

Note: Serving static files via Django/web application is inefficient because the requests have to pass through unnecessary additional code (Django) rather than being handled directly by the web server or a completely separate CDN. While this doesn't matter for local use during development, it would have a significant performance impact if we were to use the same approach in production. 

To make it easy to host static files separately from the Django web application, Django provides the collectstatic tool to collect these files for deployment (there is a settings variable that defines where the files should be collected when collectstatic is run). Django templates refer to the hosting location of the static files relative to a settings variable (STATIC_URL), so that this can be changed if the static files are moved to another host/server.

The relevant setting variables are:

  • STATIC_URL: This is the base URL location from which static files will be served, for example on a CDN. This is used for the static template variable that is accessed in our base template (see Django Tutorial Part 5: Creating our home page).
  • STATIC_ROOT: This is the absolute path to a directory where Django's "collectstatic" tool will gather any static files referenced in our templates. Once collected, these can then be uploaded as a group to wherever the files are to be hosted.
  • STATICFILES_DIRS: This lists additional directories that Django's collectstatic tool should search for static files.
settings.py

Open /locallibrary/settings.py and copy the following configuration into the bottom of the file. The BASE_DIR should already have been defined in your file (the STATIC_URL may already have been defined within the file when it was created. While it will cause no harm, you might as well delete the duplicate previous reference).

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

# The absolute path to the directory where collectstatic will collect static files for deployment.
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'

We'll actually do the file serving using a library called WhiteNoise, which we install and configure in the next section.

For more information, see Django and Static Assets (Heroku docs).

Whitenoise

There are many ways to serve static files in production (we saw the relevant Django settings in the previous sections). Heroku recommends using the WhiteNoise project for serving of static assets directly from Gunicorn in production.

Note: Heroku automatically calls collectstatic and prepares your static files for use by WhiteNoise after it uploads your application. Check out WhiteNoise documentation for an explanation of how it works and why the implementation is a relatively efficient method for serving these files.

The steps to set up WhiteNoise to use with the project are:

WhiteNoise

Install whitenoise locally using the following command:

$ pip3 install whitenoise
settings.py

To install WhiteNoise into your Django application, open /locallibrary/settings.py, find the MIDDLEWARE setting and add the WhiteNoiseMiddleware near the top of the list, just below the SecurityMiddleware:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Optionally, you can reduce the size of the static files when they are served (this is more efficient). Just add the following to the bottom of /locallibrary/settings.py:

# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

Requirements

The Python requirements of your web application must be stored in a file requirements.txt in the root of your repository. Heroku will then install these automatically when it rebuilds your environment. You can create this file using pip on the command line (run the following in the repo root):

pip3 freeze > requirements.txt

After installing all the different dependencies above, your requirements.txt file should have at least these items listed (though the version numbers may be different). Please delete any other dependencies not listed below, unless you've explicitly added them for this application.

dj-database-url==0.4.1
Django==1.10.2
gunicorn==19.6.0
psycopg2==2.6.2
whitenoise==3.2.2

Make sure that a psycopg2 line like the one above is present! Even iIf you didn't install this locally then you should still add this to the requirements.txt.

Runtime

The runtime.txt file, if defined, tells Heroku which programming language to use. Create the file in the root of the repo and add the following text:

python-3.5.2

Note: Heroku only supports a small number of Python runtimes. You can specify other Python 3 runtime values, but at time of writing the above version will actually be supported for definite.

Save changes to Github and re-test

Next lets save all our changes to Github. In the terminal (whist inside our repository), enter the following commands:

git add -A
git commit -m "Added files and changes required for deployment to heroku"
git push origin master

Before we proceed, lets test the site again locally and make sure it wasn't affected by any of our changes above. Run the development web server as usual and then check the site still works as you expect on your browser.

python3 manage.py runserver

We should now be ready to start deploying LocalLibrary on Heroku.

Get a Heroku account

To start using Heroku you will first need to create an account:

  • Go to www.heroku.com and click the SIGN UP FOR FREE button.
  • Enter your details and then press CREATE FREE ACCOUNT. You'll be asked to check your account for a sign-up email.
  • Click the account activation link in the signup email. You'll be taken back to your account on the web browser.
  • Enter your password and click SET PASSWORD AND LOGIN.
  • You'll then be logged in and taken to the Heroku dashboard: https://dashboard.heroku.com/apps.

Install the client

Download and install the Heroku client by following the instructions on Heroku here.

After the client is installed you will be able run commands. For example to get help on the client:

heroku help

Create and upload the website

To create the app we run the "create" command in the root directory of our repository. This creates a git remote ("pointer to a remote repository") named heroku in our local git environment.

heroku create

Note: You can name the remote if you like by specifying a value after "create". If you don't then you'll get a random name. The name is used in the default URL.

We can then push our app to the Heroku repository as shown below. This will upload the app, package it in a dyno, run collectstatic, and start the site.

git push heroku master

If we're lucky, the app is now "running" on the site, but it won't be working properly because we haven't set up the database tables for use by our application. To do this we need to use the heroku run command and start a "one off dyno" to perform a migrate operation. Enter the following command in your terminal:

heroku run python manage.py migrate

We're also going to need to be able to add books and authors, so lets also create our administration superuser, again using a one-off dyno:

heroku run python manage.py createsuperuser

Once this is complete, we can look at the site. It should work, although it won't have any books in it yet. To open your browser to the new website, use the command:

heroku open

Create some books in the admin site, and check out whether the site is behaving as you expect.

Managing addons

You can check out the add-ons to your app using the heroku addons command. This will list all addons, and their price tier and state.

>heroku addons

Add-on                                     Plan       Price  State
─────────────────────────────────────────  ─────────  ─────  ───────
heroku-postgresql (postgresql-flat-26536)  hobby-dev  free   created
 └─ as DATABASE

Here we see that we have just one add-on, the postgres SQL database. This is free, and was created automatically when we created the app. You can open a web page to examine the database add-on (or any other add-on) in more detail using the following command:

heroku addons:open heroku-postgresql

Other commands allow you to create, destroy, upgrade and downgrade addons (using a similar syntax to opening). For more information see Managing Add-ons (Heroku docs).

Setting configuration variables

You can check out the configuration variables for the site using the heroku config command. Below you can see that we have just one variable, the DATABASE_URL used to configure our database.

>heroku config

=== locallibrary Config Vars
DATABASE_URL: postgres://uzfnbcyxidzgrl:j2jkUFDF6OGGqxkgg7Hk3ilbZI@ec2-54-243-201-144.compute-1.amazonaws.com:5432/dbftm4qgh3kda3

If you recall from the section on getting the website ready to publish, we have to set environment variables for DJANGO_SECRET_KEY and DJANGO_DEBUG. Let's do this now.

Note: The secret key needs to be really secret! One way to generate a new key is to create a new Django project (django-admin startproject someprojectname) and then get the key that is generated for you from its settings.py.

We set DJANGO_SECRET_KEY using the config:set command (as shown below). Remember to use your own secret key!

>heroku config:set DJANGO_SECRET_KEY=eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh&=

Setting DJANGO_SECRET_KEY and restarting locallibrary... done, v7
DJANGO_SECRET_KEY: eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh

We similarly set DJANGO_DEBUG:

>heroku config:set DJANGO_DEBUG=''

Setting DJANGO_DEBUG and restarting locallibrary... done, v8

If you visit the site now you'll get a "Bad request" error, because the ALLOWED_HOSTS setting is required if you have DEBUG=False (as a security measure). Open /locallibrary/settings.py and change the ALLOWED_HOSTS setting to include your base app url (e.g. 'locallibrary1234.herokuapp.com') and the URL you normally use on your local development server.

ALLOWED_HOSTS = ['<your app URL without the https:// prefix>.herokuapp.com','127.0.0.1']
# For example: 
# ALLOWED_HOSTS = ['fathomless-scrubland-30645.herokuapp.com','127.0.0.1']

Then save your settings and commit them to your Github repo and to Heroku:

git add -A
git commit -m 'Update ALLOWED_HOSTS with site and development server URL'
git push origin master
git push heroku master

After the site update to Heroku completes, enter an URL that does not exist (e.g. /catalog/doesnotexist/). Previously this would have displayed a detailed debug page, but now you should just see a simple "Not Found" page.

Debugging

The Heroku client provides a few tools for debugging:

heroku logs  # Show current logs
heroku logs --tail # Show current logs and keep updating with any new results
heroku config:set DEBUG_COLLECTSTATIC=1 # Add additional logging for collectstatic (this tool is run automatically during a build)
heroku ps   #Display dyno status

If you need more information than these can provide you will need to start looking into Django Logging.

Summary

That's the end of this tutorial on setting up Django apps in production, and also the series of tutorials on working with Django. We hope you've found them useful. You can check out a fully worked-through version of the source code on Github here.

The next step is to read our last few articles, and then complete the assessment task.

See also

Метки документа и участники

Внесли вклад в эту страницу: kivaschenko, al+chernin
Обновлялась последний раз: kivaschenko,