Django на сервере: Nginx + uWSGI + Postgres + Ubuntu 16.04
После разработки вашего приложения, наступает пора когда его нужно деплоить, то есть сделать так, чтоб ваше приложение было доступно в интернете. Данная задаче не так тривиальна и проста как может показаться, ведь сервер, который поставляется вместе с django абсолютно не подходит для этих целей, а только для разработки вашего приложения.
Перед тем как начать развертывание приложения стоит определиться с тем, на чем вы его собираетесь разворачивать (деплоить). Для этих целей уже может не подойти обычный shared hosting и вам нужно будет заказывать VPS или VDS сервер. Благо стоят они не дорого, а их конфигураций вам будет вполне достаточно для того, чтобы ваш проект жил и выдерживал трафик проходящий через него. Соответсвенно перед тем как деплоить вам нужен VSP и VDS сервер. Предположим, что он у вас есть с установленной на нем Ubuntu 16.04.
Создаем пользователя
Для того, чтобы работать дальше нам нужно создать пользователя в нашей системе, но, чтобы он мог использовать sudo. Таким образом мы обезопасим наш сервер и не дадим root пользователю "случайно" сломать наш сервер. Такой подход используется исключительно в целях безопасности. Для этого создадим пользователя введя команду в консоль:
$ adduser user
Вместо user вы можете задать собственного пользователя, а также при выполнении данной команды вам потребуется задать пароль для данного пользователя. Далее мы должны предоставить нашему пользователя sudo привилегии, добавив его в группу sudo:
$ usermod -aG sudo dikiigr
Для того, чтобы переключится на нашего созданного пользователя выполним команду:
$ su - user
Также сразу же добавим нашего пользователя также в группу www-data, так как именно используя данную группу будет запущенны ngix и uwsgi:
$ sudo usermod -aG www-data user
На данном этапе мы подготовили пользователя под которым будет происходить деплой нашего приложения. Также стоит отметить, что теперь вы можете подключаться к серверу так:
$ shh user@ваш_ip
После чего вводит пароль пользователя и получаете доступ к серверу.
Внимание! Везде, в командах выше замените user на имя вашего пользователя!
Установка пакетов
Перед тем как двигаться дальше, нам нужно установить нужные пакеты для деплоя. Стоит отметить, что мой Django проект использует python 3 и соответственно деплой будет происходить под него, но вам также не составит труда по аналогии деплоить и для python 2.7. Для установки нужных пакетов выполним команды:
$ sudo apt-get update
$ sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
Первая команда обновляет данные о репозиториях пакетов, а втора устанавливает pip3, postges, nginx и их зависимости.
Создание базы данных Postges
После установки postges, он по умолчанию создал пользователя postges с sudo привилегиями. Для создания нашей базы данных мы должны войти в консольное приложение psql, для чего выполним команду:
$ sudo -u postgres psql
Таким образом мы аунтифицируемся как postgres пользователь и нам не нужно вводить пароль для него (мы также могли аунтифицироваться под нашим пользователем). После открытия приложения мы можем выполнять команды SQL, которые "понимает" postgres БД. Сперва создадим базу данных:
postgres=# CREATE DATABASE myproject;
Замените myproject на имя вашей БД. Создадим пользователя БД и зададим ему пароль:
postgres=# CREATE USER myprojectuser WITH PASSWORD 'password';
Замените myprojectuser на вашего пользователя и задайте ему пароль. Также нам нужно дать все привелегии нашему пользователю БД для управления ею.
postgres=# GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
После данных действий выйдем из консольного интерфейса командой:
postgres=# \q
Виртуальное окружение: virtualenv и virtualenvwrapper
Для нашего Django проекта необходимо создать виртуальное окружение, которое бы позволило работать python с нашим проектом не затрагивая другие пакеты, чтоб не засорять пакетами глобальную область. Для этого установим следующие пакеты:
$ sudo -H pip3 install --upgrade pip
$ sudo -H pip3 install virtualenv virtualenvwrapper
virtualenv и virtualenvwrapper позволят нам удобным образом работать с виртуальными окружениями. virtualenvwrapper позволяет нам хранить все виртуальные окружения в одной директории, после чего переключаться между ними используя команду workon project. После установки данных программ нам нужно в локальном .bashrc прописать настройки нашей программы, для этого выполним команды:
$ echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc
$ echo "export WORKON_HOME=~/venv" >> ~/.bashrc
$ echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc
VIRTUALENVWRAPPER_PYTHON - указываем какой python использовать по умолчанию. WORKON_HOME - путь к директории с виртуальными окружениями. Для того, чтобы применить изменения для текущей сессии выполним команду:
$ source ~/.bashrc
Теперь у нас создастся директория venv в домашней директории нашего пользователя и установятся скрипты для работы с ней.
Установка Django
Перед тем, как работать с Django нам нужно его установить, но для начала создадим виртуальное окружение:
$ mkvirtualenv myproject
mysity - название вашего виртуального окружения. После его инициализации вы автоматически "перейдете" в него, то есть у вас будет использоваться данное окружение. Для того, чтобы из него выйти нужно выполнить команду:
$ deactivate
А для того, чтобы вернуться обратно выполнить команду:
$ workon myproject
Теперь установим django и пакет для работы с postgers находясь в виртуальном окружении:
$ pip install django psycopg2
После установки создадим наш проект:
$ django-admin.py startproject myproject ~/myproject
После этого, нам нужно провести некоторые правки в settings.py, а именно настроим проект для работы с базой, а также разрешим наш хост и укажем настройки для статики:
$ nano ~/myproject/myproject/settings.py
...
ALLOWED_HOSTS = ['*']
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Теперь применим миграции, создадим супер пользователя и переместим статику Django к себе в проект:
$ ~/myproject/manage.py makemigrations
$ ~/myproject/manage.py migrate
$ ~/myproject/manage.py createsuperuser
$ ~/myproject/manage.py collectstatic
Django и uWSGI
Теперь нам нужно настроить связку Django и uWSGI. Идея простая: uWSGI должен запускать проложение Django, получать запросы от пользователей и выдавать ответ. Для этого нужно выйти из виртуального окружения, чтоб установить его глобально:
$ deactivate
$ sudo -H pip3 install uwsgi
Для сохранения наших настроек для uWSGI создадим директорию:
$ sudo mkdir -p /etc/uwsgi/sites
А в ней создадим скрипт с настройками для нашего проекта:
$ sudo nano /etc/uwsgi/sites/myproject.ini
Зададим ему следующее содержимое:
[uwsgi] project = myproject uid = user base = /home/%(uid) chdir = %(base)/%(project) home = %(base)/venv/%(project) module = %(project).wsgi:application master = true processes = 5 socket = /run/uwsgi/%(project).sock chown-socket = %(uid):www-data chmod-socket = 660 vacuum = true
- project - переменная, название вашего проекта
- uid - переменная, созданный нами пользователь
- base - переменная, путь к домашней директории пользователя
- chdir - путь к корню нашего проекта
- home - путь к скриптам (в нашем случае виртуальное окружение)
- processes - количество одновременно запущенных процессов для обслуживания нашего проекта
- socket - путь к файлу сокету
- chown-socket - указываем, кто имеет доступ к нашему сокету
- chmod-socket - указываем права (660 - только чтение и запись для группы и пользователя)
- vacuum = true - позволяет очищать файл сокета, когда сервер остановится
Создание systemd Unit файла
Для того, чтобы наш uWSGI сервер запускался при перезагрузке нашего сервера, а также получал нужные ему настройки мы воспользуемся системным менеджером для запуска демонов systemd.
$ sudo nano /etc/systemd/system/uwsgi.service
В данном файле будет следующее содержимое:
[Unit] Description=uWSGI Emperor service [Service] ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown user:www-data /run/uwsgi' ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites Restart=always KillSignal=SIGQUIT Type=notify NotifyAccess=all [Install] WantedBy=multi-user.target
- Description - метаданные, описание задачи
- ExecStartPre - команда выполняемая перед стартом. В нашем случае мы создаем папку /run/uwsgi, где будет хранится наш сокет файл, а также добавляем владельцев для этой папки в качестве user:www-data, чтоб была возможность создавать сокет-файл, считывать с него и писать в него (так работает сервер).
- ExecStart - команда старта. В нашем случае мы указали uWSGI флаг --emperor который позволит запускать множество скриптов для разных проектов, а также указали пусть к папке с конфигами нашего проекта. Таким образом мы можем создавать множество проектов, а uWSGI позаботится о их работе.
- WantedBy - уровень запуска. В нашем случае это многопользовательский режим.
Настройка Nginx
Теперь нам нужно настроить nginx, который выполняет роль proxy сервера, а также может обслуживать статику нашего сайта. Для этого создадим файл конфига:
$ sudo nano /etc/nginx/sites-available/myproject
Со следующим содержимым:
server { listen 80; server_name myproject.com www.myproject.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/user/myproject; } location / { include uwsgi_params; uwsgi_pass unix:/run/uwsgi/myproject.sock; } }
- server_name - название нашего сайта
- root - путь к папке со статикой (сама папка не указывается и должна совпадать с location значением, иначе используйте alias)
- include uwsgi_params - вставляем uwsgi параметры, которые находятся в файле /etc/nginx/uwsgi_params и предоставляются nginx по умолчанию
- uwsgi_pass - указываем путь с сокет-файлу
Для того, чтобы применялись наш конфиг применялся, мы должны создать ссылку на директорию /etc/nginx/sites-enabled:
$ sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Запуск приложения
Мы создали с вами Unit файл, который запускал наш uWSGI сервер, но мы так его и не запустили, для его запуска выполним команду:
$ sudo systemctl start uwsgi
А также перезапустим nginx, чтоб применились изменения:
$ sudo systemctl restart nginx
А чтобы при запуске сервера nginx и uwsgi автоматически запускались выполним команды:
$ sudo systemctl enable nginx
$ sudo systemctl enable uwsgi
Теперь осталось перезапустить сервер и проверить работоспособность:
$ sudo reboot
Если вы все сделали правильно, то проблем не должно возникнуть, иначе по всем вопросам пишите комментарии, а я постараюсь на них ответить.