Aplicaciones de una sola p谩gina con Vue.js y Flask: implementaci贸n

    Implementaci贸n en un servidor privado virtual

    Bienvenido a la s茅ptima y 煤ltima entrega de esta serie de tutoriales de varias partes sobre desarrollo web full-stack usando Vue.js y Flask. En esta publicaci贸n, demostrar茅 c贸mo implementar la aplicaci贸n construida a lo largo de esta serie.

    El c贸digo para esta publicaci贸n se puede encontrar en mi cuenta de GitHub en la rama S茅ptima Publicaci贸n.

    Contenido de la serie

    • Seup y familiarizaci贸n con VueJS
    • Navegando por el enrutador Vue
    • Gesti贸n de estado con Vuex
    • API RESTful con Flask
    • Integraci贸n AJAX con API REST
    • Autenticaci贸n JWT
    • Implementaci贸n en un servidor privado virtual (usted est谩 aqu铆)

    Resumen de las tecnolog铆as

    Este tutorial cubrir谩 varias tecnolog铆as necesarias para implementar una API REST de Flask de varios niveles distribuida y una aplicaci贸n Vue.js SPA. A continuaci贸n, he enumerado las tecnolog铆as y sus usos:

    • Ubuntu LTS 16.04: servidor host para ejecutar varias aplicaciones y servidores
    • uWSGI: servidor contenedor Webserver Gateway Interface (WSGI) para ejecutar aplicaciones Python (Flask en este caso)
    • Nginx: servidor web HTTP sin bloqueo de alto rendimiento capaz de realizar proxy inverso a uWSGI
    • Node.js / NPM: entorno Javascript para compilar la aplicaci贸n Vue.js SPA

    Preparar el c贸digo para la implementaci贸n

    Hay un par de cambios que deben realizarse en el c贸digo para que sea m谩s f谩cil de mantener una vez que la aplicaci贸n se haya implementado en mi entorno de producci贸n.

    Por ejemplo, en api / index.js del survey-spa Aplicaci贸n Vue.js He codificado una variable llamada API_URL para apuntar al servidor de desarrollo http://127.0.0.1:5000/api. Al hacer esto, tendr茅 que recordar cambiar esto a la direcci贸n IP del servidor de producci贸n cada vez que necesite implementar.

    La experiencia me ha ense帽ado que siempre habr谩 cambios en la aplicaci贸n que requieran futuras implementaciones donde es probable que me olvide de actualizar esta direcci贸n IP. Un mejor enfoque es eliminar el riesgo de que me olvide de actualizar esto y, en su lugar, utilice configuraciones en el proceso de compilaci贸n para manejar esto por m铆, lo que resulta en menos de lo que tengo que recordar (es decir, se necesitan menos pasos) durante la implementaci贸n. Esto reduce significativamente el riesgo de una implementaci贸n fallida en futuras actualizaciones.

    Lo logro movi茅ndome al directorio survey-spa / config y modificando los archivos dev.env.js y prod.env.js definiendo una variable llamada API_URL a los que se les asigna un valor de http://localhost:5000/api para dev y http://${process.env.BASE_URL}/api para prod como se muestra a continuaci贸n:

    // 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`)
    }
    

    Nota: el valor de process.env.BASE_URL es una variable de entorno que agregar茅 al usuario del servidor de Ubuntu .bash_profile y la establecer茅 igual a la direcci贸n IP del servidor.

    Luego, en api / index.js modifico la l铆nea const API_URL = 'http://127.0.0.1:5000/api' y ponerlo igual a process.env.API_URL.

    A continuaci贸n, en la aplicaci贸n Flask, necesito agregar un nuevo m贸dulo llamado wsgi.py para que sirva como punto de entrada a la API REST de Flask. El m贸dulo wsgi.py se parece bastante al m贸dulo appserver.py, excepto que no tiene ninguna llamada al run(...) m茅todo del objeto de la aplicaci贸n. Esto se debe a que el objeto de la aplicaci贸n servir谩 como un invocable para que el servidor de contenedores uwsgi se ejecute utilizando su protocolo binario r谩pido en lugar del servidor de desarrollo normal que se crea cuando app.run(...) se llama.

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

    Con esto terminado, puedo enviar mis cambios al control de versiones y saltar a mi servidor de producci贸n para desplegar el proyecto y configurar los programas que usar茅 para ejecutar la aplicaci贸n en el servidor de producci贸n.

    Preparando el servidor Ubuntu

    A continuaci贸n, entrar茅 en mi servidor privado virtual Ubuntu de producci贸n, que podr铆a estar alojado en uno de los muchos servicios en la nube, como AWS, DigitalOcean, Linode, etc., y comenzar茅 a instalar todas las ventajas que enumer茅 en la Descripci贸n general de las tecnolog铆as. secci贸n.

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

    Con esas instalaciones fuera del camino, ahora puedo crear un usuario llamado “encuesta” para ejecutar la aplicaci贸n y albergar el c贸digo.

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

    Ahora deber铆a estar en el directorio de inicio del usuario de “encuesta” en / home / survey.

    Con la encuesta creada por el usuario, puedo actualizar el archivo .bash_profile para que contenga la direcci贸n IP de mi servidor de producci贸n agregando esta l铆nea al final del archivo. Tenga en cuenta que 123.45.67.89 representa una direcci贸n IP falsa de mi servidor. Reempl谩celo con su verdadera direcci贸n IP si lo est谩 siguiendo.

    export BASE_URL=123.45.67.89
    

    A continuaci贸n, quiero decirle al firewall (ufw) que OpenSSH es aceptable y habil铆telo.

    $ sudo ufw allow OpenSSH
    $ sudo ufw enable
    

    Una vez hecho esto, ahora clonar茅 el repositorio en el servidor para poder construirlo e implementarlo.

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

    Ahora ingresar茅 en flask-vuejs-survey / frontend / survey-spa e instalar茅 las dependencias de frontend y construir茅 la aplicaci贸n de producci贸n.

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

    Esto crea un nuevo directorio llamado “dist”, que contendr谩 una p谩gina index.html y un directorio llamado “est谩tico” que contiene todos los archivos CSS y JavaScript compilados. Estos son los que tendr茅 en el servidor Nginx para constituir la aplicaci贸n de front-end del SPA.

    A continuaci贸n, crear茅 un entorno virtual en el directorio / home / survey para que un int茅rprete de Python3 aislado ejecute la aplicaci贸n Python. Una vez instalado, lo activo y me muevo al directorio del proyecto backend para instalar sus paquetes de dependencia especificados en el archivo requirements.txt.

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

    Ahora puedo inicializar la base de datos sqlite y ejecutar las migraciones para crear las diversas tablas de base de datos requeridas por la API REST.

    (venv) $ python manage.py db upgrade
    

    En este punto, me gustar铆a encender el servidor de desarrollo Flask para asegurarme de que todo funciona como se esperaba. Antes de hacerlo, necesito decirle al ufw servicio para permitir el tr谩fico en el puerto 5000.

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

    En un navegador ahora puedo ir a http://123.45.67.89:5000/api/surveys/ y deber铆a ver una simple respuesta JSON de [] porque a煤n no hay encuestas en esta base de datos, pero esto indica que se realiz贸 una solicitud con 茅xito. Adem谩s, en el terminal conectado al servidor deber铆a haber un mensaje registrado para la solicitud GET emitida desde mi navegador.

    Tecleo Ctrl + C en la terminal para matar el servidor de desarrollo de Flask y paso a configurar uwsgi para controlar la ejecuci贸n de mi API REST de Flask. Si se est谩 preguntando de d贸nde vino uwsgi, se especifica como un requisito en el archivo requirements.txt que instal茅 anteriormente.

    Configuraci贸n del servidor de contenedores uWSGI

    De manera similar a lo que acabo de hacer con el servidor de desarrollo Flask, ahora probar茅 que el servidor uWSGI puede servir la aplicaci贸n de la siguiente manera.

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

    Nuevamente, ir a mi navegador y actualizar la misma solicitud que hice anteriormente deber铆a devolver una respuesta de matriz JSON vac铆a. Una vez satisfecho con mi progreso, puedo volver a presionar Ctrl + C en la terminal y seguir adelante.

    Hay dos pasos m谩s que me gustar铆a seguir para completar la configuraci贸n del servidor de contenedores uWSGI. Un paso es crear un archivo de configuraci贸n que leer谩 uWSGI en el que reemplazar谩 muchos de los indicadores y argumentos de la l铆nea de comando que utilic茅 anteriormente. El segundo paso es crear un archivo de servicio systemd para administrar el servidor contenedor uWSGI como un servicio como muchos de los otros que ya se ejecutan en el servidor Ubuntu.

    En el directorio de backend, hago un archivo llamado surveyyapi.ini y lo lleno con lo siguiente:

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

    Este archivo de configuraci贸n le permite a uWSGI saber que el invocable es el objeto de la aplicaci贸n dentro del m贸dulo wsgi.py. Tambi茅n le dice que genere y use cuatro procesos para manejar solicitudes de aplicaciones comunicadas a trav茅s de un archivo de socket llamado surveyyapi.sock que tiene un permiso lo suficientemente flexible como para permitir que el servidor web Nginx lea y escriba desde 茅l. los vacuum y die-on-term Los ajustes son para asegurar una limpieza adecuada.

    Para el archivo de servicio systemd, necesito crear un archivo llamado surveyapi.service en el directorio / etc / systemd / system y agregue algunos descriptores m谩s los comandos de acceso, escritura y ejecuci贸n de la siguiente manera:

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

    Luego, compl茅telo con lo siguiente:

    [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
    

    Ahora puedo iniciar el servicio y verificar su estado y asegurarme de que el directorio de backend ahora contenga surveyyapi.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
    

    隆Excelente! Lo 煤ltimo que debo hacer es habilitar el inicio autom谩tico cada vez que se inicia el sistema, asegur谩ndome de que la aplicaci贸n est茅 siempre activa.

    (venv) $ sudo systemctl enable surveyapi
    

    Configuraci贸n de Nginx

    Utilizar茅 Nginx para servir contenido est谩tico como HTML, CSS y JavaScript, as铆 como para revertir las llamadas API REST del proxy a la aplicaci贸n Flask / uWSGI. Para configurar nginx para lograr estas cosas, necesitar茅 crear un archivo de configuraci贸n que defina c贸mo administrar estas diversas solicitudes.

    En / etc / nginx / sites-available, crear茅 un archivo llamado encuesta que contendr谩 lo siguiente:

    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;
      }
    }
    

    Este archivo crea una nueva configuraci贸n de bloque de servidor que dice que escuche la direcci贸n IP 123.45.67.89 en el puerto HTTP est谩ndar de 80. Luego dice que busque cualquier ruta URI que comience con / api y un proxy inverso al servidor Flask / uWSGI REST API utilizando el archivo de socket definido previamente. Por 煤ltimo, la configuraci贸n dice que capture todo lo dem谩s en / y sirva el archivo index.html en el directorio dist creado cuando constru铆 la aplicaci贸n SPA de front-end Vue.js antes.

    Con este archivo de configuraci贸n creado, necesito informarle a Nginx que es un sitio disponible creando un enlace simb贸lico al directorio / etc / nginx / sites-enabled como sigue:

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

    Para permitir el tr谩fico a trav茅s del puerto HTTP y enlazar con Nginx, emitir茅 la siguiente actualizaci贸n para ufw as铆 como cerrar el puerto 5000 previamente abierto.

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

    Siguiendo este comando, tendr茅 que reiniciar el servicio Nginx para que las actualizaciones surtan efecto.

    $ sudo systemctl restart nginx
    

    Ahora puedo volver a mi navegador y visitar http://123.454.67.89 y se me presenta la aplicaci贸n de encuesta que he mostrado en art铆culos anteriores.

    Conclusi贸n

    Bueno, esta es la publicaci贸n final de esta serie de tutoriales de varias partes sobre c贸mo utilizar Flask y Vue.js para construir una aplicaci贸n SPA habilitada para REST API. He intentado cubrir la mayor铆a de los temas importantes que son comunes a muchos casos de uso de aplicaciones web, asumiendo muy poco conocimiento previo de las tecnolog铆as Flask y Vue.js utilizadas.

    Les agradezco por seguir esta serie y, por favor, no tengan verg眉enza de comentar o criticar a continuaci贸n.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *