- PVSM.RU - https://www.pvsm.ru -
Многие учебные пособия по разработке на Django раскрывают как быстро получить работающий отладочный сервер (python manage.py runserver), а вопрос развертывания в боевом режиме часто остается нераскрытым или освещаются далеко не самые простые и эффективные методы.
Ниже я расскажу о об одном из способов развернуть сайт на Django в боевом режиме, начиная от выбора
Для дальнейшего повестования необходимо рассказать про структуру развертываемого проекта:
- myproject/ - корень проекта, обратите внимание, что это не корень исходников проекта;
- env/ - вируальное окружение, создаваемое при помощи virtualenv;
- src/ - папка с иходниками, ее удобно добавить в пути IDE, для того, чтобы обращаться к пакету myproject по имени;
- myproject/ - корень исходников проекта, должна быть знакома Django-программистам;
- __init__.py
- settings.py
- manage.py
- urls.py
- myapp1/
- myapp2/
...
- static_content/ - папка для файлов, которые раздает веб-сервер первого эшелона (у нас - nginx), будучи параноиком, я боюсь передавать веб-серверу папку, содержащую исходники проекта;
- static/ - статические файлы проекта (то что храним в репозитории);
- media/ - media-файлы, то что создается сайтом в ходе его функционирования;
- docs/ - тут лежат полезные документы, комментарии, примеры конфигов;
- logs/ - папка, куда складываю логи, касающиеся работы сайта;
- pids/ - тут pid-файлы.
На первый взгляд глубина вложенности исходников может показаться избыточной. Однако мой опыт показывает, что издержки на работу при такой глубине невелики, а достоинства большей структурированности значительны.
Для себя я давно выяснил, что наиболее удобный
Итак, для того, чтобы начать нужно заказать и оплатить
После заказа и оплаты на почту приходит SSH-доступ, теперь можно приступать к настройке операционной системы.
Получив доступ, я, первым делом, обновляю систему, затем отключаю root-доступ по SSH.
Подключиться по SSH в Windows можно широкоизвестной программой Putty [13], но я использую ее более “накрученную” модификацию — kitty [14]. В качестве IP-адреса сервера вводим высланный хостером адрес, подключаемся, вводим root в качестве user и пароль при запросе.
Для подключения в Линукс-подобных системах используем родной терминал (Terminal, Konsole, etc.), набрав в нем нехитрую команду:
ssh root@1.2.3.4
где 1.2.3.4 — IP-адрес, высланный хостером, при запросе вводим пароль, высланный хостинг-провайдером.
Первым делом сменим пароль рута, паранойи ради:
passwd
по запросу вводим новый пароль дважды, генерировать и хранить советую в KeePassX [15], не стесняйтесь сделать его посложнее (>20 символов), использовать его почти не придется.
Обновляем пакеты в системе:
apt-get update
apt-get upgrade
Добавляем пользователя, от лица которого будем развертывать сервер:
adduser myuser
можно ничего не вводить кроме пароля, но лучше его придумать посложнее
Теперь понадобится редактор для правки конфигов, я предпочитаю nano:
apt-get install nano
Добавляем пользователю права исполнять команды от имени root (sudo):
nano /etc/sudoers
# находим строку
root ALL=(ALL:ALL) ALL
# сразу после нее вставляем
myuser ALL=(ALL:ALL) ALL
Теперь отключаем возможность пользователю root логиниться по SSH (делать необязательно, мера безопасности):
nano /etc/ssh/sshd_config
# ищем
PermitRootLogin yes
# меняем на
PermitRootLogin no
после этого я перезагружаю машину, чтобы убедиться, что все прошло как надо:
reboot
Спустя минуту можно логиниться как myuser (или можете предварительно проверить, что логин рутом больше не работает):
ssh myuser@1.2.3.4
Теперь я ставлю ряд системных пакетов, необходимых для работы Django-приложения и инфраструктуры:
sudo apt-get install gcc mysql-server python-mysqldb memcached mercurial python-profiler w3m python-setuptools libmysqlclient-dev git-core python-dev rabbitmq-server supervisor nginx
Давайте разберем, что есть что:
Для развертывания воспользуемся виртуальным окружением, при помощи инструмента virtualenv.
В предыдущей главе мы установили полезную утилиту easy_install, с помощью которой установим теперь virtualenv последней версии:
sudo easy_install virtualenv
Примечание. Я намеренно не ставил pip глобально, чтобы не было случайных конфликтов с ним у pip’ов в виртуальных окружениях.
Теперь можно приступить к развертыванию проекта. Для начала нужно разместить его где-то в домашней директории, пусть это будет:
/home/myuser/web/myproject
Я пользуюсь системой контроля версий git. Но вы можете добиться этого простым копированием по SCP. В Windows можно использовать WinSCP [17], в линуксах файловые менеджеры поддерживают формат адреса sftp://myuser@1.2.3.4, как вы наверное догадались, в качестве аутентификационных используются данные для доступа по SSH.
В моем проекте в корне лежит файл для сборки виртуального окружения — build_env.sh:
#!/bin/bash
echo $0: Creating virtual environment
virtualenv --prompt="<myenv>" ./env
mkdir ./logs
mkdir ./pids
mkdir ./db
mkdir ./static_content
mkdir ./static_content/media
echo $0: Installing dependencies
source ./env/bin/activate
export PIP_REQUIRE_VIRTUALENV=true
./env/bin/pip install --requirement=./requirements.conf --log=./logs/build_pip_packages.log
echo $0: Making virtual environment relocatable
virtualenv --relocatable ./env
echo $0: Creating virtual environment finished.
и файл requirements.conf, который содержит пакеты, необходимые для работы приложения:
django
git+git://github.com/sehmaschine/django-grappelli.git#egg=django-grappelli
git+git://github.com/django-mptt/django-mptt.git#egg=django-mptt
git+git://github.com/krvss/django-social-auth.git#django-social-auth
git+git://github.com/gabrielhurley/django-wymeditor.git#django-wymeditor
git+git://github.com/jtauber/django-mailer.git#django-mailer
git+git://github.com/tweepy/tweepy.git#tweepy
django-celery
django-debug-toolbar
django-pdb
python-memcached
MySQL-python
xlrd
unidecode
anyjson
gunicorn
pillow
south
fabric
requests
xlwt
Это возможный набор пакетов, как-нибудь расскажу подробнее про некоторые из них, но мы не углубляемся в аспекты разработки в этой теме.
Итак, после запуска в папке проекта /home/myuser/web/myproject:
./build_env.sh
устанавливается виртуальное окружение для работы нашего сервера.
Теперь нужно позаботиться о создании базы данных. В наших проектах мы используем MySQL. Запускаем консоль MySQL:
mysql -uroot -pROOTPASSWORD
где создаем базу и пользователя:
CREATE DATABASE myproject CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE USER 'myproject'@'localhost' IDENTIFIED BY 'USERPASSWORD';
GRANT ALL PRIVILEGES ON myproject.* TO ‘myproject'@'localhost';
теперь настройки доступа можно внести в файл настроек проекта (settings.py или local_settings.py).
Если у вас есть дамп базы — вы знаете, что делать. Если нет, то создаем в ней схему и необходимые данные:
cd ~/web/myproject # возвращаемся в папку проекта
source env/bin/activate # активируем виртуальное окружение
python manage.py syncdb # синхронизируем модели с базой данных
теперь соберем статические файлы:
python manage.py collectstatic
На этом приложение готово к запуску.
Для настройки веб-сервера Nginx нужно разместить конфиг myproject.conf (суффикс должен быть .conf) в папке /etc/nginx/sites-available/.
Создать и отредактировать файл можно в консоле SSH через nano:
sudo nano /etc/nginx/sites-available/myproject.conf
затем вставляем содержимое примера ниже (Shift+Insert), исправляем под свои нужды, сохраняем (Ctrl+O), выходим (Ctrl+X).
Пример содержания файла myproject.conf:
upstream myproject.ru {
server localhost:12345 fail_timeout=0;
}
server {
listen 80;
server_name www.myproject.ru;
rewrite ^/(.*) http://myproject.ru/$1 permanent;
}
server {
listen 80;
client_max_body_size 4G;
server_name myproject.ru;
access_log /home/myuser/web/myproject/logs/myproject.access.log;
keepalive_timeout 5;
root /home/myuser/web/myproject/static_content;
location / {
proxy_pass http://myproject.ru;
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/myuser/web/myproject/static_content/static/html;
}
location ~ ^/(static|media)/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://myproject.ru;
break;
}
}
}
Попробуем разобраться в общих словах, что здесь к чему.
В данном примере upstream — сокет localhost:12345, в который будем пересылать все запросы, которые не удовлетворяют следующим url:
/static/* — статические файлы сайта;
/media/* — медиа-файлы, файлы, которые создаются в процессе функционирования сайта;
На этом сокете мы повесим на прослушивание наш gunicorn в следующей части статьи. Имя апстрима, теоретически, выбирается произвольно, однако я сталкивался с проблемами, в случае, если имя апстрима отличалось от доменного имени сайта (не помню текста ошибок Django, чтобы описать подробнее).
Еще интересные части конфига:
редирект с поддомена www.myproject.ru [18] на myproject.ru, можете сделать наоборот, если вам больше нравится;
обработка ошибок 5XX орагнизована выдачей статического файла 500.html. Получить такой файл довольно просто: заставить сайт показать страницу 404, сохранить в браузере как 500.html и отредактировать текст ошибки;
в случае, если статический файл не найден, запрос направляется gunicorn’у, чтобы тот мог выдать стандартную ошибку 404.
После того, как файл конфига размещен где следует (можно проверить командой cat /etc/nginx/sites-available/myproject.conf), нужно проставить на него симлинк:
sudo ln -s /etc/nginx/sites-available/myproject.conf /etc/nginx/sites-enabled/
и перезапустить nginx:
sudo service nginx restart
При развертывании проекта мы установили пакет gunicorn, теперь мы используем его для формирования динамичеких HTTP-ответов (HTTP-response) Django-приложением. Сам gunicorn умеет принимать запросы и формировать ответы на них, однако нужно поддерживать сам gunicorn запущенным, например стартовать при перезапуске системы, это мы поручим специализирующейся в этом программе supervisor.
Заметьте, что разработчики gunicorn крайне не рекомендуют ставить его на линию фронта, а поручить прием запросов от пользователей специализированным серверам, например nginx, как это делаем мы.
Итак, создаем в папке /etc/supervisor/conf.d/ файл myproject.conf следующего содержания:
[program:myproject]
command=/home/myuser/web/myproject/env/bin/python /home/myuser/web/myproject/src/myproject/manage.py run_gunicorn --bind=localhost:12345 --workers=3 --pid=/home/myuser/web/myproject/pids/gunicorn.pid --log-file /home/myuser/web/myproject/logs/gunicorn.log
directory=/home/myuser/web/myproject/src/myproject
umask=022
autostart=true
autorestart=true
startsecs=10
startretries=3
exitcodes=0,2
stopsignal=TERM
stopwaitsecs=10
user=myuser
Заметьте, что в параметрах gunicorn’у мы передаем для прослушки тот же порт (в нашем примере 12345), что указывали в конфиге nginx’а. Количество рабочих процессов установлено в значение 3, подбирал этот параметр субъективно для одного из сайтов, исходя из своих нагрузок, и пока не могу порекомендовать какое-либо значение.
После того как конфиг размещен в нужной папке (можно проверить запуском cat /etc/supervisor/conf.d/myproject.conf) нужно перечитать файл либо просто перезапустить supervisor, я использую второй вариант для надежности:
sudo supervisorctl reload
проверить успешность запуска можно командой:
sudo supervisorctl status
в случае успеха статус процесса myproject через несколько секунд станет RUNNING.
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
решается добавлением правильной локали:
locale-gen ru_RU.UTF8
по мотивам: http://askubuntu.com/questions/76013/how-do-i-add-locale-to-ubuntu-server [19]
sudo: must be setuid root
решается например так:
chmod 4755 /usr/bin/sudo
libc6-dev : Depends: libc6 (= 2.15-0ubuntu10.2) but 2.15-0ubuntu10+openvz0 is to be installed
E: Unable to correct problems, you have held broken packages.
Для ее решения достаточно модифицировать файл /etc/apt/preferences.d/99ovz-libc-pin:
заменив
libc-bin libc6
на
libc-bin libc6 libc6-dev libc-dev-bin
Couldn't open /dev/null: Permission denied
решал так:
sudo chmod 666 /dev/null
не знаю, насколько это корректно, но я опасностей не увидел.
Отметим положительные моменты такого развертывания:
sudo supervisorctl stop myproject
python manage.py runserver localhost:12345 # из папки с исходниками
теперь nginx будет передавать запросы на сервер разработчика, даже не узнав про изменения.
В сатье расмотрен лишь один из множества вариантов развертывания Django-приложения, я пришел к нему путем многих проб и ошибок. Мои рекомендации не претендуют на истину в последней инстанции. Более того, буду рад любой конструктивной критике.
Автор: alekseyspb
Источник [26]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nginx/20648
Ссылки в тексте:
[1] хостинга: https://www.reg.ru/?rlink=reflink-717
[2] Оглавление: #contents
[3] Структура проекта: #structure
[4] Хостинг: #hosting
[5] Ubuntu server: #ubuntu
[6] Развертывание проекта: #deployement
[7] Настройка веб-сервера Nginx: #nginx
[8] Настройка gunicorn и supervisor: #gunicorn
[9] Устранение проблем: #problems
[10] Заключение: #conclusion
[11] Полезные ссылки: #links
[12] FirstVDS: http://firstvds.ru/?from=96322
[13] Putty: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
[14] kitty: http://www.9bis.net/kitty/
[15] KeePassX: http://www.keepassx.org/
[16] Игорю Сысоеву: http://sysoev.ru/about.html
[17] WinSCP: http://winscp.net/
[18] www.myproject.ru: http://www.myproject.ru
[19] http://askubuntu.com/questions/76013/how-do-i-add-locale-to-ubuntu-server: http://askubuntu.com/questions/76013/how-do-i-add-locale-to-ubuntu-server
[20] Ubuntu LTS: https://wiki.ubuntu.com/LTS
[21] Ubuntu Security: http://www.rationallyparanoid.com/articles/ubuntu-10-lts-security.html
[22] Django Deployement: https://docs.djangoproject.com/en/dev/howto/deployment/fastcgi/
[23] virtualenv: http://pypi.python.org/pypi/virtualenv
[24] Nginx: https://calomel.org/nginx.html
[25] Supervisor+gunicorn: http://gunicorn.org/#deployment
[26] Источник: http://habrahabr.ru/post/159575/
Нажмите здесь для печати.