Debian, Nginx und Gunicorn für ein Django-Projekt konfigurieren



Guten Tag allerseits.

Es gab eine Aufgabe, den Debian-Server auf Nginx für die Projekte Django 3.x zu erhöhen. Ich habe es geschafft, eine Reihe von Informationen im Internet zu brechen, indem ich Empfehlungen von verschiedenen Websites kombiniert habe. Wenn Sie lesen möchten, wie Sie Ihren ersten Server für ein Django-Projekt einrichten, sind Sie herzlich willkommen.

Ich werde dir ein wenig über dich erzählen, damit du verstehst, wer ich bin. Ich bin kein Entwickler, kein Programmierer, kein Systemadministrator oder habe sogar eine IT-Ausbildung. Ich bin Informatiklehrer. Aber bei der Arbeit muss ich den Schülern einige Punkte erklären, die sehr weit vom Schulkurs in Informatik entfernt sind, und einer davon ist die Entwicklung von Projekten auf Django.

Grundeinstellungen


Zunächst haben wir bereits einen Server mit Debian 10 installiert, es sollte keine Probleme bei der Installation von Debian geben. Ich hatte eine Neuinstallation ohne zusätzliche Einstellungen, also ging ich über root zu meinem Server und begann, einige der Hauptkomponenten für mich zu installieren.

apt-get update
apt-get install -y sudo htop git curl wget unzip zip gcc build-essential make
apt-get install -y tree redis-server nginx  libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-dev python-pil ython3-pil 
apt-get install -y python3-lxml libxslt-dev python-libxml2 python-libxslt1 python-dev gnumeric libpq-dev libxml2-dev libxslt1-dev libjpeg-dev libfreetype6-dev libcurl4-openssl-dev supervisor libgdbm-dev libnss3-dev ufw

Sie können dies alles in einer Installation zusammenfassen, aber ich habe einen Fehler erhalten, und in dieser Reihenfolge ist alles gut gelaufen.

Erstellen Sie als Nächstes einen neuen Benutzer und fügen Sie ihn der Sudo- Gruppe hinzu, damit er Prozesse im Auftrag des Superusers starten kann.

adduser username 
usermod -aG sudo username

Dabei ist Benutzername der Benutzername , den Sie in Zukunft verwenden werden.
Installieren Sie die neueste Version von Python aus dem Quellcode. Zum Zeitpunkt des Schreibens war dies 3.8.2 .

cd /home/username
curl -O https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
tar -xf Python-3.8.2.tar.xz
cd Python-3.8.2

Erklärung der Aktionen
cd — , change directory;
curl — URL. ;
tar — .

Nachdem wir die neueste Version von Python heruntergeladen und in das Quellverzeichnis verschoben haben, führen wir Folgendes aus:

./configure --enable-optimizations
make -j 2

Auf diese Weise können wir alles vorbereiten, was für die Installation von Python erforderlich ist. Hier ist die Nummer 2 die Anzahl der Prozessorkerne. Sie können dies mit dem Befehl nproc herausfinden .
Wir starten die Installation.
make altinstall

Sie können überprüfen, ob Python installiert wurde, indem Sie den folgenden Befehl verwenden:

python3.8 -V

Es wird eine Version von Python ausgegeben .
Danach aktualisieren wir pip und installieren die am häufigsten verwendeten Pakete für Python .
python3.8 -m pip install -U pip
python3.8 -m pip install -U setuptools
python3.8 -m pip install pillow
python3.8 -m pip install virtualenv

Django Setup


Wir starten das System neu und gehen unter den von Ihnen erstellten Benutzer. Gehen wir zum Verzeichnis / var / www und laden unser Projekt herunter, das auf GitHub hochgeladen wird .

cd /var/www
sudo git clone LINK_TO_PROJECT

Konfigurieren Sie die Rechte für den normalen Betrieb mit dem Verzeichnis / var / www
sudo chown -R www-data:www-data /var/www
sudo usermod -aG www-data username
sudo chmod go-rwx /var/www
sudo chmod go+x /var/www
sudo chgrp -R www-data /var/www
sudo chmod -R go-rwx /var/www
sudo chmod -R g+rwx /var/www

Es mag den Anschein haben, als würden wir bestimmte Aktionen ausführen und sie dann abbrechen. Der Punkt ist jedoch, dass wir zuerst alle Berechtigungen für alle entfernen und sie dann einem bestimmten Benutzer oder einer bestimmten Gruppe zuweisen.

Wir gehen zu unserem Projekt, erstellen eine virtuelle Umgebung und führen sie aus:

cd djangoprojectname/
virtualenv env
source ./env/bin/activate

Wenn alles aktiviert ist, wird eine Zeile des Formulars angezeigt: (env) Benutzername @ Server.

Wir werden die Hauptpakete liefern / aktualisieren, die wir für unser Projekt benötigen.

pip install -U pip
pip install -U setuptools
pip install -U pillow

Wir setzen Django, Gunicorn und einen Adapter für PostgreSQL.

pip install django gunicorn psycopg2-binary

Sie können auch die für Ihr Projekt erforderlichen Pakete einfügen. Ich verwende Summernote für Text:

pip install django-summernote

Wir haben eine Firewall eingerichtet, daher müssen wir auf Port 8000 eine Ausnahme dafür erstellen (wir verwenden sie standardmäßig, wenn wir eine andere verwenden möchten, geben Sie sie an):

sudo ufw allow 8000

Der erforderliche Schritt besteht darin, den Zustand des Servers zu überprüfen:

python3.8 manage.py runserver 0.0.0.0:8000

Und gehen Sie zu Ihrer Website, DOMAIN_NAME: 8000 , um sicherzustellen, dass alles funktioniert! Aber im Moment haben wir noch nicht viel konfiguriert, dies sind nur Grundeinstellungen, wir müssen den normalen Betrieb des Servers konfigurieren, die Statik verbinden usw.
Wenn Ihre Site nicht gestartet wird, müssen Sie sich mit den Einstellungen (möglicherweise Zugriffsrechten) befassen und feststellen, welches Paket nicht installiert wurde. Alles ist sehr individuell.

Zur Vervollständigung durch Drücken der Tasten: die STRG + die C .

Dann fahren wir erst fort, wenn Ihr Projekt gestartet wurde. Ich empfehle dringend, nicht weiterzumachen, wenn etwas nicht funktioniert. Es ist besser, das Problem in der Anfangsphase zu beheben, als den Server bis zum Stamm herunterzureißen (ich habe 3 Mal abgerissen und dann angefangen, diese Anweisung zu schreiben und jede Aktion zu beheben).

Überprüfung der Arbeit von Gunicorn:

gunicorn --bind 0.0.0.0:8000 MAINAPPNAME.wsgi

MAINAPPNAME ist der Name der Hauptanwendung, die settings.py enthält .

Wenn der Server funktioniert, fahren Sie fort.

Zur Vervollständigung durch Drücken der Tasten: die C TRL + die C .

Einstellungen einstellen.py


Bei der Bereitstellung auf einem Produktionsserver müssen Sie das Debuggen aus dem Projekt deaktivieren und mehrere Einstellungen ändern. Dies habe ich in settings.py meines Projekts wie folgt durchgeführt .

DEBUG = False
if DEBUG:
    ALLOWED_HOSTS = ['*']
else:
    ALLOWED_HOSTS = ['HOST IP', 'DOMAIN NAIM', 'localhost']
...
STATIC_URL = '/static/'
if DEBUG:
    STATIC_DIR = os.path.join(BASE_DIR, 'static')
    STATICFILES_DIRS = [
        STATIC_DIR,
        '/var/www/static/',
    ]
else:
    STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    )
MEDIA_URL = '/media/'

In urls.py habe ich die Einstellungen für Statik und Medien geändert.

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Ich weiß nicht, wie sehr dies die richtige Entscheidung ist, und vielleicht gibt es korrektere Änderungen an diesen Dateien. In diesem Fall reicht es mir jedoch, den Wert von DEBUG zu ändern, um zwischen Entwicklung und Veröffentlichung zu wechseln.

Führen Sie den folgenden Befehl aus:

python3.8 manage.py collectstatic

So sammeln Sie Statiken und deaktivieren die virtuelle Umgebung:

deactivate

Gunicorn konfigurieren


Lassen Sie uns für die Anpassung öffnen

sudo nano /etc/systemd/system/gunicorn.socket

Schreiben wir ein paar Einstellungen in die Datei:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Wir haben den Abschnitt [Unit] erstellt, um den Socket zu beschreiben. Im Abschnitt [Socket] haben wir die Position des Sockets bestimmt und im Abschnitt [Install] müssen wir den Socket zum richtigen Zeitpunkt installieren.

Öffnen Sie die Dienstprogrammdatei systemd, um den Dienst zu konfigurieren:

sudo nano /etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=username
Group=www-data
WorkingDirectory=/var/www/djangoprojectname
ExecStart=/var/www/djangoprojectname/env/bin/gunicorn \
          --access-logfile - \
          --workers 5 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Vergessen Sie nicht, Ihren Benutzer, Ihren Projektnamen und Ihre virtuelle Umgebung anzugeben.

Wie mir erklärt, werden Worker als Anzahl der Prozessorkerne * 2 + 1 berechnet .
Jetzt starten und aktivieren wir die Gunicorn-Buchse.

sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

Und stellen Sie sicher, dass alles funktioniert!

sudo systemctl status gunicorn.socket

Sollte Informationen über den laufenden Dienst anzeigen. Drücken Sie zum Beenden

die Q- Taste (im englischen Layout erforderlich).

file /run/gunicorn.sock

Der letzte Befehl sollte eine Meldung über die Datei anzeigen.

Wenn der erste Befehl sudo systemctl status gunicorn.socket fehlschlägt oder wenn der zweite Befehl /run/gunicorn.sock meldet, dass sich die Datei gunicorn.sock nicht im Verzeichnis befindet, konnte der Gunicorn-Socket nicht erstellt werden. Sie müssen die Gunicorn-Socket-Protokolle mit dem folgenden Befehl überprüfen:

sudo journalctl -u gunicorn.socket

Sehen Sie, was der Fehler ist, und beheben Sie ihn.

Fahren wir mit dem Testen der Socket-Aktivierung fort.

sudo systemctl status gunicorn

Höchstwahrscheinlich haben Sie eine Aufzeichnung:

Active: inactive (dead)

Bisher läuft alles gut.

Stellen Sie durch Locken eine Verbindung zur Steckdose her.

curl --unix-socket /run/gunicorn.sock localhost


Kann den Fehler "Bad Request (400)" auslösen.

Versuchen Sie anstelle von localhost , die IP Ihres Servers anzugeben. Wenn alles in Ordnung ist, liegt dies höchstwahrscheinlich an den Nginx-Einstellungen, die wir noch nicht vorgenommen haben. Geh einfach weiter.

Fordern Sie erneut die Statusausgabe an:

sudo systemctl status gunicorn

Active: active (running)

Wenn der Datensatz dies + ist, gibt es immer noch viele Informationen, aber nicht über Fehler, dann ist alles in Ordnung.

Ansonsten betrachten wir Fehler im Protokoll

sudo journalctl -u gunicorn

Und starten Sie die Gunicorn-Prozesse neu

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

NGINX-Setup


Wir erstellen einen neuen Serverblock für unsere Site und konfigurieren ihn so, dass der Server beim Zugriff auf unsere Site in der Adressleiste versteht, von was und wo er abgerufen werden kann.

sudo nano /etc/nginx/sites-available/djangoprojectname

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /var/www/djangoprojectname/static/;
    }

    location /media/ {
        alias /var/www/djangoprojectname/media/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Im Abschnitt "Sever_Name" können Sie mehrere Adressen angeben, die durch Leerzeichen getrennt sind.

Test auf Syntaxfehler:

sudo nginx -t

Wenn keine Fehler vorliegen, starten Sie den Server neu und geben Sie unserer Firewall die erforderlichen Rechte:

sudo systemctl restart nginx
sudo ufw allow 'Nginx Full'

Sie können auch den Zugriff auf Port 8000 entfernen

sudo ufw delete allow 8000

Zu diesem Zeitpunkt sollte alles funktionieren, aber es hat für mich nicht gut funktioniert, bis ich https konfiguriert habe. Leider kann ich nicht erklären, womit dies zusammenhängt, aber die Statik wurde nicht geladen, obwohl die Mediendateien normal geladen wurden.

HTTPS-Setup


Wir werden Cerbot zum Konfigurieren verwenden

sudo apt-get install certbot python-certbot-nginx
sudo certbot –nginx

Befolgen Sie die Anweisungen auf dem Bildschirm. Wenn es Fehler gibt, beseitigen Sie und versuchen Sie es erneut. Beispielsweise kann ein Fehler auftreten, wenn Sie einen Domänennamen angeben, der nicht mit diesem Server zusammenhängt.
Geben Sie den Befehl ein, um das Zertifikat automatisch zu erneuern.

sudo certbot renew --dry-run 

Jetzt testen wir die Website und alles sollte funktionieren!

Wenn die Statik immer noch nicht angezeigt wird, versuchen Sie, eine CSS-Datei zu öffnen, in der die vollständige Adresse angegeben ist. Wenn Sie einen 403-Fehler erhalten, ist alles in Ordnung, aber das Problem mit den Zugriffsrechten muss mit ihnen experimentiert werden. Versuchen Sie, alle Rechteeinstellungen für WWW-Daten auf zurückzusetzen Verzeichnis / var / www . Wenn der Fehler 404 ist, müssen Sie in den NGINX- Einstellungen nach den Standorteinstellungen suchen .

PostgreSQL-Setup


Richten Sie PostgreSQL ein und importieren Sie Daten aus SQLite. Wenn Sie es nicht benötigen, überspringen Sie diesen Schritt oder nehmen Sie nur die PostgreSQL-Einstellungen vor.

Erstellen Sie eine Datenbank und einen Benutzer.

sudo -u postgres psql

CREATE DATABASE dbforproject;
CREATE USER projectdbuser WITH PASSWORD 'password';

Wir werden den Empfehlungen für das Django-Projekt folgen.

Wir setzen die Standardcodierung auf UTF-8, setzen das Standard-Transaktionsisolationsschema auf "Commit lesen", um das Lesen von nicht bestätigten Transaktionen zu blockieren. Stellen Sie die Zeitzone auf GMT (UTC) ein.

ALTER ROLE projectdbuser SET client_encoding TO 'utf8';
ALTER ROLE projectdbuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE projectdbuser SET timezone TO 'UTC';

Danach müssen Sie dem von uns erstellten Benutzer Zugriff gewähren, um die neue Datenbank zu verwalten:

GRANT ALL PRIVILEGES ON DATABASE dbforproject TO projectdbuser;

Nachdem alle Befehle ausgeführt wurden, können Sie den PostgreSQL-Dialog mit dem folgenden Befehl schließen:

\q

Jetzt ist die PostgreSQL-Konfiguration abgeschlossen. Jetzt konfigurieren wir Django so, dass es korrekt mit PostreSQL funktioniert.

Kopieren Sie zunächst die alten Daten aus SQLite (falls erforderlich). Gehen Sie dazu zu Ihrem Projekt und starten Sie die virtuelle Umgebung:

cd /var/www/djangoprojectname
source ./env/bin/activate
cd mainappname/
python3.8 manage.py dumpdata > datadump.json

Ändern Sie die Einstellungen für die Verbindung zur Datenbank:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'dbforproject',
        'USER': 'projectdbuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

Führen Sie die Migration für die Datenbank aus:

python3.8 manage.py migrate --run-syncdb

Nach dieser Shell:

python3 manage.py shell

Und schreibe hinein:

>>> from django.contrib.contenttypes.models import ContentType
>>> ContentType.objects.all().delete()
>>> quit()

Laden Sie die zuvor hochgeladenen Daten von SQLite:

python3.8 manage.py loaddata datadump.json

Das ist alles, alles hat begonnen und funktioniert für mich, aber im Fehlerfall ist es sehr individuell. Ich empfehle daher, die Schritte mit den Leistungstests nicht zu überspringen, damit Sie verstehen, in welchem ​​Stadium der Fehler aufgetreten ist.

Beim Schreiben habe ich verwendet:

  1. www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04-ru
  2. vexxhost.com/resources/tutorials/how-to-deploy-django-on-nginx-gunicorn-with-postgres
  3. pythonworld.ru/web/django-ubuntu1604.html

All Articles