Vorbereiten eines Servers für die Veröffentlichung einer Web-App in Python

Guten Tag, Habrovsk!

Es gab Freizeit und den Wunsch, eine kleine Webanwendung zu erstellen. Es gibt eine Idee (Daten von einem Wettersensor zu empfangen, in der Datenbank zu speichern und dann etwas Interessantes zu tun), einen kostenlosen Server für Centos. Die Tutorials zum Einrichten scheinen auch die gleichen zu sein ... Aber zum Zeitpunkt des Schreibens wurde kein einziges voll funktionsfähiges gefunden. Wenn Sie die Anwendung auch mit python3 auf einem CentOS 7.4-Server bereitstellen möchten. * Bundle, uwsgi und nginx, willkommen bei cat.

Also, was sollte schon sein und was wird in diesem Artikel nicht behandelt:

  1. Ein physischer oder virtueller Server unter CentOS 7.4 (die Leistung wird für andere Betriebssysteme und Versionen nicht garantiert).
  2. Zugriff auf den Server mit Superuser-Berechtigungen * Wenn der Server virtuell ist, wird davon ausgegangen, dass die Möglichkeit und Fähigkeit besteht, über SSH eine Verbindung zu ihm herzustellen.

Nach dem Herstellen einer Verbindung als Root-Benutzer besteht der erste Schritt darin, einen neuen Benutzer mit Administratorrechten zu erstellen (dies ist nicht erforderlich, aber zumindest ein guter Ton):

adduser developer
passwd developer

Hier müssen Sie das Benutzerpasswort eingeben und bestätigen

usermod -aG wheel developer

Benutzer zur lokalen Administratorgruppe hinzufügen

su - developer

Wechseln Sie zum frisch erstellten Benutzer.

Bereiten Sie nun die Umgebung vor:

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

Ich möchte auf die vorletzte Zeile aufmerksam machen - „Entwicklungstools“ und „Entwicklungsbibliotheken“ sind für den korrekten Start der virtuellen Umgebung erforderlich. Wir verwenden die Flagge, damit das Team erfüllt, ohne um Bestätigung zu bitten.

Jetzt können Sie mit der Erstellung des Arbeitsverzeichnisses beginnen:

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

Jetzt bereiten wir den Einstiegspunkt für die Webanwendung vor:

vi /opt/myproject/wsgi.py(Im Folgenden werde ich den vi-Editor verwenden, dies ist jedoch Geschmackssache.)

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

Mit diesem Code nach dem Start können wir sicherstellen, dass alle zuvor durchgeführten Schritte erfolgreich waren. Führen Sie zum Testen den Dienst aus:

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

Bei einer physischen ljcnegt- oder rdp-Verbindung kann das Ergebnis in einem Browser unter 0.0.0.0:8080 überprüft werden. Öffnen Sie mit einer SSH-Verbindung eine neue Sitzung und testen Sie mit curl:

curl -v 0.0.0.0:8080

Mit dem Flag -v können Sie die vollständige Ausgabe anzeigen.

Nach Abschluss des Tests sollten Sie den Dienst beenden, indem Sie STRG + C drücken (andernfalls müssen Sie nach dem Prozess suchen und ihn mit kill beenden. Dies ist ebenfalls ein Exit, aber definitiv weniger praktisch).

Jetzt können Sie die Hauptwebanwendung erstellen:

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')

Der Testprozess ist dem vorherigen ziemlich ähnlich - wir starten die Anwendung mit dem Befehl python3 /opt/myproject/myproject.pyund überprüfen. Das Ergebnis sollte das gleiche sein.

Bearbeiten Sie nun den Einstiegspunkt so, dass unsere Anwendung beim Aufruf startet:

vi /opt/myproject/wsgi.py

from myproject import application

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

Jetzt das schwierigste und interessanteste. Es ist Zeit, aus dieser Anwendung einen Dienst zu machen, der automatisch und im Hintergrund funktioniert.

Bereiten Sie zunächst die INI-Datei für uwsgi vor:

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

Hier möchte ich auf folgende Zeilen achten:

  1. socket = /tmp/uwsgi/myproject.sock - Um den Dienst zu beschleunigen, sollten Sie unix-socket verwenden. Damit nginx eine Verbindung herstellen kann, erstellen Sie ihn im temporären Ordner / tmp / uwsgi
  2. chown-socket = nginx: nginx überträgt Socket-Nutzungsrechte an den nginx-Benutzer
  3. chmod-socket = 666 - dient dem gleichen Zweck wie der vorherige. Verschiedene Handbücher und Tipps haben unterschiedliche Parameterwerte - 664, 665, 777 -, aber es wurde experimentell festgestellt, dass 666 nur minimal funktioniert.

Jetzt können Sie direkt mit dem Erstellen des Dienstes fortfahren:

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

Alle interessanten Zeilen befinden sich im Serviceblock:

  1. ExecStartPre ist ein Befehl, den der Systemmanager vor dem Starten des Dienstes ausführt.

    - / usr / bin / bash -c kündigt den Start der nächsten Befehlssequenz an, und 'mkdir -p / tmp / uwsgi chown nginx: nginx / tmp / uwsgi' erstellt einen temporären Ordner für den Socket und überträgt die Rechte an den nginx-Benutzer.
  2. ExecStart ist der Befehl, mit dem der Dienst direkt gestartet wird. In diesem Befehl werden wir nacheinander in das Arbeitsverzeichnis wechseln, die virtuelle Umgebung aktivieren und den uwsgi-Server über die INI-Datei starten.
  3. ExecStartPost - Ein Befehl, der nach dem Start des Dienstes ausgeführt wird. In unserem Fall ist dies für die korrekte Übertragung von Anforderungen vom nginx-Server zum uwsgi-Server erforderlich.
  4. PrivateTmp = false ist ein Parameter, der den erstellten temporären Ordner für andere Prozesse sichtbar macht.

Führen Sie nun den Dienst aus:

systemctl start myproject
systemctl status myproject
systemctl enable myproject

Mit dem letzten Befehl wird der Autostart nach einem Neustart des Servers ausgeführt.

Und der letzte Trottel - wir werden den Nginx-Server konfigurieren und unsere Webanwendung für das externe Netzwerk verfügbar machen. Das Protokoll seiner Arbeit kann immer mit dem Befehl angezeigt werden

journalctl -u  myproject

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

Suchen Sie den Block [Service] und fügen Sie am Ende PrivateTmp = false hinzu.

Starten Sie danach die Daemons mit dem Befehl neu. systemctl daemon-reload

Nun fahren wir direkt mit der Serverkonfiguration fort:

vi /etc/nginx/nginx.conf

http {
    . . .

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

    server {
        listen 80 default_server;

        . . .

Suchen Sie den http-Block und fügen Sie einen neuen Server hinzu:

server {
    listen 80;
    server_name server_domain_or_IP;

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

Jetzt muss der Server eingeschaltet und die Regeln für die Firewall bearbeitet werden:

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

Wenn wir nun über den Domänennamen oder die IP-Adresse auf den Server zugreifen, erhalten wir eine Antwort von unserer Flask-Anwendung.

Ich hoffe, dass dieses Material nützlich sein wird.

All Articles