Preparación de un servidor para publicar una aplicación web en Python

¡Buen día, Habrovsk!

Había tiempo libre, y había un deseo de hacer una pequeña aplicación web. Existe una idea (para recibir datos de un sensor meteorológico, almacenar en la base de datos y luego hacer algo interesante), un servidor gratuito en centos también. Los tutoriales sobre la configuración también parecen ser los mismos ... Pero al momento de escribir, no se encontró ninguno que funcionara completamente . Si también desea implementar la aplicación en un servidor CentOS 7.4 usando python3. * Bundle, uwsgi y nginx, bienvenido a cat.

Entonces, qué debería ser y qué no se cubrirá en este artículo:

  1. Un servidor físico o virtual que ejecuta CentOS 7.4 (el rendimiento no está garantizado para otros sistemas operativos y versiones).
  2. Acceso al servidor con privilegios de superusuario * si el servidor es virtual, entonces se supone que existe la capacidad y la capacidad de conectarse a él a través de SSH).

Después de conectarse como usuario root, el primer paso es crear un nuevo usuario con derechos de administrador (esto no es necesario, pero al menos es un buen tono):

adduser developer
passwd developer

Aquí deberá ingresar y confirmar la contraseña de usuario

usermod -aG wheel developer

Agregar usuario al grupo de administradores locales

su - developer

Cambie al usuario recién creado.

Ahora prepara el medio ambiente:

sudo yum install -y epel-release
sudo yum install -y python3 python3-pip python3-devel nginx gcc
sudo yum update -y python36 python2
sudo yum groupinstall -y "Development Tools" "Development Libraries"
sudo yum install -y python3-devel python36-virtualenv

Me gustaría llamar la atención sobre la penúltima línea: las "Herramientas de desarrollo" y las "Bibliotecas de desarrollo" son necesarias para el lanzamiento correcto del entorno virtual. Usamos la bandera para que el equipo cumpla sin pedir confirmación.

Ahora puede comenzar a crear el directorio de trabajo:

sudo mkdir /opt/myproject && cd /opt/myproject
sudo chown -R developer /opt/
python3 -m venv myprojectenv
source myprojectenv/bin/activate

pip3 install --upgrade pip
pip3 install uwsgi flask

Ahora prepararemos el punto de entrada para la aplicación web:

vi /opt/myproject/wsgi.py(en adelante usaré el editor vi, sin embargo, esto es cuestión de gustos)

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return ["<h1 style='color:blue'>Testing Success!</h1>"]

Este código después del lanzamiento nos permitirá asegurarnos de que todos los pasos dados anteriormente fueron exitosos. Para probar, ejecute el servicio:

uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi

Con una conexión física ljcnegt o rdp, el resultado se puede verificar en un navegador a 0.0.0.0:8080. Con una conexión SSH, abra una nueva sesión y pruebe con curl:

curl -v 0.0.0.0:8080

El indicador -v le permite ver la salida completa.

Una vez completada la prueba, debe finalizar el servicio presionando CTRL + C (de lo contrario, debe buscar el proceso y matarlo con kill. También es una salida, pero definitivamente menos conveniente).

Ahora puedes hacer la aplicación web principal:

vi /opt/myproject/myproject.py

from flask import Flask
application = Flask(__name__)

@application.route("/")
def hello():
   return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
   application.run(host='0.0.0.0')

El proceso de prueba es bastante similar al anterior: iniciamos la aplicación usando el comando python3 /opt/myproject/myproject.pyy verificamos. El resultado debería ser el mismo.

Ahora edite el punto de entrada para que cuando se llame, se inicie nuestra aplicación:

vi /opt/myproject/wsgi.py

from myproject import application

if __name__ == "__main__":
   application.run()

Ahora lo más difícil e interesante. Es hora de hacer un servicio con esta aplicación que funcionará automáticamente y en segundo plano.

Primero, prepare el archivo ini para uwsgi:

vi /opt/myproject/myproject.ini

[uwsgi]
wsgi-file = myproject/wsgi.py

master = true
processes = 2

uid = developer
socket = /tmp/uwsgi/myproject.sock
chown-socket = nginx:nginx
chmod-socket = 666
vacuum = true

die-on-term = true

Aquí quiero prestar atención a las siguientes líneas:

  1. socket = /tmp/uwsgi/myproject.sock: para acelerar el servicio, debe usar unix-socket, y para que nginx se conecte a él, créelo en la carpeta temporal / tmp / uwsgi
  2. chown-socket = nginx: nginx transferirá los derechos de uso del socket al usuario nginx
  3. chmod-socket = 666 - tiene el mismo propósito que el anterior. Diferentes manuales y consejos tienen diferentes valores de parámetros (664, 665, 777), pero se ha establecido experimentalmente que 666 es mínimamente funcional.

Ahora puede proceder directamente a crear el servicio:

sudo vi /etc/systemd/system/myproject.service

[Unit]
Description=uWSGI instance to serve myproject app
After=network.target

[Service]
ExecStartPre=-/usr/bin/bash -c 'mkdir -p /tmp/uwsgi chown nginx:nginx /tmp/uwsgi'
ExecStart=/usr/bin/bash -c 'cd /opt/myproject; source myprojectenv/bin/activate; uwsgi --ini myproject.ini'
ExecStartPost=/usr/bin/bash -c 'setenforce 0'
PrivateTmp=false
[Install]
WantedBy=multi-user.target

Todas las líneas interesantes están en el bloque de Servicio:

  1. ExecStartPre es un comando que ejecutará el administrador del sistema antes de iniciar el servicio.

    - / usr / bin / bash -c anuncia el inicio de la siguiente secuencia de comandos, y 'mkdir -p / tmp / uwsgi chown nginx: nginx / tmp / uwsgi' crea una carpeta temporal para el socket y transfiere los derechos al usuario nginx.
  2. ExecStart es el comando que inicia el servicio directamente, y en él vamos secuencialmente al directorio de trabajo, activamos el entorno virtual e iniciamos el servidor uwsgi desde el archivo ini.
  3. ExecStartPost: un comando que se ejecuta después de que se inicia el servicio. En nuestro caso, es necesario para la correcta transferencia de solicitudes del servidor nginx al servidor uwsgi.
  4. PrivateTmp = false es un parámetro que hace que la carpeta temporal creada sea visible para otros procesos.

Ahora ejecuta el servicio:

systemctl start myproject
systemctl status myproject
systemctl enable myproject

El último comando hará que se inicie automáticamente después de reiniciar el servidor.

Y el último tirón: configuraremos el servidor nginx y haremos que nuestra aplicación web esté disponible para la red externa. El registro de su trabajo siempre se puede ver con el comando

journalctl -u  myproject

sudo vi /usr/lib/systemd/system/nginx.service

Busque el bloque [Servicio] y agregue PrivateTmp = false al final.

Después de eso, reinicie los demonios con el comando. systemctl daemon-reload

Ahora procedemos directamente a la configuración del servidor:

vi /etc/nginx/nginx.conf

http {
    . . .

    include /etc/nginx/conf.d/*.conf;

    server {
        listen 80 default_server;

        . . .

Encuentra el bloque http y agrega un nuevo servidor:

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/uwsgi/myproject.sock;
    }
}

Ahora queda encender el servidor y editar las reglas en el firewall:

systemctl start nginx
systemctl enable nginx

firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https

firewall-cmd --reload

Ahora, al acceder al servidor por su nombre de dominio o dirección IP, recibiremos una respuesta de nuestra aplicación Flask.

Espero que este material sea útil.

All Articles