Часть девятая. Деплой проекта
Мы у финиша
Цель: Выгрузить сайт в интернет
Задачи:
    Указать три способа выгрузки сайта
    Осуществить первый способ
    Осуществить второй способ
    Осуществить третий способ

Какие бывают способы деплоя?

Существует 3 способа выгрузить проект в интернет. Выгрузка проекта называется деплоем.

Способ первый. WGET.

Этот способ самый дешёвый, но при это совершенно не правильный, хоть и простой. При использовании этого способа, сайт будет отображаться страница целиком, но никакие механизмы в нём работать не будут.
    Шаг 0 (для Windows). Скачать на компьютер wget. Это бесплатная утилита для скачивания сайтов целиком. В UNIX-образных системах она установлена.
    Шаг 1. Запускаем сервер.
    Шаг 2. Переходим в терминал/командную строку и пишем команду:
    1
    wget -r -k -l 7 -p -E -nc <http://127.0.0.1:8080/>
    Copied!
    Шаг 3. Заходим в папку загрузки (по умолчанию – это папка пользователя) и находим папку с проектом.
    Шаг 4. Выгружаем папку целиком на публичный хостинг.

Способ №2. Деплой при помощи PythonAnywhere

Плюсы данного способа – полноценный деплой и простота настройки. Главный минус – использование стороннего ПО.
Есть много компаний, предоставляющих сервера в интернете. Мы воспользуемся услугами одной из них, с довольно простым процессом публикации: PythonAnywhere (https://www.pythonanywhere.com). PythonAnywhere бесплатен для маленьких приложений с небольшим числом посетителей, и этого будет для нас более чем достаточно.
Другим внешним сервисом, которым мы воспользуемся, будет GitHub (https://github.com) — сервис хостинга кода. Существуют и другие похожие сервисы, но практически у каждого программиста есть GitHub аккаунт.
В итоге код будет в трёх местах. На локальном компьютере мы будем заниматься разработкой и тестированием. Когда результат полностью устроит, мы загрузим свою программу на GitHub. А сайт будет на PythonAnywhere, и мы сможем обновлять его, просто загружая новую версию кода с GitHub.

Git

Git — это «система управления версиями», используемая множеством программистов. Эта программа отслеживает изменения, происходящие с файлами, чтобы впоследствии можно было восстановить состояние кода на нужный момент времени. Это немного похоже на функцию отслеживания изменений в Microsoft Word, но куда мощнее.

Установка Git

Windows

Вы можете загрузить Git с официального сайта git-scm.com. Можно нажимать "дальше, дальше, дальше" на всех этапах установки за исключением одного: на пятом шаге, который называется "Adjusting your PATH environment" (Настройка системной переменной Path), выберите "Use Git and optional Unix tools from the Windows Command Prompt" (Запуск Git и соответствующих Unix утилит через командную строку Windows, нижняя опция). Все остальные настройки можно оставить по умолчанию. Также неплохо будет выбрать опцию "Checkout Windows-style, commit Unix-style line endings".
После окончания установки не забудьте перезапустить командную строку или powershell.

OS X

Загрузи Git с официального сайта git-scm.com и просто следуй инструкциям по установке.

Debian и Ubuntu

1
command-line
2
$ sudo apt install git
Copied!

Fedora

1
command-line
2
$ sudo dnf install git
Copied!

openSUSE

1
command-line
2
$ sudo zypper install git
Copied!

Создаём Git-репозиторий

Git отслеживает изменения определенного набора файлов, который называется репозиторием. Давайте создадим такой для нашего проекта. Откройте консоль и запустите эти команды в папке saitMiigaika:
1
command-line
2
$ git init
3
Initialized empty Git repository in ~/saitMiigaika/.git/
4
$ git config --global user.name "Your Name"
5
$ git config --global user.email [email protected]
Copied!
Инициализировать git-репозиторий придется только один раз за проект.
Git будет отслеживать изменения всех файлов и каталогов в заданной директории, однако некоторые из них мы предпочли бы игнорировать. Для этого нам нужно создать файл .gitignore в корневом каталоге репозитория. Откройте редактор и создай новый файл со следующим содержанием:
1
.gitignore
2
*.pyc
3
*~
4
__pycache__
5
myvenv
6
db.sqlite3
7
/static
8
.DS_Store
Copied!
И сохраните его как .gitignore в корневом каталоге "saitMiigaika".
Используйте команду git status перед git add или в любой другой момент, когда вы не уверены, что изменения — хорошая идея. Это убережёт сайт от таких неприятных сюрпризов, как добавление неправильных файлов. Команда git status возвращает информацию обо всех ранее неотслеживаемых/изменённых/добавленных в git файлах, а также статус ветки и многое другое. Результат должен быть похож на:
1
command-line
2
$ git status
3
On branch master
4
5
No commits yet
6
7
Untracked files:
8
(use "git add <file>..." to include in what will be committed)
9
10
.gitignore
11
blog/
12
manage.py
13
mysite/
14
15
nothing added to commit but untracked files present (use "git add" to track)
Copied!
И, наконец, мы сохраним наши изменения. Переключаемся на консоль и набираем:
1
command-line
2
$ git add --all .
3
$ git commit -m "My Django MIIGAiK app, first commit"
4
[...]
5
13 files changed, 200 insertions(+)
6
create mode 100644 .gitignore
7
[...]
8
create mode 100644 mysite/wsgi.py
Copied!
Загружаем код в репозиторий GitHub
Зайдите на GitHub.com и создайте новую бесплатную учётную запись.
Затем создайте новый репозиторий и назови его "my-first-blog" (к примеру). Не выбирайте опцию "initialise with a README", не создавайте файл .gitignore (мы сделаем это локально сами) и оставьте лицензию None.
На следующем экране мы видим URL для клонирования репозитория. Выберите вариант "HTTPS" и скопируй ссылку:
Теперь нужно связать локальный репозиторий с репозиторием на GitHub.
Напечатайте у себя в консоли следующую команду (замените \ на имя, указанное при создании аккаунта на GitHub, но без угловых скобок):
1
command-line
2
$ git remote add origin https://github.com/<github-username>/my-first-blog.git
3
$ git push -u origin master
Copied!
Введите свое имя пользователя и пароль от аккаунта GitHub; мы должны увидеть примерно следующее:
1
command-line
2
Username for 'https://github.com': Username
3
Password for 'https://hjwp\@github.com':
4
Counting objects: 6, done.
5
Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done.
6
Total 3 (delta 0), reused 0 (delta 0)
7
To https://github.com/hjwp/my-first-blog.git
8
* [new branch] master -> master
9
Branch master set up to track remote branch master from origin.
Copied!
Наш код теперь на GitHub. Зайдите на сайт и проверьте.

Настройка блога на PythonAnywhere

Регистрация на PythonAnywhere

PythonAnywhere — это сервис по запуску кода на Python в облаке. Мы будем использовать его, чтобы разместить наш сайт «вживую» в интернете.
Создайте аккаунт уровня "Beginner" на PythonAnywhere. Он бесплатный.
Host, run, and code Python in the cloud: PythonAnywhere

Создание API токена для PythonAnywhere

Это нужно будет сделать только один раз. Когда вы зарегистрируетесь на PythonAnywhere, откроется панель управления (dashboard). На ней в правом верхнем углу будет ссылка на страницу «Account»:
Там выберите вкладку «API token» и нажмите кнопку, на которой написано «Create new API token» (создать новый API token).

Настройка сайта на PythonAnywhere

Вернитесь на главную страницу PythonAnywhere, кликнув логотип. Затем запустите Bash-консоль. Нажав на кнопку bash мы запускаем командную строку, которая находится на серверах PythonAnywhere. Эта командная строка аналогична тому, что есть на компьютере.
Чтобы опубликовать сайт на PythonAnywhere, нужно загрузить на PythonAnywhere код с Github и затем настроить PythonAnywhere так, чтобы он распознал код и запустил веб-приложение. Существуют способы сделать это «вручную», но для PythonAnywhere есть программа-помощник, которая сделает это за нас. Давайте её установим.
1
PythonAnywhere command-line
2
$ pip3.6 install --user pythonanywhere
Copied!
Когда мы это запустим, в консоли будет печататься лог установки. Он начнётся с чего-то вроде Collecting pythonanywhere, а последней будет строчка Successfully installed (...) pythonanywhere- (...).
Теперь запустим эту вспомогательную утилиту, которую только что установили. Она настроит приложение, скачав его код с GitHub. Напечатайте следующее в консоли PythonAnywhere:
1
PythonAnywhere command-line
2
$ pa_autoconfigure_django.py https://github.com/<github-username>/my-first-blog.git
Copied!
Утилита будет печатать в консоль, что она делает:
    Скачивает код с GitHub
    Создаёт виртуальное окружение на PythonAnywhere, такое же, как на компьютере
    Обновляет файл настроек с настройками деплоя
    Создаёт базу данных на PythonAnywhere, используя команду manage.py migrate
    Разбирается со статическими файлами
    Настраивает PythonAnywhere так, чтобы приложение было доступно в интернете
Все эти шаги автоматизированы на PythonAnywhere, но они совершенно такие же, какие надо было бы совершить с любым другим хостинговым сервисом.
Главное, на что нужно обратить внимание сейчас, — это то, что база данных на PythonAnywhere никак не связана с базой данных на компьютере. Поэтому там будут разные посты и разные аккаунты администраторов. Как следствие, для базы на PythonAnywhere необходимо создать аккаунт администратора так же, как мы это дели локально с помощью команды createsuperuser. На PythonAnywhere заранее активировано виртуальное окружение, так что всё, что нужно сделать — это запустить в консоли PythonAnhywhere команду:
1
PythonAnywhere command-line
2
(ola.pythonanywhere.com) $ python manage.py createsuperuser
Copied!
Введите параметры для своего пользователя-админа. Лучше всего использовать те же самые данные, что и на локальном компьютере, чтобы избежать путаницы.
Сейчас, если хотите, посмотрите на файлы на PythonAnywhere с помощью команды ls:
1
PythonAnywhere command-line
2
(ola.pythonanywhere.com) $ ls
3
blog db.sqlite3 manage.py mysite requirements.txt static
4
(ola.pythonanywhere.com) $ ls blog/
5
__init__.py __pycache__ admin.py apps.py migrations models.py tests.py views.py
Copied!

Вариант 3. Без автоматизации PythonAnywhere (не рекомендуется новичку)

Самый сложный, но при этом самый правильный метод настройки, так как нам не потребуется использовать стороннее ПО для деплоя, а это уменьшает число уязвимостей.
Необходимо купить выделенный VDS или VPS сервер. VDS выделяет место на сервере физически, VPS – программным методом.
Предположим, у Вас куплена свежая машина, мы первый раз к ней подключаемся. Используем мы Ubuntu.
Далее буду вводить команды списком, чтобы не запутаться в шагах.
    Если у вас уже прописан ключ к вашей машине, но он не совпадает, очищаете его
1
rm .ssh/known_hosts
Copied!
    Подключаетесь и вводите пароль от сервера.
1
ssh root\@5.45.120.175
Copied!
    Обновляете пароль рута, если он вас не устраивает
1
passwd root
Copied!
    Обновляем списки репозиториев.
1
apt-get update
Copied!
    Апгредим.
1
apt-get upgrade
Copied!
    Если присутствуют проблемы локали, исправляем их сразу.
1
perl -v
Copied!
    Смотрим, если ругается и есть предупреждения генерируем локаль.
1
locale-gen en_US en_US.UTF-8 ru_RU.UTF-8
Copied!
    Затем реконфигурируем локаль машины.
1
dpkg-reconfigure locales
Copied!
    Вновь проверяем на наличие ошибок
1
perl -v
Copied!
    Ура их нет! Двигаемся дальше. Устанавливаем Nginx.
1
apt-get install nginx
Copied!
    После установки запускаем nginx.
1
service nginx start
Copied!
    Смотрим статус:
1
service nginx status
Copied!
    Если все ок, и он запущен можете открыть страничку вашего сайта и вы увидите
    стартовую страницу nginx. Если же сервер не запустился, проверте, не запущен ли
    у вас apache
1
service apache2 status
Copied!
    Если он запущен стопайте его. Его необходимо полностью удалить.
1
service apache2 stop
Copied!
    Деинсталируем апач и все его конфиги такой вот не хитрой командой:
1
apt-get purge apache2 apache2-utils apache2.2-bin apache2-common
Copied!
    Если какие то пакеты, которые собираемся удалить отсутствуют, просто уберите
    их из команды. Далее:
1
apt-get autoremove
Copied!
    Наконец, надо проверить наличие конфигурационных файлов или мануалов,
    связанных с Apache2, но до сих пор не удаленных.
1
whereis apache2
Copied!
    Удаляете все эти директории вручную. Например, вот так:
1
rm -rf /etc/apache2
Copied!
    Если все удалено, аллилуя. Запускаем nginx. И смотрим статус:
1
service nginx start
2
service nginx status
Copied!
    Если все ок, заходите на вашу страничку и вы увидете стартовую страницу
    nginx. Идем дальше. Cоздайте пользователя для старта django-приложения. Создайте
    из-под него виртуальное окружение.
1
apt-get install python3-dev python3-setuptools
2
easy_install-3.4 virtualenv
3
adduser django
4
login django
5
cd /home/django
6
virtualenv venv
Copied!
    Теперь, переносим проект в эту папку.Устанавливаем git, nano если они не
    установлены.
1
apt-get install git nano
Copied!
    Создаем ключ ssh. Все поля оставляем пустыми.
1
ssh-keygen -t rsa -C "your_mail\@mail.com"
Copied!
    Переходим в директорию ключа, открываем необходимый нам публичный ключ.
    Советую с помощью утилиты sshfs подключиться к вашей машине через gui интерфейс.
    Вам будет необходимо указать адрес машины и папку, в которую поместите файлы
    машины. Например вот так.
1
sshfs [email protected]:/ /home/user/Develop/sites/my_site/
Copied!
    Затем копируете ключ.
1
/root/.ssh/id_rsa.pub
Copied!
    Копируем его в настройки пользователя git репозитория
    После того, как вы это сделаете, вы сможете спокойно клонировать по ssh репозиторий. Заходите под рутом.
1
su - root
2
cd /home/django/
3
git clone [email protected]:user/my_site.git
Copied!
    Симлинк /etc/nginx/sites-enabled/default можно удалить
    Логинимся под юзером django.
1
login django
Copied!
    Активируем виртуальное окружение.
1
source venv/bin/activate
Copied!
    Устанавливаем Django в наше виртуальное окружене:
1
pip install Django
Copied!
    Переходим в корневую папку проекта.
1
cd my_site
Copied!
    Один из хороших способов установить uWSGI:
1
pip install uwsgi
Copied!
    Проверка. Создаем файл test.py:
1
nano test.py
Copied!
    С таким содержимым:(Если не создается, создайте от рута)
1
def application(env, start_response):
2
start_response('200 OK', [('Content-Type','text/html')])
3
return [b"Hello World"]
Copied!
    Запускаем uWSGI:
1
uwsgi --http :8000 --wsgi-file test.py
Copied!
    Если все работает, нажимаем ctrl-c, завершая процесс и продолжаем дальше.
    Теперь конфигурируем наш сайт. Устанавливаем postgresql. Из под рута.
1
apt-get install libpq-dev postgresql postgresql-contrib
2
su - postgres
3
createdb my_site
4
createuser -P django
5
psql
6
postgres=# GRANT ALL PRIVILEGES ON DATABASE my_site TO django;
7
su - root
8
login django
9
source /home/django/venv/bin/activate
10
pip install psycopg2
Copied!
    Если необходимо перенести БД со старой на новую делается это так:
    Шаг 1. Выполняется со старыми настройками DATABASES в settings.py python manage.py dumpdata > datadump.json
    Шаг 2. Выполняется с новыми настройками DATABASES в settings.py python manage.py loaddata datadump.json
    После этого устанавливаем все библиотеки что есть в requirements.txt. Для этого заходим в папку my_site проектом и вводим следующую команду. Разумеется с помощью виртуального окружения.
1
pip install -r requirements.txt
Copied!
    Если не установилась какая-нибудь библиотека X устанавливайте более позднюю
    версию:
1
pip install X==2.9.0
Copied!
    В файле …/my_site/settings.py обязательно нужно указать настройки базы
    данных:
1
DATABASES = {
2
'default': {
3
'ENGINE': 'django.db.backends.postgresql_psycopg2',
4
'NAME': 'my_site',
5
'USER': 'django',
6
'PASSWORD': '1234567890',
7
'HOST': 'localhost',
8
'PORT': '',
9
}
10
}
Copied!
    В файле settings.py должен быть такой путь:
1
MEDIA_ROOT = "/home/django/my_site/media"
Copied!
    Делаем миграцию, если это необходимо:
1
python manage.py migrate
Copied!
    Создаем супер пользователя.
1
python manage.py createsuperuser
Copied!
    Запускаем сервер
1
python manage.py runserver 0.0.0.0:8080
Copied!
    Если ошибок не возникло, заходим и настраиваем сайт через панель администратора (если у вас новая свежая база данных без данных).
    После того, как вы сконфигурировали проект идем дальше. Собираем всю статику (Скорее всего это сработает только из под рута):
1
python manage.py collectstatic
Copied!
    Теперь, вы можете запустить my_site через uwsgi, и если это не сработало, значит вы где то совершили ошибку. Вполне вероятно, о ней сообщат логи uwsgi.
1
uwsgi --http :8000 --module my_site.wsgi
Copied!
    Теперь нам необходимо сконфигурировать nginx. Для начала, создайте файл в корне проекта my_site с названием uwsgi_params, с таким содержанием:
1
uwsgi_param QUERY_STRING $query_string;
2
uwsgi_param REQUEST_METHOD $request_method;
3
uwsgi_param CONTENT_TYPE $content_type;
4
uwsgi_param CONTENT_LENGTH $content_length;
5
uwsgi_param REQUEST_URI $request_uri;
6
uwsgi_param PATH_INFO $document_uri;
7
uwsgi_param DOCUMENT_ROOT $document_root;
8
uwsgi_param SERVER_PROTOCOL $server_protocol;
9
uwsgi_param REQUEST_SCHEME $scheme;
10
uwsgi_param HTTPS $https if_not_empty;
11
uwsgi_param REMOTE_ADDR $remote_addr;
12
uwsgi_param REMOTE_PORT $remote_port;
13
uwsgi_param SERVER_PORT $server_port;
14
uwsgi_param SERVER_NAME $server_name;
Copied!
    Вообще, лучше поместите этот файл в корень проекта, в папку с названием deployment, чтобы файлы проекта различались с файлами деплоя.
    Теперь в той же папке создайте файл my_site_nginx.conf
    Наполните его таким содержимым:
1
# the upstream component nginx needs to connect to
2
upstream django {
3
server unix:///home/django/my_site/uwsgi_nginx.sock; # for a file socket
4
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)
5
}
6
7
# configuration of the server
8
server {
9
# the port your site will be served on
10
listen 8000;
11
# the domain name it will serve for
12
server_name my_site.ru; # substitute your machine's IP address or FQDN
13
charset utf-8;
14
15
# max upload size
16
client_max_body_size 75M; # adjust to taste
17
18
# Django media
19
location /media {
20
alias /home/django/my_site/media; # your Django project's media files - amend as required
21
}
22
23
location /static {
24
alias /home/django/my_site/static; # your Django project's static files - amend as required
25
}
26
27
# Finally, send all non-media requests to the Django server.
28
location / {
29
uwsgi_pass django;
30
include /home/django/my_site/deployment/uwsgi_params; # the uwsgi_params file you installed
31
}
32
}
Copied!
    В папке /etc/nginx/sites-enabled создаем ссылку на файл mysite_nginx.conf, чтобы nginx увидел его.
1
sudo ln -s /home/django/rss_news/deployment/rss_news_nginx.conf /etc/nginx/sites-enabled
Copied!
    Перезапускаем nginx:
1
/etc/init.d/nginx restart
Copied!
    Помещаем файл с именем, например, media.png в папку /home/django/my_site/media.
    В браузере переходим по адресу yourserver.com:8000/media/media.png и, если видим наш файл, значит мы все сделали правильно.
    Пробуем запустить через сокет:
1
uwsgi --socket uwsgi_nginx.sock --wsgi-file test.py —-chmod-socket=666
Copied!
    nginx + uWSGI + Django. Запускаем: В браузере переходим на yourserver.com:8000/ и видим стартовую страницу Django.
1
uwsgi --socket uwsgi_nginx.sock --module my_site.wsgi --chmod-socket=666
Copied!
    Мы собрали всю цепочку, но настройка еще не закончена, идем дальше.
    Очень удобно все опции, с которыми мы запускаем uWSGI, указать в ini файле, а при запуске передавать только путь к этому файлу. Создаем файл my_site_uwsgi.ini в нашей папке deployment. Указываем в нем следующее содержимое:
1
#mysite_uwsgi.ini
2
[uwsgi]
3
4
# Настройки, связанные с Django
5
# Корневая папка проекта (полный путь)
6
chdir = /home/django/my_site
7
# Django wsgi файл
8
module = my_site.wsgi
9
# полный путь к виртуальному окружению
10
home = /home/django/venv
11
# общие настройки
12
# master
13
master = true
14
# максимальное количество процессов
15
processes = 10
16
# полный путь к файлу сокета
17
socket = /home/django/my_site/uwsgi_nginx.sock
18
# права доступа к файлу сокета
19
chmod-socket = 666
20
# очищать окружение от служебных файлов uwsgi по завершению
21
vacuum = true
22
env = DEBUG_MODE=False
23
daemonize=/var/log/uwsgi/my_site.log
Copied!
    Запускаем этот файл:
1
uwsgi --ini my_site_uwsgi.ini
Copied!
    Проверяем. Все работает? Дальше. До сих пор uWSGI был установлен в виртуальном окружении. Чтобы была возможность автоматически запускать uWSGI при старте операционной системы, мы установим его глобально. Деактивируем виртуальное окружение:
1
deactivate
Copied!
    Устанавливаем pip и pip3 глобально.
1
apt-get install python-pip python3-pip
Copied!
    Затем, устанавливаем uwsgi глобально.
1
pip3 install uwsgi
Copied!
    Проверяем запуск:
1
uwsgi --ini my_site_uwsgi.ini
Copied!
    Если сервер обслуживает несколько проектов, каждый из которых использует uWSGI, то нужно использовать режим Emperor. В этом режиме uWSGI просматривает папку с конфигурационными файлами и для каждого файла запускает отдельный процесс (вассал).
    Если один из конфигурационных файлов будет изменен, uWSGI перезапустит соответствующего вассала.
    Создаем папку для конфигурационных файлов:
1
sudo mkdir /etc/uwsgi
2
3
sudo mkdir /etc/uwsgi/vassals
Copied!
    Создаем в ней ссылку на my_site_uwsgi.ini:
1
sudo ln -s /home/django/my_site/deployment/my_site_uwsgi.ini /etc/uwsgi/vassals/
Copied!
    Запускаем uWSGI в режиме Emperor, потом отключаем если все работает (Возможно вам придется перезапустить вашу БД такой командой sudo service postgresql restart):
1
uwsgi --emperor "/home/django/my_site/deployment/my_site_uwsgi.ini"
Copied!
    Устанавливаем супервизор
1
apt-get install supervisor
Copied!
    Создаем файл конфигурации в папке etc/supervisor/conf.d/my_site.conf:
1
echo_supervisord_conf > /etc/supervisord.conf
Copied!
    В Этом файле указываем следующий текст:
1
[program:my_site]
2
command=uwsgi --emperor "/home/django/my_site/deployment/my_site_uwsgi.ini"
3
stdout_logfile=/home/django/my_site/deployment/uwsgi.log
4
stderr_logfile=/home/django/my_site/deployment/uwsgi_err.log
5
autostart=true
6
autorestart=true
Copied!
    Индексируем этот файл: (Если появляются какие то ошибки, перезапускаем supervisor (service supervisor restart)) Так же, смотрим логи.
1
supervisorctl reread
2
supervisorctl update
Copied!
    Все должно работать. Управлять supervisor можно как сервисом:
1
service supervisor start|stop|status ...
Copied!
    Если происходят какие то изменения в коде, выполняем эту команду в папке deployment:
1
service supervisor stop
2
touch my_site_uwsgi.ini
3
service supervisor start
Copied!
    Команда supervisorctl покажет запущенные приложения императором.
    Если необходимо запустить проект в режиме дебага, меняем значение DEBUG_MODE=False на DEBUG_MODE=True в файле конфигурации uwsgi.
    Готово!
Last modified 10mo ago