Одностраничные приложения с Vue.js и Flask: развертывание

Развертывание на виртуальном частном сервере Добро пожаловать в седьмую и последнюю часть этой серии руководств, состоящих из нескольких частей, по полнофункциональной веб-разработке с использованием Vue.js и Flask. В этом посте я продемонстрирую, как развернуть приложение, созданное в этой серии. Код этого сообщения можно найти в моей учетной записи GitHub в ветке SeventhPost [https://github.com/amcquistan/flask-vuejs-survey/tree/SeventhPost]. Содержание серии 1. Поиск и знакомство с VueJS [/ single-page-apps

Развертывание на виртуальном частном сервере

Добро пожаловать в седьмую и последнюю часть этой серии руководств, состоящих из нескольких частей, по полнофункциональной веб-разработке с использованием Vue.js и Flask. В этом посте я продемонстрирую, как развернуть приложение, созданное в этой серии.

Код этого поста можно найти в моей учетной записи GitHub в ветке SeventhPost .

Содержание серии

  1. Seup и знакомство с VueJS
  2. Навигация по Vue Router
  3. Управление состоянием с Vuex
  4. RESTful API с Flask
  5. Интеграция AJAX с REST API
  6. JWT аутентификация
  7. Развертывание на виртуальном частном сервере (вы здесь)

Обзор технологий

В этом руководстве будут рассмотрены несколько технологий, необходимых для развертывания распределенного многоуровневого REST API Flask и приложения Vue.js SPA. Ниже я перечислил технологии и их использование:

  • Ubuntu LTS 16.04: хост-сервер для запуска различных приложений и серверов
  • uWSGI: сервер-контейнер интерфейса шлюза веб-сервера (WSGI) для выполнения приложений Python (в данном случае Flask)
  • Nginx: высокопроизводительный неблокирующий веб-сервер HTTP, способный выполнять обратное проксирование в uWSGI.
  • Node.js / NPM: среда Javascript для создания приложения Vue.js SPA

Подготовка кода к развертыванию

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

Например, в api / index.js survey-spa Vue.js я жестко запрограммировал переменную с именем API_URL чтобы она указывала на сервер разработки http://127.0.0.1:5000/api . При этом мне нужно будет не забыть менять это на IP-адрес производственного сервера каждый раз, когда мне нужно будет развернуть.

Опыт научил меня, что всегда будут изменения в приложении, требующие будущих развертываний, когда я, вероятно, забуду обновить этот IP-адрес. Лучшим подходом является устранение риска того, что я забуду обновить это, и вместо этого использую конфигурации в процессе сборки, чтобы справиться с этим для меня, что приведет к тому, что мне нужно помнить меньше (т. Это значительно снижает риск неудачного развертывания будущих обновлений.

Я добиваюсь этого, перейдя в каталог survey-spa / config и изменив файлы dev.env.js и prod.env.js, определив переменную с именем API_URL которой присвоено значение http://localhost:5000/api для dev и http://${process.env.BASE_URL}/api для prod, как показано ниже:

 // dev.env.js 
 
 'use strict' 
 const merge = require('webpack-merge') 
 const prodEnv = require('./prod.env') 
 
 module.exports = merge(prodEnv, { 
 NODE_ENV: '"development"', 
 API_URL: JSON.stringify(`http://localhost:5000/api`) 
 }) 

 // prod.env.js 
 'use strict' 
 module.exports = { 
 NODE_ENV: '"production"', 
 API_URL: JSON.stringify(`http://${process.env.BASE_URL}/api`) 
 } 

Примечание : значение process.env.BASE_URL - это переменная среды, которую я добавлю к пользователю сервера Ubuntu .bash_profile и установлю его равным IP-адресу сервера.

Затем в api / index.js я изменяю строку const API_URL = 'http://127.0.0.1:5000/api' и устанавливаю ее равной process.env.API_URL .

Затем в приложении Flask мне нужно добавить новый модуль с именем wsgi.py, который будет служить точкой входа в REST API Flask. Модуль wsgi.py выглядит очень похоже на модуль appserver.py за исключением того, что он не имеет никаких вызовов run(...) объекта приложения. Это связано с тем, что объект приложения будет служить вызываемым сервером контейнера uwsgi для выполнения с использованием его быстрого двоичного протокола, а не обычного сервера разработки, который создается при app.run(...) .

 # backend/wsgi.py 
 
 from surveyapi.application import create_app 
 app = create_app() 

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

Подготовка сервера Ubuntu

Затем я перейду к своему производственному виртуальному частному серверу Ubuntu, который может быть размещен в одном из множества облачных сервисов, таких как AWS, DigitalOcean, Linode и т. Д., И начну установку всех полезных функций, перечисленных в Обзоре технологий. раздел.

 $ apt-get update 
 $ apt-get install python3-pip python3-dev python3-venv nginx nodejs npm 

После этих установок я теперь могу создать пользователя с именем «survey» для выполнения приложения и размещения кода.

 $ adduser survey 
 $ usermod -aG sudo survey 
 $ su survey 
 $ cd 

Теперь я должен быть в домашнем каталоге пользователя "Survey" в / home / survey.

Создав пользователя опроса, я могу обновить файл .bash_profile, чтобы он содержал IP-адрес моего рабочего сервера, добавив эту строку в конец файла. Обратите внимание, что 123.45.67.89 представляет собой поддельный IP-адрес моего сервера. Замените его своим истинным IP-адресом, если вы следите за ним.

 export BASE_URL=123.45.67.89 

Затем я хочу сообщить брандмауэру ( ufw ), что OpenSSH приемлем, и включить его.

 $ sudo ufw allow OpenSSH 
 $ sudo ufw enable 

После этого я клонирую репозиторий на сервер, чтобы я мог его собрать и развернуть.

 $ git clone https://github.com/amcquistan/flask-vuejs-survey.git 

Теперь я перейду в flask-vuejs-survey / frontend / survey-spa и установлю зависимости внешнего интерфейса, а также создам производственное приложение.

 $ cd flask-vuejs-survey/frontend/survey-spa 
 $ npm install 
 $ npm run build 

Это создает новый каталог с именем «dist», который будет содержать страницу index.html и каталог с именем «static», содержащий все скомпилированные файлы CSS и JavaScript. Это то, что у меня будет сервер Nginx, чтобы составить интерфейсное приложение SPA.

Далее я создам виртуальную среду в каталоге / home / survey для изолированного интерпретатора Python3 для запуска приложения Python. После установки я активирую его и перехожу в каталог внутреннего проекта, чтобы установить его пакеты зависимостей, указанные в файле requirements.txt.

 $ python3 -m venv venv 
 $ source venv/bin/activate 
 (venv) $ cd flask-vuejs-survey/backend 
 (venv) $ pip install -r requirements.txt 

Теперь я могу инициализировать базу данных sqlite и запустить миграции для создания различных таблиц базы данных, необходимых для REST API.

 (venv) $ python manage.py db upgrade 

На этом этапе я хотел бы запустить сервер разработки Flask, чтобы убедиться, что все работает должным образом. Перед тем, как сделать это, мне нужно сообщить ufw чтобы она разрешила трафик через порт 5000.

 (venv) $ sudo ufw allow 5000 
 (venv) $ python appserver.py 

Теперь в браузере я могу перейти на http://123.45.67.89:5000/api/surveys/ и я должен увидеть простой ответ JSON [] потому что в этой базе данных еще нет опросов, но это означает, что успешный запрос был сделан. Кроме того, в терминале, подключенном к серверу, должно быть зарегистрированное сообщение для запроса GET, отправленного из моего браузера.

Я нажимаю Ctrl + C в терминале, чтобы убить сервер Flask dev, и перехожу к настройке uwsgi для управления выполнением моего Flask REST API. Если вам интересно, откуда взялся uwsgi, он указан как требование в файле requirements.txt, который я установил ранее.

Настройка сервера контейнера uWSGI

Подобно тому, что я только что сделал с сервером разработки Flask, теперь я проверю, может ли сервер uWSGI обслуживать приложение следующим образом.

 (venv) $ uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app 

Опять же, переход в свой браузер и обновление того же запроса, который я сделал ранее, должен вернуть пустой ответ массива JSON. Как только я доволен своим прогрессом, я могу снова нажать Ctrl + C в терминале и двигаться дальше.

Есть еще два шага, которые я хотел бы сделать, чтобы завершить настройку сервера контейнера uWSGI. Один шаг - создать файл конфигурации, который будет читать uWSGI, который заменит многие из тех флагов и аргументов командной строки, которые я использовал выше. Второй шаг - создать служебный файл systemd для управления сервером контейнера uWSGI как службой, как и многие другие, уже запущенные на сервере Ubuntu.

В каталоге backend я создаю файл с именем surveyapi.ini и заполняю его следующим:

 [uwsgi] 
 module = wsgi:app 
 
 master = true 
 processes = 4 
 
 socket = myproject.sock 
 chmod-socket = 660 
 vacuum = true 
 
 die-on-term = true 

Этот файл конфигурации позволяет uWSGI знать, что вызываемый объект - это объект приложения внутри модуля wsgi.py. Он также сообщает ему создать и использовать четыре процесса для обработки запросов приложений, передаваемых через файл сокета под названием Surveyapi.sock, который имеет достаточно свободные права, позволяющие веб-серверу Nginx читать и писать из него. Настройки vacuum и die-on-term службы должны обеспечивать надлежащую очистку.

Для служебного файла systemd мне нужно создать файл с именем surveyapi.service в каталоге / etc / systemd / system и добавить несколько дескрипторов, а также команды доступа, записи и выполнения, например:

 (venv) $ sudo nano /etc/systemd/system/surveyapi.service 

Затем заполните его следующим:

 [Unit] 
 Description=uWSGI Python container server 
 After=network.target 
 
 [Service] 
 User=survey 
 Group=www-data 
 WorkingDirectory=/home/survey/flask-vuejs-survey/backend 
 Environment="PATH=/home/survey/venv/bin" 
 ExecStart=/home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 
 [Install] 
 WantedBy=multi-user.target 

Теперь я могу запустить службу и проверить ее статус, а также убедиться, что в внутреннем каталоге теперь есть surveyapi.sock.

 (venv) $ sudo systemctl start surveyapi 
 (venv) $ sudo systemctl status surveyapi 
 Loaded: loaded (/etc/systemd/system/surveyapi.service; disabled; vendor preset: enabled) 
 Active: active (running) since Mon 2018-04-23 19:23:01 UTC; 2min 28s ago 
 Main PID: 11221 (uwsgi) 
 Tasks: 6 
 Memory: 28.1M 
 CPU: 384ms 
 CGroup: /system.slice/surveyapi.service 
 ├─11221 /home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 ├─11226 /home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 ├─11227 /home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 ├─11228 /home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 ├─11229 /home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 └─11230 /home/survey/venv/bin/uwsgi --ini surveyapi.ini 
 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: mapped 437520 bytes (427 KB) for 5 cores 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: *** Operational MODE: preforking *** 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x8b4c30 pid: 112 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: *** uWSGI is running in multiple interpreter mode *** 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: spawned uWSGI master process (pid: 11221) 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: spawned uWSGI worker 1 (pid: 11226, cores: 1) 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: spawned uWSGI worker 2 (pid: 11227, cores: 1) 
 Apr 23 19:23:01 ubuntu-s-1vcpu-2gb-sfo2-01 uwsgi[11221]: spawned uWSGI worker 3 (pid: 11228, cores: 1) 
 lines 1-23 
 (venv) $ ls -l /home/survey/flask-vuejs-survey/backend 
 -rw-rw-r-- 1 survey survey 201 Apr 23 18:18 appserver.py 
 -rw-rw-r-- 1 survey survey 745 Apr 23 17:55 manage.py 
 drwxrwxr-x 4 survey survey 4096 Apr 23 18:06 migrations 
 drwxrwxr-x 2 survey survey 4096 Apr 23 18:52 __pycache__ 
 -rw-rw-r-- 1 survey survey 397 Apr 23 18:46 requirements.txt 
 drwxrwxr-x 3 survey survey 4096 Apr 23 18:06 surveyapi 
 -rw-rw-r-- 1 survey survey 133 Apr 23 19:04 surveyapi.ini 
 srw-rw---- 1 survey www-data 0 Apr 23 19:23 surveyapi.sock 
 -rw-r--r-- 1 survey survey 10240 Apr 23 18:19 survey.db 
 -rw-rw-r-- 1 survey survey 84 Apr 23 18:42 wsgi.py 

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

 (venv) $ sudo systemctl enable surveyapi 

Настройка Nginx

Я буду использовать Nginx для обслуживания статического контента, такого как HTML, CSS и JavaScript, а также для обратных вызовов REST API прокси для приложения Flask / uWSGI. Чтобы настроить nginx для выполнения этих задач, мне нужно будет создать файл конфигурации, который определяет, как управлять этими различными запросами.

В / etc / nginx / sites-available я создам файл под названием survey, который будет содержать следующее:

 server { 
 listen 80; 
 server_name 123.45.67.89; 
 
 location /api { 
 include uwsgi_params; 
 uwsgi_pass unix:/home/survey/flask-vuejs-survey/backend/surveyapi.sock; 
 } 
 
 location / { 
 root /home/survey/flask-vuejs-survey/frontend/survey-spa/dist; 
 try_files $uri $uri/ /index.html; 
 } 
 } 

Этот файл создает новую конфигурацию серверного блока, в которой говорится, что нужно прослушивать IP-адрес 123.45.67.89 на стандартном HTTP-порту 80. Затем он говорит, что нужно искать любые пути URI, начинающиеся с / api, и обратный прокси-сервер, ведущий к серверу Flask / uWSGI REST API. используя ранее определенный файл сокета. Наконец, конфигурация говорит, что нужно поймать все остальное в / и обслуживать файл index.html в каталоге dist, созданном, когда я ранее создавал интерфейсное приложение SPA Vue.js.

Создав этот файл конфигурации, мне нужно сообщить Nginx, что это доступный сайт, создав символическую ссылку на каталог / etc / nginx / sites-enabled, например:

 $ sudo ln -s /etc/nginx/sites-available/survey /etc/nginx/sites-enabled 

Чтобы разрешить трафик через порт HTTP и привязать к Nginx, я ufw а также закрою ранее открытый порт 5000.

 $ sudo ufw delete allow 5000 
 $ sudo ufw allow 'Nginx Full' 

Следуя этой команде, мне нужно будет перезапустить службу Nginx, чтобы обновления вступили в силу.

 $ sudo systemctl restart nginx 

Теперь я могу снова зайти в свой браузер и посетить http://123.454.67.89 и мне будет представлено приложение для опроса, которое я показал в предыдущих статьях.

Заключение

Что ж, это заключительный пост в этой серии руководств, состоящих из нескольких частей, о том, как использовать Flask и Vue.js для создания приложения SPA с поддержкой REST API. Я попытался охватить большинство важных тем, которые являются общими для многих случаев использования веб-приложений, предполагая очень мало предварительных знаний об используемых технологиях Flask и Vue.js.

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

comments powered by Disqus