Развёртывание django-проекта под ключ (linux + apache + mysql + django)

f8ee7cd563ee4f80ad62d86b2bdcea16

Я занималась штампованием django-сайтиков и потому возникла необходимость максимальной автоматизации различных процессов, связанных с разработкой, деплоем и поддержкой проектов, вследствие чего мной было разработано несколько решений. Одним из них я поделюсь в этой статье – это скрипт деплоя проекта на пустую debian-машину, с ним развётрывание стало лёгким и непринуждённым. Под катом Вы найдёте инструкцию, как развернуть django-приложение за 10 минут, из них 5 займёт чтение статьи и ещё 5 – собственно дело. Способ годен для начинающих, не имеющих никаких знаний в админстве.

Для того, чтобы выложить проект, нужно его подготовить, купить сервер, развернуть и всё протестировать.

1. Подготовка проекта:

Если проекта как такового у Вас нет, то можете пропустить этот шаг. Мой скрипт по умолчанию будет загружать пустой django-проект с моего гитхаба.

Если ссылки на гитхаб у Вас не работают, то на линуксе делаем так

Если проект уже есть:

  • Нужно загрузить проект в git-репозиторий либо подправить скрипт на код, который будет вытаскивать проект из нужного места (wget, например).
  • В корне проекта должен лежать файл requirements со всеми pip-зависимостями. Отмечу, что там обязательно должны стоять версии пакетов.
  • В корне должен быть корректный файл wsgi.py (по умолчанию в последних версиях django он лежит в projectname/, так вот, его оттуда нужно перенести в ../)
  • Опционально там же может находиться файл с apt-зависимостями под именем apt-requirements.
  • Корректный файл settings. В качестве базы по умолчанию будем использовать MySQL, поэтому в поле ENGINE должно стоять значение ‘django.db.backends.mysql’.

Примеры этих файлов, которые кочуют у меня из проекта в проект, можно посмотреть в тестовом django-проекте.

2. Подготовка хостинга:

Вы можете выбрать любой хостинг с debian дистрибутивом, главное – иметь права рута. Я буду рассказывать по шагам, как настраивать VDS на FirstVDS. Для начала можно выбрать специальный тестовый тариф VDS-Разминка за 60 руб в месяц либо VDS-Старт за 200 руб. У меня на одном сервере (тариф Разгон, 350 руб) было размещено около 20 среднестатистических клиентских сайта, всё работало исправно.

  • Итак, переходим на FirstVDS.
  • Регистрируемся, входим в личный кабинет.
  • На главной: Заказать услугу -> Виртуальный сервер -> VDS-OVZ-Разминка (или Старт)-> Заказать.
  • Доменное имя пишем любое, Шаблон ОС – Debian (! это важно), панель управления – это гуй, он стоит 150 руб в месяц, мы вполне обойдёмся и без него. Снимаем галочку.
  • Привязываем номер телефона, оплачиваем сервер и ждём активации (примерно 5 мин). После этого должно прийти уведомление с доступами на email.
  • Подключаемся к серверу по ssh через рута.

3. Развёртывание:
Так как мы зашли под рутом, то нужно создать нового обычного пользователя и работать через него. Я написала мини-скрипт, делающий это:

#! /bin/bash
 
if [ $# -eq 0 ]
then
    echo "Введите имя нового пользователя, который будет рулить сайтом. (Не рут же это будет, в самом деле)"
else
    useradd -m $1                                   # добавляем юзера
    passwd $1                                       # назначаем ему пароль
    echo "$1 ALL=(ALL) ALL" >> /etc/sudoers         # делаем судоером
    chsh -s /bin/bash $1
    cd /home/$1/
    # скачиваем код скрипта c gist
    wget https://gist.github.com/kpx13/51e37fbd2b457cd6d821/raw/70ad75f0164c97abdcd30660ae359f6c468fe213/django_deploy_script.sh
    chown $1:$1 django_deploy_script.sh
    chmod ug+x django_deploy_script.sh                      # делаем его исполняемым
fi

Скрипт хранится на gist, поэтому мы выкачиваем его и выполняем команды:

wget https://gist.github.com/kpx13/51e37fbd2b457cd6d821/raw/e5c8393c64a3c9123e31228095bfae1f282b2d17/initial_script.sh
/bin/bash initial_script.sh <юзернейм нового пользователя>
su <юзернейм>
cd

После этого видим в домашней директории файл django_deploy_script.sh с содержимым:

#! /bin/bash
 
#аргументы ниже нужно заполнить!
PROJECT_NAME="django_empty_project"                                 # * название проекта
GITHUB_PROJECT="https://github.com/kpx13/django_empty_project.git"  # * адрес гитхаб-репозитория
DB_ROOT_PASSWORD="asdf"                                             # * пароль рута от MySQL
DB_NAME="mysql_db_name"                                             # * конфиг БД (должен совпадать с конфигом в settings.py) название БД
DB_USER="mysql_db_user"                                             # * юзер
DB_PASSWORD="mysql_db_password"                                     # * пароль
 
APACHE_SERVER_NAME="yoursite.ru"                                    # домен
GITHUB_EMAIL="[email protected]"                                     # конфиг для гитхаба, эмейл
GITHUB_USERNAME='annkpx'                                            # конфиг для гитхаба, юзернэйм
# конец аргументов
 
APACHE_LISTEN="$(hostname --ip-address):80"
THIS_PATH=$PWD
PROJECT_ROOT=$THIS_PATH/$PROJECT_NAME
 
# установка базовых пакетов
distr_install ()
{
    echo "Устанавливаем ПО..."
    sudo apt-get update
    yes | sudo apt-get install apache2 libapache2-mod-wsgi # необходимо для работы связки apache + django
    yes | sudo apt-get install python-dev python-pip # необходимо для работы связки  python + mysql
    yes | sudo apt-get install libjpeg62 libjpeg62-dev libfreetype6 libfreetype6-dev zlib1g-dev # необходимо для графики и шрифтов
    
    # MySQL + Python
    read -p "Сейчас будет устанавливаться MySQL, в синем окне Вы должны 2 раза ввести пароль рута для базы: $DB_ROOT_PASSWORD" 
    yes | sudo apt-get install mysql-server
    yes | sudo apt-get install python-mysqldb
}
 
# выкачивание репозитория с кодом
git_init ()
{
    # если будет использоваться не git, а что-то другое, эту функцию нужно переписать
    yes | sudo apt-get install git
    echo "Клонируем репозиторий с гитхаба..."
    echo "192.30.252.128 github.com" | sudo tee --append /etc/hosts   # всвязи с суицидниками на гитхабе
    git clone $GITHUB_PROJECT
    echo ".*
*.pyc
env/
logs/
static/" > $PROJECT_ROOT/.gitignore   # стандартный файл .gitignore, можно отредактировать
    git config --global user.email $GITHUB_EMAIL
    git config --global user.name $GITHUB_USERNAME
}
 
# удовлетворение зависимостей
project_req ()
{
    echo "Устанавливаем зависимости..."
    cat $PROJECT_ROOT/apt-requirements | xargs sudo apt-get install # установка apt-зависимостей
    sudo pip install -r $PROJECT_ROOT/requirements # установка pip-зависимостей 
}
 
# создание базы MySQL
create_db ()
{
    # если будет использоваться другая база, заменить эту часть
    mysql -u root -p$DB_ROOT_PASSWORD -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD'"
    mysql -u root -p$DB_ROOT_PASSWORD -e "CREATE DATABASE $DB_NAME"
    mysql -u root -p$DB_ROOT_PASSWORD -e "GRANT ALL ON $DB_NAME.* TO $DB_USER@localhost"
    echo "БД установлена..."
}
 
# инициализация в джанго
django ()
{
    cd $PROJECT_ROOT
    
    echo "Собираем статику..."
    mkdir media 2>/dev/null
    mkdir media/uploads 2>/dev/null
    python manage.py collectstatic
    
    echo "Синхронизируем БД..."
    python manage.py syncdb
}
 
# установка apache
apache_set()
{
    # настройка связки с apache
    cd $PROJECT_ROOT
    echo "Alias /media/ $PROJECT_ROOT/media/
<Directory $PROJECT_ROOT/media>
            Order allow,deny
            Options -Indexes
            Allow from all
            IndexOptions FancyIndexing
</Directory>

Alias /static/ $PROJECT_ROOT/static/
<Directory $PROJECT_ROOT/static>
            Order allow,deny
            Options -Indexes
            Allow from all
            IndexOptions FancyIndexing
</Directory>

WSGIScriptAlias / $PROJECT_ROOT/wsgi.py
" > httpd.conf
 
    echo "<VirtualHost $APACHE_LISTEN >
        ServerName $APACHE_SERVER_NAME
        CustomLog $PROJECT_ROOT/logs/access.log combined
        DocumentRoot $PROJECT_ROOT
        ErrorLog $PROJECT_ROOT/logs/error.log
        ServerAlias www.$APACHE_SERVER_NAME

        Include '$PROJECT_ROOT/httpd.conf'
</VirtualHost>

WSGIPythonPath $PROJECT_ROOT
" | sudo tee /etc/apache2/sites-enabled/$PROJECT_NAME
 
    chmod -R ugo+rw media/
    chmod -R a+rw media/
    mkdir logs 2>/dev/null
    sudo /etc/init.d/apache2 restart
}
 
# деплой под ключ на пустой машине
all () 
{
    echo "Выполняем деплой проекта под ключ."
    distr_install
    git_init
    project_req
    create_db
    django
    apache_set
    echo "Скрипт отработан."
    exit
}
 
 
 
clear
clear
 
echo "
Скрипт выполняется последовательно, по шагам. Можно запустить выполнение сразу всех шагов используя пункт меню 7 или пройти по всем меню подряд для пущего контроля.

Меню:"
 
OPTIONS="ПО Гит Зависимости БазаДанных Джанго apache ВСЁ Выход"
select opt in $OPTIONS
do
    case $opt in
        "ПО")             distr_install   ;;  
        "Гит")            git_init        ;;
        "Зависимости")    project_req     ;;
        "БазаДанных")     create_db       ;;
        "Джанго")         django          ;;
        "apache")         apache_set      ;;
        "ВСЁ")            all             ;;
        "Выход")          exit            ;;
    esac
done

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

./django_deploy_script.sh

Можно выбрать пункт меню 7, тогда всё будет установлено «под ключ», либо пройти последовательно от 1 до 6.

Когда скрипт отработает, заходим на сервер по ip и оцениваем результат.

Заключение.
Когда я только начинала делать сайтики на django, деплой проектов у меня занимал время, соизмеримое со временем разработки. С опытом всё изменилось. За эти годы я разработала конвейер, который позволяет и быстро создавать сайты, и быстро деплоить. Есть аналогичный скрипт для деплоя на nginx, если нужно – выложу. Я делала так: у меня был свой сервер на nginx, там было много сайтов со своими виртуальными окружениями. Перед тем, как разместить у клиента на отдельном сервере, я размещала и отлаживала сайт у себя, а после оплаты переносила на отдельный хостинг.