One place for hosting & domains

      Gunicorn

      How To Deploy a Flask App Using Gunicorn to App Platform


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      In this guide, you will build a Python application using the Flask microframework on DigitalOcean’s App Platform. Flask is a Python-based microframework that is popular with web developers, given its lightweight nature and ease of use.

      This tutorial will focus on deploying a Flask app to App Platform using gunicorn. Gunicorn is a Python WSGI HTTP Server that uses a pre-fork worker model. By using gunicorn, you’ll be able to serve your Flask application on more than one thread.

      Prerequisites

      To complete this tutorial, you’ll need:

      Note: If you are looking for a general introduction to the Python programming language, our tutorial series, How To Code in Python, is a great place to start.

      Step 1 — Creating a Python Virtual Environment for your Project

      Before you get started, you need to set up your Python developer environment. You will install your Python requirements within a virtual environment for easier management.

      First, let’s create a project directory for our code and requirements.txt file to be stored in and change into that directory. Run the following commands:

      • mkdir flask-app
      • cd flask-app

      Next, create a directory in your home directory that you can use to store all of your virtual environments:

      Now create your virtual environment using Python:

      • python3 -m venv ~/.venvs/flask

      This will create a directory called flask within your .venvs directory. Inside, it will install a local version of Python and a local version of pip. You can use this to install and configure an isolated Python environment for your project.

      Before you install your project’s Python requirements, you need to activate the virtual environment.

      Use the following command:

      • source ~.venvs/flask/bin/activate

      Your prompt will change to indicate that you are now operating within a Python virtual environment. It will look something like this: (flask)user@host:~$.

      With your virtual environment active, install Flask and gunicorn using the local instance of pip:

      • pip install Flask gunicorn

      Note: When the virtual environment is activated (when your prompt has (flask) preceding it), use pip instead of pip3, even if you are using Python 3. The virtual environment’s copy of the tool is always named pip, regardless of the Python version.

      Now that you have the flask package installed, you will need to save this requirement and its dependencies so App Platform can install them later.

      Do this now using pip and then saving the information to a requirements.txt file:

      • pip freeze > requirements.txt

      You now have all of the software needed to start a Flask app. You are almost ready to deploy.

      Step 2 — Creating a Minimal Flask App

      In this step, you will build a standard Hello Sammy! Flask application. You won’t focus on the mechanics of Flask outside of how to deploy it to App Platform. If you wish to deploy another application, the following steps will work for a wide range of Flask applications.

      Using your favorite text editor, open a file named app.py:

      Now add the following code to the file:

      app.py

      from flask import Flask
      app = Flask(__name__)
      
      @app.route('/')
      def hello_world():
          return 'Hello Sammy!'
      

      This code is the standard Hello World example for Flask with a slight modification to say hello to your favorite shark. For more information about this file and Flask, visit the official Flask documentation.

      You have written your application code. Now you will configure the Gunicorn server.

      Step 3 — Setting Up Your Gunicorn Configuration

      Gunicorn is a Python WSGI HTTP server that many developers use to deploy their Python applications. This WSGI (Web Server Gateway Interface) is necessary because traditional web servers do not understand how to run Python applications. For your purposes, a WSGI allows you to deploy your Python applications consistently. You can also configure multiple threads to serve your Python application, should you need them. In this example, you will make your application accessible on port 8080, the standard App Platform port. You will also configure two worker-threads to serve your application.

      Open a file named gunicorn_config.py:

      Now add the following code to the file:

      gunicorn_config.py

      bind = "0.0.0.0:8080"
      workers = 2
      

      This is all you need to do to have your app run on App Platform using Gunicorn. Next, you’ll commit your code to GitHub and then deploy it.

      Step 4 — Pushing the Site to GitHub

      DigitalOcean’s App Platform deploys your code from GitHub repositories. This means that you must get your site in a git repository and then push that repository to GitHub.

      First, initialize your project directory containing your files as a git repository:

      When you work on your Flask app locally, certain files get added that are unnecessary for deployment. Let’s exclude those files using Git’s ignore list. Create a new file called .gitignore:

      Add the following code to the file:

      .gitignore

      *.pyc
      

      Save and close the file.

      Now execute the following command to add files to your repository:

      • git add app.py gunicorn_config.py requirements.txt .gitignore

      Make your initial commit:

      • git commit -m "Initial Flask App"

      Your files will commit:

      Output

      [master (root-commit) aa78a20] Initial Flask App 4 files changed, 18 insertions(+) create mode 100644 .gitignore create mode 100644 app.py create mode 100644 gunicorn_config.py create mode 100644 requirements.txt

      Open your browser and navigate to GitHub, log in with your profile, and create a new repository called flask-app. Create an empty repository without a README or license file.

      Once you’ve created the repository, return to the command line and push your local files to GitHub.

      First, add GitHub as a remote repository:

      • git remote add origin https://github.com/your_username/flask-app

      Next, rename the default branch main, to match what GitHub expects:

      Finally, push your main branch to GitHub’s main branch:

      Your files will transfer:

      Output

      Enumerating objects: 6, done. Counting objects: 100% (6/6), done. Delta compression using up to 8 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), 1.20 KiB | 77.00 KiB/s, done. Total 6 (delta 0), reused 0 (delta 0) To github.com:MasonEgger/flask-app.git * [new branch] main -> main Branch 'main' set up to track remote branch 'main' from 'origin'.

      Enter your GitHub credentials when prompted to push your code.

      Your code is now on GitHub and accessible through a web browser. Now you will deploy your app to DigitalOcean’s App Platform.

      Step 5 — Deploying to DigitalOcean with App Platform

      Once you push the code, visit The App Platform Homepage and click Launch Your App. A prompt will request that you connect your GitHub account:

      Connect GitHub account

      Connect your account and allow DigitalOcean to access your repositories. You can choose to let DigitalOcean access all of your repositories or just to the ones you wish to deploy.

      Allow repository access

      Click Install and Authorize. GitHub will return you to your DigitalOcean dashboard.

      Once you’ve connected your GitHub account, select the your_account/flask-app repository and click Next.

      Choose your repository

      Next, provide your app’s name, choose a region, and ensure the main branch is selected. Then ensure that Autodeploy code changes is checked. Click Next to continue.

      Choose a name, region, and branch

      DigitalOcean will detect that your project is a Python app and will automatically populate a partial Run command.

      Python Application detected and partial run command populated

      Click the Edit link next to the Build and Run commands to complete the build command. Your completed build command needs to reference your project’s WSGI file. In this example, this is at app:apitp.

      Replace the existing command with the following:

      • gunicorn --worker-tmp-dir /dev/shm app:app

      Completing the run command

      Click Next, and App Platform will direct you to the Finalize and Launch screen. Here you’ll choose your plan. Be sure to select the plan that fits your needs, whether in Basic App or Professional App. Click Launch App at the bottom. Your app will build and deploy:

      App building and deploying

      Once your app finishes deploying, click on the link to your app provided by App Platform. This link will take you to your Hello Sammy page.

      Initial Flask App

      You now have a Flask app deployed to App Platform. Make and push any changes to GitHub, and App Platform will automatically deploy them.

      Conclusion

      In this tutorial, you set up a Flask app and deployed it using DigitalOcean’s App Platform. Any changes you commit and push to your repository will trigger a new deployment. This means you can spend more time focusing on your code and expanding your application.

      You can find the example code for this tutorial in the DigitalOcean Sample Images Repository.

      The example in this tutorial is a minimal Flask app. Your project might have more applications and features, but the deployment process will be the same.



      Source link

      Einrichten von Django mit Postgres, Nginx und Gunicorn unter Ubuntu 20.04


      Einführung

      Django ist ein leistungsfähiges Web-Framework, das Ihnen dabei helfen kann, Ihre Python-Anwendung oder Website bereitzustellen. Django umfasst einen vereinfachten Entwicklungsserver zum lokalen Testen Ihres Codes; für alles, was auch nur ansatzweise mit der Produktion zu tun hat, wird ein sicherer und leistungsfähiger Webserver benötigt.

      In diesem Leitfaden zeigen wir, wie sich bestimmte Komponenten zum Unterstützen und Bereitstellen von Django-Anwendungen in Ubuntu 20.04 installieren und konfigurieren lassen. Wir werden anstelle der standardmäßigen SQLite-Datenbank eine PostgreSQL-Datenbank einrichten. Wir werden den Gunicorn-Anwendungsserver als Schnittstelle zu unseren Anwendungen konfigurieren. Dann werden wir Nginx als Reverseproxy für Gunicorn einrichten, damit wir beim Bereitstellen unserer Anwendungen auf dessen Sicherheits- und Leistungsmerkmale zugreifen können.

      Voraussetzungen und Ziele

      Um diesen Leitfaden erfolgreich zu absolvieren, sollten Sie eine neue Ubuntu 20.04-Serverinstanz mit einer einfachen Firewall und einem Nicht-root-Benutzer mit sudo-Berechtigungen konfiguriert haben. In unserem Leitfaden zur Ersteinrichtung des Servers erfahren Sie, wie Sie die Einrichtung vornehmen.

      Wir werden Django in einer virtuellen Umgebung installieren. Wenn Sie Django in einer für Ihr Projekt spezifischen Umgebung installieren, können Sie Ihre Projekte und deren Anforderungen separat verwalten.

      Sobald wir über unsere Datenbank verfügen und die Anwendung ausgeführt wird, installieren und konfigurieren wir den Gunicorn-Anwendungsserver. Dieser wird als Schnittstelle zu unserer Anwendung dienen und Clientanfragen aus HTTP in Python-Aufrufe übersetzen, die unsere Anwendung verarbeiten kann. Dann richten wir Nginx vor Gunicorn ein, um dessen leistungsfähige Verbindungsverwaltungsmechanismen und einfach zu implementierenden Sicherheitsfunktionen nutzen zu können.

      Fangen wir an.

      Installieren der Pakete aus den Ubuntu-Repositorys

      Zu Beginn laden wir alle Elemente, die wir benötigen, aus den Ubuntu-Repositorys herunter und installieren sie. Ein wenig später werden wir mit dem Python-Paketmanager pip zusätzliche Komponenten installieren.

      Wir müssen zuerst den lokalen Paketindex apt aktualisieren und dann die Pakete herunterladen und installieren: Die installierten Pakete hängen davon ab, welche Version von Python Sie für Ihr Projekt verwenden werden.

      Wenn Sie Django mit Python 3 nutzen, geben Sie Folgendes ein:

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

      Django 1.11 ist die letzte Version von Django, die Python 2 unterstützt. Wenn Sie neue Projekte starten, wird dringend empfohlen, Python 3 zu wählen. Wenn Sie Python 2 weiter verwenden müssen, geben Sie Folgendes ein:

      • sudo apt update
      • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

      Dadurch werden pip, die Python-Entwicklungsdateien, die zum späteren Erstellen von Gunicorn benötigt werden, das Postgres-Datenbankysystem, die zum Interagieren damit erforderlichen Bibliotheken sowie der Nginx-Webserver installiert.

      Erstellen der PostgreSQL-Datenbank und des Benutzers

      Wir legen sofort los und erstellen für unsere Django-Anwendung eine Datenbank und einen Datenbankbenutzer.

      Standardmäßig nutzt Postgres ein Authentifizierungschema namens „Peer Authentication“ für lokale Verbindungen. Im Grunde bedeutet dies, dass sich der Benutzer ohne weitere Authentifizierung anmelden kann, wenn der Benutzername des Benutzers im Betriebssystem mit einem gültigen Postgres-Benutzernamen übereinstimmt.

      Während der Postgres-Installation wurde ein Betriebssystembenutzer namens postgres erstellt, der dem administrativen PostgreSQL-Benutzer postgres entspricht. Wir benötigen diesen Benutzer zur Erledigung administrativer Aufgaben. Wir können sudo verwenden und den Benutzernamen mit der Option -u übergeben.

      Melden Sie sich in einer interaktiven Postgres-Sitzung an, indem Sie Folgendes eingeben:

      Ihnen wird eine PostgreSQL-Eingabeaufforderung angezeigt, in der Sie Ihre Anforderungen einrichten können.

      Erstellen Sie zunächst eine Datenbank für Ihr Projekt:

      • CREATE DATABASE myproject;

      Anmerkung: Jede Postgres-Anweisung muss mit einem Semikolon enden; stellen Sie sicher, dass Ihr Befehl auf ein Semikolon endet, falls Probleme auftreten.

      Erstellen Sie als Nächstes einen Datenbankbenutzer für das Projekt. Wählen Sie unbedingt ein sicheres Passwort:

      • CREATE USER myprojectuser WITH PASSWORD 'password';

      Anschließend ändern wir einige der Verbindungsparameter für den gerade erstellten Benutzer. Dadurch werden Datenbankoperationen beschleunigt, sodass die richtigen Werte nicht jedes Mal abgefragt und festgelegt werden müssen, wenn eine Verbindung hergestellt wird.

      Wir legen die Standardkodierung auf UTF-8 fest, was Django erwartet. Außerdem legen wir das standardmäßige Transaktionsisolierungsschema auf „read committed“ fest, um das Lesen von Blöcken aus Transaktionen ohne Commit zu blockieren. Schließlich legen wir die Zeitzone fest. Standardmäßig werden unsere Django-Projekte die Zeitzone UTC verwenden. Dies sind alles Empfehlungen aus dem Django-Projekt selbst:

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

      Jetzt können wir unserem neuen Benutzer Zugriff zum Verwalten unserer neuen Datenbank gewähren:

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

      Wenn Sie damit fertig sind, beenden Sie die PostgreSQL-Eingabeaufforderung durch folgende Eingabe:

      Postgres ist nun so eingerichtet, dass Django eine Verbindung herstellen und dessen Datenbankinformationen verwalten kann.

      Erstellen einer virtuellen Python-Umgebung für Ihr Projekt

      Nachdem wir unsere Datenbank erstellt haben, können wir nun damit beginnen, die restlichen Projektanforderungen zu erfüllen. Wir werden unsere Python-Anforderungen zur einfacheren Verwaltung in einer virtuellen Umgebung installieren.

      Dazu benötigen wir zunächst Zugriff auf den Befehl virtualenv. Wir können ihn mit pip installieren.

      Wenn Sie Python 3 verwenden, aktualisieren Sie pip und installieren Sie das Paket durch folgende Eingabe:

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

      Wenn Sie Python 2 verwenden, aktualisieren Sie pip und installieren Sie das Paket durch folgende Eingabe:

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

      Nach der Installation von virtualenv können wir mit der Gestaltung unseres Projekts beginnen. Erstellen und wechseln Sie in ein Verzeichnis, in dem wir unsere Projektdateien speichern können.

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

      Erstellen Sie im Projektverzeichnis durch folgende Eingabe eine virtuelle Python-Umgebung:

      Auf diese Weise wird ein Verzeichnis mit dem Namen myprojectenv in Ihrem Verzeichnis myprojectdir erstellt. Darin wird eine lokale Version von Python und eine lokale Version von pip installiert. Mit ihrer Hilfe können wir für unser Projekt eine isolierte Python-Umgebung installieren und konfigurieren.

      Bevor wir die Python-Anforderungen unseres Projekts installieren, müssen wir die virtuelle Umgebung aktivieren. Geben Sie hierzu Folgendes ein:

      • source myprojectenv/bin/activate

      Ihre Eingabeaufforderung ändert sich und zeigt an, dass Sie jetzt innerhalb einer virtuellen Python-Umgebung arbeiten. Sie sieht etwa wie folgt aus: (myprojectenv)user@host:~/myprojectdir$.

      Bei aktivierter virtueller Umgebung installieren Sie Django, Gunicorn und den PostgreSQL-Adapter psycopg2 mit der lokalen Instanz von pip:

      Anmerkung: Wenn die virtuelle Umgebung aktiviert ist (wenn Ihrer Eingabeaufforderung (myprojectenv) voransteht), verwenden Sie pip anstelle von pip3, selbst wenn Sie Python 3 verwenden. Die Kopie des Tools der virtuellen Umgebung heißt immer pip – unabhängig von der Python-Version.

      • pip install django gunicorn psycopg2-binary

      Sie sollten nun die gesamte für den Start eines Django-Projekts erforderliche Software haben.

      Erstellen und Konfigurieren eines neuen Django-Projekts

      Nach der Installation unserer Python-Komponenten können wir die eigentlichen Django-Projektdateien erstellen.

      Erstellen des Django-Projekts

      Da wir bereits über ein Projektverzeichnis verfügen, werden wir Django anweisen, die Dateien dort zu installieren. Es wird ein Verzeichnis der zweiten Ebene mit dem tatsächlichen Code erstellt, was normal ist, und ein Managementskript in diesem Verzeichnis platziert. Der Schlüssel dazu besteht darin, dass wir das Verzeichnis explizit definieren, anstatt Django Entscheidungen in Bezug auf unser aktuelles Verzeichnis zu ermöglichen:

      • django-admin.py startproject myproject ~/myprojectdir

      An diesem Punkt sollte Ihr Projektverzeichnis (in unserem Fall ~/myprojectdir) folgenden Inhalt haben:

      • ~/myprojectdir/manage.py: Ein Django-Projektmanagement-Skript.
      • ~/myprojectdir/myproject/: Das Django-Projektpaket. Dieses sollte die Dateien __init__.py, settings.py, urls.py, asgi.py und wsgi.py enthalten.
      • ~/myprojectdir/myprojectenv/: Das Verzeichnis der virtuellen Umgebung, die wir zuvor erstellt haben.

      Anpassen der Projekteinstellungen

      Das Erste, was wir mit unseren neu erstellten Projektdateien tun sollten, ist das Anpassen der Einstellungen. Öffnen Sie die Einstellungsdatei in Ihrem Texteditor:

      • nano ~/myprojectdir/myproject/settings.py

      Suchen Sie zunächst nach der Direktive ALLOWED_HOSTS. Dadurch wird eine Liste der Adressen oder Domänennamen des Servers definiert, die zum Herstellen einer Verbindung mit der Django-Instanz genutzt werden können. Alle eingehenden Anfragen mit einem Host, der sich nicht in dieser Liste befindet, werden eine Ausnahme auslösen. Django verlangt, dass Sie dies so festlegen, um eine bestimmte Art von Sicherheitslücke zu verhindern.

      In den quadratischen Klammern listen Sie die IP-Adressen oder Domänennamen auf, die mit Ihrem Django-Projekt verknüpft sind. Jedes Element sollte in Anführungszeichen aufgelistet werden, wobei Einträge durch ein Komma getrennt werden. Wenn Sie Anfragen für eine ganze Domäne und Subdomänen wünschen, stellen Sie dem Anfang des Eintrags einen Punkt voran. Im folgenden Snippet befinden sich einige auskommentierte Beispiele:

      Anmerkung: Stellen Sie sicher, dass localhost als eine der Optionen eingeschlossen ist, da wir Verbindungen über eine lokale Nginx-Instanz vermitteln werden.

      ~/myprojectdir/myproject/settings.py

      . . .
      # The simplest case: just add the domain name(s) and IP addresses of your Django server
      # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
      # To respond to 'example.com' and any subdomains, start the domain with a dot
      # ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
      ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
      

      Als Nächstes suchen Sie nach dem Bereich, der Datenbankzugriff konfiguriert. Er beginnt mit DATABASES. Die Konfiguration in der Datei dient für eine SQLite-Datenbank. Wir haben für unser Projekt bereits eine PostgreSQL-Datenbank erstellt; daher müssen wir die Einstellungen anpassen.

      Ändern Sie die Einstellungen mit Ihren PostgreSQL-Datenbankinformationen. Wir weisen Django an, den mit pip installierten psycopg2-Adapter zu verwenden. Wir müssen den Datenbanknamen, den Namen des Datenbankbenutzers und das Passwort des Datenbankbenutzers angeben. Dann geben wir an, dass sich die Datenbank auf dem lokalen Computer befindet. Sie können die PORT-Einstellung als leere Zeichenfolge belassen:

      ~/myprojectdir/myproject/settings.py

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

      Als Nächstes bewegen Sie sich nach unten zum Ende der Datei und fügen eine Einstellung hinzu, die angibt, wo die statischen Dateien platziert werden sollen. Das ist notwendig, damit Nginx Anfragen für diese Elemente verwalten kann. In der folgenden Zeile wird Django angewiesen, sie im grundlegenden Projektverzeichnis in einem Verzeichnis mit dem Namen static zu platzieren:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
      

      Wenn Sie dies abgeschlossen haben, speichern und schließen Sie die Datei.

      Abschließen der anfänglichen Projekteinrichtung

      Jetzt können wir das erste Datenbankschema mit dem Managementskript in unsere PostgreSQL-Datenbank migrieren:

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

      Erstellen Sie durch folgende Eingabe einen administrativen Benutzer für das Projekt:

      • ~/myprojectdir/manage.py createsuperuser

      Sie müssen einen Benutzernamen auswählen, eine E-Mail-Adresse angeben und ein Passwort bestätigen.

      Wir können alle statischen Inhalte am von uns konfigurierten Verzeichnisort sammeln, indem wir Folgendes eingeben:

      • ~/myprojectdir/manage.py collectstatic

      Sie müssen die Operation bestätigen. Die statischen Dateien werden dann in Ihrem Projektverzeichnis in einem Verzeichnis mit dem Namen static platziert.

      Wenn Sie den Leitfaden zur Ersteinrichtung des Servers befolgt haben, sollte Ihre UFW-Firewall Ihren Server schützen. Um den Entwicklungsserver zu testen, müssen wir Zugriff auf den Port gewähren, den wir dazu verwenden möchten.

      Erstellen Sie durch folgende Eingabe eine Ausnahme für Port 8000:

      Schließlich können Sie Ihr Projekt durch Starten des Django-Entwicklungsservers mit diesem Befehl testen:

      • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

      Rufen Sie in Ihrem Webbrowser den Domänennamen oder die IP-Adresse Ihres Servers auf, gefolgt von :8000:

      http://server_domain_or_IP:8000
      

      Sie sollten nun die Indexseite von Django erhalten:

      Django-Indexseite

      Wenn Sie am Ende der URL in der Adressleiste /admin anfügen, werden Sie zur Eingabe des administrativen Benutzernamens und Passworts aufgefordert, die Sie mit dem Befehl createsuperuser erstellt haben:

      Django-Admin-Anmeldung

      Nach der Authentifizierung können Sie auf die standardmäßige Admin-Schnittstelle von Django zugreifen:

      Django-Admin-Schnittstelle

      Wenn Sie mit der Erkundung fertig sind, klicken Sie im Terminalfenster auf Strg+C, um den Entwicklungsserver herunterzufahren.

      Testen der Fähigkeit von Gunicorn zum Bereitstellen des Projekts

      Das Letzte, was wir tun möchten, bevor wir unsere virtuelle Umgebung verlassen, ist Gunicorn zu testen. Dadurch wollen wir sicherstellen, dass die Anwendung bereitgestellt werden kann. Wir geben dazu unser Projektverzeichnis ein und verwenden gunicorn zum Laden des WSGI-Moduls des Projekts:

      • cd ~/myprojectdir
      • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

      Dadurch wird Gunicorn an der gleichen Schnittstelle gestartet, an der auch der Django-Server ausgeführt wurde. Sie können zurückgehen und die Anwendung erneut testen.

      Anmerkung: Die Admin-Schnittstelle wird keinen der verwendeten Stile verwenden, da Gunicorn nicht weiß, wo der dafür zuständige statische CSS-Inhalt zu finden ist.

      Wir haben Gunicorn einem Modul übergeben, indem wir mithilfe der Modulsyntax von Python den relativen Verzeichnispfad zur Datei wsgi.py von Django angegeben haben. Diese ist der Einstiegspunkt für unsere Anwendung. In dieser Datei ist eine Funktion namens application definiert, die zur Kommunikation mit der Anwendung dient. Um mehr über die WSGI-Spezifikation zu erfahren, klicken Sie hier.

      Wenn Sie mit dem Testen fertig sind, drücken Sie im Terminalfenster auf Strg+C, um Gunicorn anzuhalten.

      Wir sind nun fertig mit der Konfiguration unserer Django-Anwendung. Wir können unsere virtuelle Umgebung durch folgende Eingabe verlassen:

      Der Indikator für die virtuelle Umgebung in Ihrer Eingabeaufforderung wird entfernt.

      Erstellen von systemd-Socket- und Service-Dateien für Gunicorn

      Wir haben getestet, ob Gunicorn mit unserer Django-Anwendung interagieren kann. Wir sollten jedoch eine effektivere Methode zum Starten und Anhalten des Anwendungsservers implementieren. Dazu erstellen wir systemd-Service- und Socket-Dateien.

      Das Gunicorn-Socket wird beim Booten erstellt und nach Verbindungen lauschen. Wenn eine Verbindung hergestellt wird, startet systemd automatisch den Gunicorn-Prozess, um die Verbindung zu verwalten.

      Erstellen und öffnen Sie zunächst eine systemd-Socket-Datei für Gunicorn mit sudo-Berechtigungen:

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

      Darin erstellen wir einen Abschnitt [Unit], um das Socket zu beschreiben, einen Abschnitt [Socket], um den Ort des Sockets zu definieren, und einen Abschnitt [Install], um sicherzustellen, dass das Socket zum richtigen Zeitpunkt erstellt wird:

      /etc/systemd/system/gunicorn.socket

      [Unit]
      Description=gunicorn socket
      
      [Socket]
      ListenStream=/run/gunicorn.sock
      
      [Install]
      WantedBy=sockets.target
      

      Wenn Sie dies abgeschlossen haben, speichern und schließen Sie die Datei.

      Erstellen und öffnen Sie in Ihrem Texteditor als Nächstes eine systemd-Service-Datei für Gunicorn mit sudo-Berechtigungen. Der Name der Service-Datei sollte mit Ausnahme der Erweiterung mit dem Namen der Socket-Datei übereinstimmen:

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

      Beginnen Sie mit dem Abschnitt [Unit], mit dem Metadaten und Abhängigkeiten angegeben werden. Wir werden hier eine Beschreibung unseres Diensts eingeben und das Init-System anweisen, ihn erst zu starten, nachdem das Netzwerkziel erreicht wurde. Da sich unser Dienst auf das Socket aus der Socket-Datei bezieht, müssen wir eine Requires-Direktive einschließen, um diese Beziehung anzugeben:

      /etc/systemd/system/gunicorn.service

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

      Als Nächstes werden wir den Abschnitt [Service] öffnen. Wir werden den Benutzer und die Gruppe angeben, unter denen wir den Prozess ausführen möchten. Wir wollen unserem regulären Benutzerkonto die Prozessverantwortung übergeben, da es alle relevanten Dateien besitzt. Wir werden der Gruppe www-data die Gruppenverantwortung übergeben, damit Nginx einfach mit Gunicorn kommunizieren kann.

      Dann werden wir das Arbeitsverzeichnis zuordnen und den Befehl zum Starten des Diensts angeben. In diesem Fall müssen wir den vollständigen Pfad zur ausführbaren Gunicorn-Datei angeben, die in unserer virtuellen Umgebung installiert ist. Wir werden den Prozess mit dem im Verzeichnis /run erstellten Unix-Socket verknüpfen, damit der Prozess mit Nginx kommunizieren kann. Wir protokollieren alle Daten in der Standardausgabe, damit der journald-Prozess die Gunicorn-Protokolle erfassen kann. Außerdem können wir hier optionale Gunicorn-Optimierungen angeben. Beispielsweise haben wir in diesem Fall drei Workerprozesse angegeben:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      

      Schließlich werden wir einen Abschnitt [Install] hinzufügen. Dies teilt systemd mit, womit dieser Dienst verknüpft werden soll, wenn wir festlegen, dass er während des Startvorgangs starten soll. Wir wollen, dass dieser Dienst startet, wenn das normale Mehrbenutzersystem arbeitet.

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      
      [Install]
      WantedBy=multi-user.target
      

      Damit ist unsere systemd-Dienstdatei fertiggestellt. Speichern und schließen Sie diese jetzt.

      Wir können nun starten und das Gunicorn-Socket aktivieren. Dadurch wird die Socket-Datei nun unter /run/gunicorn.sock und beim Booten erstellt. Wenn eine Verbindung zu diesem Socket hergestellt wird, startet systemd automatisch den gunicorn.service, um die Verbindung zu verwalten:

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

      Wir können uns vergewissern, dass der Vorgang erfolgreich war, indem wir nach der Socket-Datei suchen.

      Suchen nach der Gunicorn-Socket-Datei

      Überprüfen Sie den Status des Prozesses, um herauszufinden, ob er gestartet werden konnte:

      • sudo systemctl status gunicorn.socket

      Sie sollten eine Ausgabe wie diese erhalten:

      Output

      ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

      Überprüfen Sie als Nächstes, ob die Datei gunicorn.sock im Verzeichnis /run vorhanden ist:

      Output

      /run/gunicorn.sock: socket

      Wenn der Befehl systemctl status angegeben hat, dass ein Fehler aufgetreten ist, oder Sie die Datei gunicorn.sock im Verzeichnis nicht finden können, ist dies ein Hinweis darauf, dass das Gunicorn-Socket nicht richtig erstellt wurde. Überprüfen Sie die Protokolle des Gunicorn-Sockets durch folgende Eingabe:

      • sudo journalctl -u gunicorn.socket

      Werfen Sie einen erneuten Blick auf Ihre Datei /etc/systemd/system/gunicorn.socket, um alle vorhandenen Probleme zu beheben, bevor Sie fortfahren.

      Testen der Socket-Aktivierung

      Wenn Sie derzeit nur die Einheit gunicorn.socket gestartet haben, wird der gunicorn.service aktuell noch nicht aktiv sein, da das Socket noch keine Verbindungen erhalten hat. Geben Sie zum Überprüfen Folgendes ein:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

      Zum Testen des Socket-Aktivierungsverfahrens können wir über curl eine Verbindung an das Socket senden, indem wir Folgendes eingeben:

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

      Sie sollten die HTML-Ausgabe von Ihrer Anwendung im Terminal erhalten. Das bedeutet, dass Gunicorn gestartet wurde und Ihre Django-Anwendung bereitstellen konnte. Sie können überprüfen, ob der Gunicorn-Service ausgeführt wird, indem Sie Folgendes eingeben:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

      Wenn die Ausgabe von curl oder die Ausgabe von systemctl status anzeigt, dass ein Problem aufgetreten ist, prüfen Sie die Protokolle auf weitere Details:

      • sudo journalctl -u gunicorn

      Überprüfen Sie Ihre Datei /etc/systemd/system/gunicorn.service auf Probleme. Wenn Sie Änderungen an der Datei /etc/systemd/system/gunicorn.service vornehmen, laden Sie das Daemon neu, um die Dienstdefinition neu zu lesen, und starten Sie den Gunicorn-Prozess neu, indem Sie Folgendes eingeben:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn

      Sorgen Sie dafür, dass die oben genannten Probleme behoben werden, bevor Sie fortfahren.

      Konfigurieren von Nginx zur Proxy-Übergabe an Gunicorn

      Nachdem Gunicorn eingerichtet ist, müssen wir nun Nginx so konfigurieren, dass Datenverkehr an den Prozess übergeben wird.

      Erstellen und öffnen Sie zunächst einen neuen Serverblock im Verzeichnis sites-available von Nginx:

      • sudo nano /etc/nginx/sites-available/myproject

      Öffnen Sie darin einen neuen Serverblock. Wir geben zunächst an, dass dieser Block am normalen Port 80 lauschen und auf den Domänennamen oder die IP-Adresse unseres Servers reagieren soll:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      }
      

      Als Nächstes weisen wir Nginx an, alle Probleme bei der Suche nach einem Favicon zu ignorieren. Außerdem teilen wir Nginx mit, wo die statischen Assets zu finden sind, die wir in unserem Verzeichnis ~/myprojectdir/static gesammelt haben. Alle diese Dateien verfügen über das Standard-URI-Präfix “/static”; daher können wir einen Ortsblock erstellen, um diese Anfragen abzugleichen:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      }
      

      Schließlich erstellen wir einen location / {}-Block zum Abgleichen aller anderen Anforderungen. In diesen Block werden wir die standardmäßige Datei proxy_params einschließen, die in der Nginx-Installation enthalten ist, und dann den Datenverkehr direkt an das Gunicorn-Socket übergeben.

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/run/gunicorn.sock;
          }
      }
      

      Wenn Sie dies abgeschlossen haben, speichern und schließen Sie die Datei. Jetzt können wir die Datei aktivieren, indem wir sie mit dem Verzeichnis sites-enabled verknüpfen:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Prüfen Sie Ihre Nginx-Konfiguration durch folgende Eingabe auf Syntaxfehler:

      Wenn keine Fehler gemeldet werden, fahren Sie fort und starten Sie Nginx neu, indem Sie Folgendes eingeben:

      • sudo systemctl restart nginx

      Schließlich müssen wir unsere Firewall an Port 80 für normalen Datenverkehr öffnen. Da wir keinen Zugriff mehr auf den Entwicklungsserver benötigen, können wir außerdem die Regel zum Öffnen von Port 8000 entfernen:

      • sudo ufw delete allow 8000
      • sudo ufw allow 'Nginx Full'

      Sie sollten nun in der Lage sein, die Domäne oder IP-Adresse Ihres Servers aufzurufen, um Ihre Anwendung anzuzeigen.

      Anmerkung: Nach der Konfiguration von Nginx sollte der nächste Schritt aus dem Sichern des Datenverkehrs zum Server mit SSL/TLS bestehen. Das ist äußerst wichtig, da ohne SSL/TLS alle Informationen, einschließlich Passwörter, in Klartext über das Netzwerk gesendet werden.

      Wenn Sie einen Domänennamen haben, ist Let’s Encrypt der einfachste Weg, um sich ein SSL-Zertifikat zum Sichern Ihres Datenverkehrs zu verschaffen. Folgen Sie diesem Leitfaden zum Einrichten von Let’s Encrypt mit Nginx unter Ubuntu 20.04. Befolgen Sie das Verfahren mit dem Nginx-Serverblock, den wir in diesem Leitfaden erstellt haben.

      Fehlerbehebung bei Nginx und Gunicorn

      Wenn Ihre Anwendung in diesem letzten Schritt nicht angezeigt wird, müssen Sie Probleme mit Ihrer Installation beheben.

      Nginx zeigt anstelle der Django-Anwendung die Standardseite an

      Wenn Nginx die Standardseite und nicht einen Proxy zu Ihrer Anwendung anzeigt, bedeutet das in der Regel, dass Sie den server_name in der Datei /etc/nginx/sites-available/myproject so ändern müssen, dass er auf die IP-Adresse oder den Domänennamen Ihres Servers verweist.

      Nginx verwendet den server_name, um zu bestimmen, welcher Serverblock für Antworten auf Anfragen verwendet werden soll. Wenn Sie die Nginx-Standardseite erhalten, ist das ein Zeichen dafür, dass Nginx die Anfrage nicht explizit mit einem Serverblock abgleichen konnte. Darum greift Nginx auf den Standardblock zurück, der in /etc/nginx/sites-available/default definiert ist.

      Der server_name im Serverblock Ihres Projekts muss spezifischer sein als der im auszuwählenden standardmäßigen Serverblock.

      Nginx zeigt anstelle der Django-Anwendung einen 502-Fehler (Ungültiges Gateway) an

      Ein 502-Fehler zeigt, dass Nginx die Anfrage per Proxy nicht erfolgreich vermitteln kann. Eine Vielzahl von Konfigurationsproblemen äußern sich in einem 502-Fehler; für eine angemessene Fehlerbehebung sind also weitere Informationen erforderlich.

      Der primäre Ort zur Suche nach weiteren Informationen sind die Fehlerprotokolle von Nginx. Generell werden sie Ihnen mitteilen, welche Bedingungen während des Proxying-Ereignisses Probleme verursacht haben. Folgen Sie den Nginx-Fehlerprotokollen, indem Sie Folgendes eingeben:

      • sudo tail -F /var/log/nginx/error.log

      Erstellen Sie nun in Ihrem Browser eine weitere Anfrage zur Generierung eines neuen Fehlers (versuchen Sie, die Seite zu aktualisieren). Sie sollten eine neue Fehlermeldung erhalten, die in das Protokoll geschrieben wird. Wenn Sie sich die Nachricht ansehen, sollten Sie das Problem eingrenzen können.

      Sie erhalten möglicherweise die folgende Meldung:

      connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

      Das bedeutet, dass Nginx die Datei gunicorn.sock am angegebenen Ort nicht finden konnte. Sie sollten den proxy_pass-Ort, der in der Datei /etc/nginx/sites-available/myproject definiert ist, mit dem tatsächlichen Ort der Datei gunicorn.sock vergleichen, die von der Datei gunicorn.socket generiert wurde.

      Wenn Sie keine gunicorn.sock-Datei im Verzeichnis /run finden können, bedeutet das im Allgemeinen, dass die systemd-Socket-Datei sie nicht erstellen konnte. Kehren Sie zurück zum Abschnitt zum Suchen nach der Gunicorn-Socket-Datei, um die Schritte zur Fehlerbehebung für Gunicorn zu durchlaufen.

      connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

      Das bedeutet, dass Nginx aufgrund von Berechtigungsproblemen keine Verbindung zum Gunicorn-Socket herstellen konnte. Dies kann geschehen, wenn das Verfahren mit dem root user anstelle eines sudo-Benutzers ausgeführt wird. Zwar kann systemd die Gunicorn-Socket-Datei erstellen, doch kann Nginx nicht darauf zugreifen.

      Dies kann geschehen, wenn es an einem beliebigen Punkt zwischen dem root-Verzeichnis (/) der Datei gunicorn.sock begrenzte Berechtigungen gibt. Wir können die Berechtigungen und Verantwortungswerte der Socket-Datei und jedes der übergeordneten Verzeichnisse überprüfen, indem wir den absoluten Pfad zu unserer Socket-Datei dem Befehl namei übergeben:

      • namei -l /run/gunicorn.sock

      Output

      f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

      Die Ausgabe zeigt die Berechtigungen der einzelnen Verzeichniskomponenten an. Indem wir uns die Berechtigungen (erste Spalte), den Besitzer (zweite Spalte) und den Gruppenbesitzer (dritte Spalte) ansehen, können wir ermitteln, welche Art des Zugriffs auf die Socket-Datei erlaubt ist.

      Im obigen Beispiel haben die Socket-Datei und die einzelnen Verzeichnisse, die zur Socket-Datei führen, globale Lese- und Ausführungsberechtigungen (die Berechtigungsspalte für die Verzeichnisse endet mit r-x anstelle von ---). Der Nginx-Prozess sollte erfolgreich auf das Socket zugreifen können.

      Wenn eines der Verzeichnisse, das zum Socket führt, keine globale Lese- und Ausführungsberechtigung aufweist, kann Nginx nicht auf das Socket zugreifen, ohne globale Lese- und Ausführungsberechtigungen zuzulassen oder sicherzustellen, dass die Gruppenverantwortung einer Gruppe erteilt wird, zu der Nginx gehört.

      Django zeigt an: “could not connect to server: Connection refused”

      Eine Meldung, die Sie bei dem Versuch, im Webbrowser auf Teile der Anwendung zuzugreifen, von Django erhalten können, lautet:

      OperationalError at /admin/login/
      could not connect to server: Connection refused
          Is the server running on host "localhost" (127.0.0.1) and accepting
          TCP/IP connections on port 5432?
      

      Das bedeutet, dass Django keine Verbindung zur Postgres-Datenbank herstellen kann. Vergewissern Sie sich durch folgende Eingabe, dass die Postgres-Instanz ausgeführt wird:

      • sudo systemctl status postgresql

      Wenn nicht, können Sie sie starten und so aktivieren, dass sie beim Booten automatisch gestartet wird (wenn sie nicht bereits entsprechend konfiguriert ist); geben Sie dazu Folgendes ein:

      • sudo systemctl start postgresql
      • sudo systemctl enable postgresql

      Wenn Sie weiter Probleme haben, stellen Sie sicher, dass die in der Datei ~/myprojectdir/myproject/settings.py definierten Datenbankeinstellungen korrekt sind.

      Weitere Fehlerbehebung

      Bei der weiteren Fehlerbehebung können die Protokolle dazu beitragen, mögliche Ursachen einzugrenzen. Prüfen Sie sie nacheinander und suchen Sie nach Meldungen, die auf Problembereiche hinweisen.

      Folgende Protokolle können hilfreich sein:

      • Prüfen Sie die Nginx-Prozessprotokolle, indem Sie Folgendes eingeben: sudo journalctl -u nginx
      • Prüfen Sie die Nginx-Zugangsprotokolle, indem Sie Folgendes eingeben: sudo less /var/log/nginx/access.log
      • Prüfen Sie die Nginx-Fehlerprotokolle, indem Sie Folgendes eingeben: sudo less /var/log/nginx/error.log
      • Prüfen Sie die Gunicorn-Anwendungsprotokolle, indem Sie Folgendes eingeben: sudo journalctl -u gunicorn
      • Prüfen Sie die Gunicorn-Socket-Protokolle, indem Sie Folgendes eingeben: sudo journalctl -u gunicorn.socket

      Wenn Sie Ihre Konfiguration oder Anwendung aktualisieren, müssen Sie die Prozesse wahrscheinlich neu starten, damit Ihre Änderungen aktiv werden.

      Wenn Sie Ihre Django-Anwendung aktualisieren, können Sie den Gunicorn-Prozess durch folgende Eingabe neu starten, um die Änderungen zu erfassen:

      • sudo systemctl restart gunicorn

      Wenn Sie Gunicorn-Socket- oder Service-Dateien ändern, laden Sie das Daemon neu und starten Sie den Prozess neu, indem Sie Folgendes eingeben:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

      Wenn Sie die Konfiguration des Nginx-Serverblocks ändern, testen Sie die Konfiguration und dann Nginx, indem Sie Folgendes eingeben:

      • sudo nginx -t && sudo systemctl restart nginx

      Diese Befehle sind hilfreich, um Änderungen zu erfassen, während Sie Ihre Konfiguration anpassen.

      Zusammenfassung

      In diesem Leitfaden haben wir ein Django-Projekt in seiner eigenen virtuellen Umgebung eingerichtet. Wir haben Gunicorn so konfiguriert, dass Clientanfragen übersetzt werden, damit Django sie verwalten kann. Anschließend haben wir Nginx als Reverseproxy eingerichtet, um Clientverbindungen zu verwalten und je nach Clientanfrage das richtige Projekt bereitzustellen.

      Django macht die Erstellung von Projekten und Anwendungen durch Bereitstellung vieler der gängigen Elemente besonders einfach; so können Sie sich ganz auf die individuellen Elemente konzentrieren. Durch Nutzung der in diesem Artikel beschriebenen allgemeinen Tool Chain können Sie die erstellten Anwendungen bequem über einen einzelnen Server bereitstellen.



      Source link

      Cómo configurar Django con Postgres, Nginx y Gunicorn en Ubuntu 20.04


      Introducción

      Django es un poderoso framework que puede ayudarle a poner en marcha su aplicación o sitio web con Python. Incluye un servidor de desarrollo simplificado para probar su código a nivel local. Sin embargo, para cualquier cosa que esté incluso apenas relacionada con la producción se requiere un servidor web más seguro y potente.

      En esta guía, demostraremos la forma de instalar y configurar algunos componentes en Ubuntu 20.04 para que sean compatibles con aplicaciones de Django y permitan su funcionamiento. Configuraremos una base de datos de PostgreSQL en lugar de usar la base de datos predeterminada de SQLite. Configuraremos el servidor de aplicaciones de Gunicorn para que interactúe con nuestras aplicaciones. Luego, configuraremos Nginx para que invierta el proxy de Gunicorn, lo que nos dará acceso a sus funciones de seguridad y rendimiento para nuestras aplicaciones.

      Requisitos previos y objetivos

      Para completar esta guía, debe disponer de una instancia de servidor de Ubuntu 20.04 nueva con un firewall básico y un usuario no root con privilegios sudo configurados. Puede aprender a configurarlo con nuestra guía de configuración inicial para servidores.

      Instalaremos Django en un entorno virtual. Instalar Django en un entorno específico para nuestro proyecto permitirá que sus proyectos y los requisitos de estos se administren por separado.

      Una vez que tengamos nuestra base de datos y la aplicación en funcionamiento, instalaremos y configuraremos el servidor de aplicaciones de Gunicorn. Esto servirá como interfaz para nuestra aplicación, al traducir las solicitudes de los clientes de HTTP a llamadas Python que nuestra aplicación puede procesar. Luego, instalaremos Nginx frente a Gunicorn para aprovechar sus mecanismos de administración de conexiones de alto rendimiento y sus características de seguridad fáciles de implementar.

      Comencemos.

      Instalar los paquetes desde los repositorios de Ubuntu

      Para iniciar este proceso, descargaremos e instalaremos todos los elementos necesarios desde los repositorios de Ubuntu. Usaremos el administrador de paquetes de Python pip para instalar componentes adicionales más tarde.

      Tendremos que actualizar el índice de paquetes apt local y, luego, descargar e instalar los paquetes. Los paquetes que instalemos dependen de la versión de Python que use en su proyecto.

      Si usa Django con Python 3, escriba lo siguiente:

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

      Django 1.11 es la última versión que será compatible con Python 2. Si va a iniciar proyectos nuevos, le recomendamos enfáticamente seleccionar Python 3. Si necesita seguir usando Python 2, escriba lo siguiente:

      • sudo apt update
      • sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

      Con esto, se instalarán pip, los archivos de desarrollo de Python necesarios para compilar Gunicorn posteriormente, el sistema de base de datos de Postgres junto con las bibliotecas necesarias para interactuar con él y el servidor web Nginx.

      Crear la base de datos y el usuario de PostgreSQL

      Crearemos una base de datos y un usuario de base de datos para nuestra aplicación de Django.

      Por defecto, Postgres usa un esquema de autenticación llamado “autenticación por pares” para las conexiones locales. Básicamente, esto significa que si el nombre de usuario del sistema operativo del usuario coincide con un nombre de usuario de Postgres válido, ese usuario puede iniciar sesión sin autenticaciones adicionales.

      Durante la instalación de Postgres, se creó un usuario del sistema operativo llamado postgres para que se corresponda con el usuario administrativo postgres de PostgreSQL. Necesitamos usar este usuario para realizar tareas administrativas. Podemos usar sudo y pasar el nombre de usuario con la opción -u.

      Inicie una sesión interactiva de Postgres escribiendo lo siguiente:

      Recibirá un mensaje de PostgreSQL en el que se pueden configurar los requisitos.

      Primero, cree una base de datos para su proyecto:

      • CREATE DATABASE myproject;

      Nota: Cada instrucción de Postgres debe terminar con punto y coma. Por eso, si presenta problemas, debe asegurarse de que su comando tenga esta terminación.

      A continuación, cree un usuario de base de datos para nuestro proyecto. Asegúrese de elegir una contraseña segura.

      • CREATE USER myprojectuser WITH PASSWORD 'password';

      Más adelante, modificaremos algunos de los parámetros de conexión para el usuario que acabamos de crear. Esto acelerará las operaciones de la base de datos para que no sea necesario consultar y fijar los valores correctos cada vez que se establezca una conexión.

      Fijaremos el código predeterminado en UTF-8, que es lo que Django espera. También fijaremos el esquema predeterminado de aislamiento de transacciones en “read committed”, que bloquea las lecturas de transacciones no comprometidas. Por último, configuraremos la zona horaria. Por defecto, nuestros proyectos de Django se configurarán para usar la opción UTC. Estas son todas las recomendaciones del propio proyecto de Django:

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

      Ahora, podemos brindar a nuestro nuevo usuario acceso para administrar nuestra nueva base de datos:

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

      Cuando termine, cierre la línea de comandos de PostgreSQL escribiendo lo siguiente:

      Postgres quedará, así, configurado para que Django pueda conectarse y administrar la información de su base de datos.

      Crear un entorno virtual de Python para su proyecto

      Ahora que tenemos nuestra base de datos, podemos empezar a cumplir con el resto de los requisitos de nuestro proyecto. Instalaremos los componentes de Python requeridos en un entorno virtual para facilitar la administración.

      Para hacerlo, primero necesitamos acceso al comando virtualenv. Podemos instalarlo con pip.

      Si usa Python 3, actualice pip e instale el paquete escribiendo lo siguiente:

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

      Si usa Python 2, actualice pip e instale el paquete escribiendo lo siguiente:

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

      Con virtualenv instalado, podemos comenzar a dar forma a nuestro proyecto. Cree y un directorio en el que podamos guardar los archivos de nuestro proyecto y posiciónese en él:

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

      En el directorio del proyecto, cree un entorno virtual de Python escribiendo lo siguiente:

      Con esto, se creará un directorio llamado myprojectenv en su directorio myprojectdir. Dentro de este, se instalarán una versión local de Python y una versión local de pip. Podemos usar esto para instalar y configurar un entorno aislado de Python para nuestro proyecto.

      Antes de instalar los componentes de Python requeridos para nuestro proyecto, debemos activar el entorno virtual. Puede hacerlo escribiendo lo siguiente:

      • source myprojectenv/bin/activate

      Su línea de comandos cambiará para indicar que ahora realiza operaciones en un entorno virtual de Python. Tendrá este aspecto: (myprojectenv)user@host:~/myprojectdir$.

      Con su entorno virtual activo, instale Django, Gunicorn y el adaptador psycopg2 de PostgreSQL con la instancia local de pip:

      Nota: Cuando se active el entorno virtual (cuando (myprojectenv) se encuentre al inicio de su línea de comandos), use pip en lugar de pip3, incluso si emplea Python 3. La copia del entorno virtual de la herramienta siempre se llama pip, independientemente de la versión de Python.

      • pip install django gunicorn psycopg2-binary

      Con esto, debería contar con todo el software necesario para iniciar un proyecto en Django.

      Crear y configurar un nuevo proyecto de Django

      Una vez instalados nuestros componentes de Python, podemos crear los archivos reales del proyecto en Django.

      Crear el proyecto de Django

      Debido a que ya disponemos de un directorio de proyectos, le indicaremos a Django que instale los archivos en él. Se creará un directorio de segundo nivel con el código real, lo cual es normal, y se dispondrá una secuencia de comandos de administración en este directorio. La clave para esto es que definiremos el directorio de forma explícita en lugar de permitir que Django tome decisiones vinculadas con nuestro directorio actual:

      • django-admin.py startproject myproject ~/myprojectdir

      En este punto, el directorio de su proyecto (~/myprojectdir en nuestro caso) debe tener el siguiente contenido:

      • ~/myprojectdir/manage.py: una secuencia de comandos de administración del proyecto de Django.
      • ~/myprojectdir/myproject/: el paquete de proyectos de Django. Este debe contener los archivos __init__.py, settings.py, urls.py, asgi.py y wsgi.py.
      • ~/myprojectdir/myprojectenv/: el directorio del entorno virtual que creamos anteriormente.

      Ajustar la configuración del proyecto

      Lo primero que debemos hacer con los archivos del proyecto recientemente creado es ajustar la configuración. Abra el archivo de configuración en su editor de texto:

      • nano ~/myprojectdir/myproject/settings.py

      Comience por localizar la directiva ALLOWED_HOSTS. Con esto, se define una lista de las direcciones de los servidores o los nombres de dominio que pueden usarse para establecer una conexión con la instancia en Django. Cualquier solicitud entrante con un encabezado de Host que no figure en esta lista generará una excepción. Django necesita que configure esto para evitar una clase de vulnerabilidad de seguridad determinada.

      En los corchetes, enumere las direcciones IP o los nombres de dominio que están asociados con su servidor Django. Cada elemento debe listarse entre comillas y las entradas deben ir separadas por una coma. Si desea solicitudes para un dominio completo y cualquier subdominio, anteponga un punto al comienzo de la entrada. En el fragmento inferior, hay algunos ejemplos comentados que se usan para demostrar lo siguiente:

      Nota: Asegúrese de incluir localhost como una de las opciones, ya que autorizaremos conexiones a través de una instancia local de Nginx.

      ~/myprojectdir/myproject/settings.py

      . . .
      # The simplest case: just add the domain name(s) and IP addresses of your Django server
      # ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
      # To respond to 'example.com' and any subdomains, start the domain with a dot
      # ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
      ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
      

      A continuación, busque la sección que configura el acceso a la base de datos. Se iniciará con DATABASES. La configuración del archivo es para una base de datos de SQLite. Ya creamos una base de datos de PostgreSQL para nuestro proyecto. Ahora debemos ajustar las configuraciones.

      Cambie las configuraciones por la información de su base de datos de PostgreSQL. Indicaremos a Django que use el adaptador psycopg2 que instalamos con pip. Debemos proporcionar el nombre de la base de datos, el nombre de usuario y la contraseña del usuario, y luego especificar que la base de datos se encuentra en una computadora local. Puede dejar la configuración de PORT como una secuencia de comandos vacía:

      ~/myprojectdir/myproject/settings.py

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

      A continuación, diríjase hasta la parte inferior del archivo y agregue una configuración que indique dónde deben disponerse los archivos estáticos. Esto es necesario para que Nginx pueda manejar las solicitudes de estos elementos. La siguiente línea indica a Django que los disponga en un directorio llamado static en el directorio de proyectos de base:

      ~/myprojectdir/myproject/settings.py

      . . .
      
      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
      

      Guarde y cierre el archivo cuando termine.

      Completar la configuración inicial del proyecto

      Ahora, podemos migrar el esquema inicial de la base de datos a nuestra base de datos de PostgreSQL usando la secuencia de comandos de administración:

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

      Cree un usuario administrativo para el proyecto escribiendo lo siguiente:

      • ~/myprojectdir/manage.py createsuperuser

      Deberá seleccionar el nombre de usuario, proporcionar una dirección de correo electrónico y elegir y confirmar una contraseña.

      Podemos recolectar todo el contenido estático en la ubicación del directorio que configuramos escribiendo lo siguiente:

      • ~/myprojectdir/manage.py collectstatic

      Deberá confirmar la operación. Luego, los archivos estáticos se ubicarán en un directorio llamado static, dentro del directorio de su proyecto.

      Si siguió la guía de configuración inicial para servidores, debería proteger su servidor con un firewall UFW. Para probar el servidor de desarrollo, tendremos que permitir el acceso al puerto que usaremos.

      Cree una excepción para el puerto 8000 escribiendo lo siguiente:

      Por último, puede probar su proyecto iniciando el servidor de desarrollo de Django con este comando:

      • ~/myprojectdir/manage.py runserver 0.0.0.0:8000

      En su buscador web, agregue :8000 al final del nombre del dominio o de la dirección IP de su servidor y visítelos:

      http://server_domain_or_IP:8000
      

      Debe obtener como resultado la página de índice predeterminada de Django:

      Página de índice de Django

      Si agrega /admin al final de la URL en la barra de direcciones, se le solicitará el nombre de usuario administrativo y la contraseña que creó con el comando createsuperuser:

      Inicio de sesión de administrador en Django

      Después de la autenticación, puede acceder a la interfaz administrativa predeterminada de Django:

      Interfaz de administración de Django

      Cuando finalice la exploración, presione CTRL-C en la ventana de la terminal para desactivar el servidor de desarrollo.

      Poner a prueba la capacidad de Gunicorn para presentar el proyecto

      Lo último que nos convendrá hacer antes de cerrar nuestro entorno virtual será probar Gunicorn para asegurarnos de que pueda hacer funcionar la aplicación. Podemos hacerlo ingresando a nuestro directorio de proyectos y usando gunicorn para cargar el módulo WSGI del proyecto:

      • cd ~/myprojectdir
      • gunicorn --bind 0.0.0.0:8000 myproject.wsgi

      Con esto se iniciará Gunicorn en la misma interfaz en la que se encontraba en ejecución el servidor de desarrollo en Django. Puede volver y probar la aplicación de nuevo.

      Nota: No se aplicará ninguno de los estilos a la interfaz de administrador, ya que Gunicorn no sabe cómo encontrar el contenido estático de CSS responsable de esto.

      Pasamos un módulo a Gunicorn especificando la ruta relativa del directorio al archivo wsgi.py de Django, que es el punto de entrada a nuestra aplicación, usando la sintaxis del módulo de Python. Dentro de este archivo, se define una función llamada application, que se usa para establecer conexión con la aplicación. Para obtener más información sobre la especificación WSGI, haga clic aquí.

      Cuando termine de realizar las pruebas, presione CTRL-C en la ventana de la terminal para detener Gunicorn.

      Con esto habremos terminado de configurar nuestra aplicación en Django. Podemos cerrar nuestro entorno virtual escribiendo lo siguiente:

      Se eliminará el indicador del entorno virtual en su línea de comandos.

      Crear archivos de socket y servicio de systemd para Gunicorn

      Comprobamos que Gunicorn puede interactuar con nuestra aplicación en Django, pero debemos implementar un mejor método para iniciar y detener el servidor de la aplicación. Para lograr esto, crearemos archivos de servicio y socket systemd.

      El socket Gunicorn se creará en el inicio y escuchará las conexiones. Cuando se establezca una conexión, systemd iniciará de forma automática el proceso de Gunicorn para manejarla conexión.

      Comience por crear y abrir un archivo de socket de systemd para Gunicorn con privilegios sudo:

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

      En su interior, crearemos una sección [Unit] para describir el socket, una sección [Socket] para definir la ubicación del socket y una sección [Install] para asegurarnos de que el socket se cree en el momento adecuado:

      /etc/systemd/system/gunicorn.socket

      [Unit]
      Description=gunicorn socket
      
      [Socket]
      ListenStream=/run/gunicorn.sock
      
      [Install]
      WantedBy=sockets.target
      

      Guarde y cierre el archivo cuando termine.

      A continuación, cree y abra un archivo de servicio systemd para Gunicorn con privilegios sudo en su editor de texto. El nombre del archivo de servicio debe coincidir con el de socket, salvo en la extensión:

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

      Empiece por la sección [Unit], que se usa para especificar metadatos y dependencias. Aquí introduciremos una descripción de nuestro servicio e indicaremos al sistema init que lo inicie solo tras haber alcanzado el objetivo de red: Debido a que nuestro servicio se basa en el socket del archivo de sockets, necesitamos incluir una directiva Requires para indicar esta relación:

      /etc/systemd/system/gunicorn.service

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

      A continuación, abriremos la sección [Service]. Especificaremos el usuario y el grupo con los cuales deseamos que se ejecute el proceso. Otorgaremos la propiedad del proceso a nuestra cuenta de usuario normal, ya que tiene la propiedad de todos los archivos pertinentes. Otorgaremos la propiedad del grupo al grupo www-data para que Nginx pueda comunicarse fácilmente con Gunicorn.

      Luego, mapearemos el directorio de trabajo y especificaremos el comando que se usará para iniciar el servicio. En este caso, tendremos que especificar la ruta completa al ejecutable de Gunicorn, que está instalado en nuestro entorno virtual. Vincularemos el proceso con el socket de Unix que creamos en el directorio /run para que el proceso pueda comunicarse con Nginx. Registramos todos los datos a la salida estándar para que el proceso journald pueda recopilar los registros de Gunicorn. También podemos especificar cualquier ajuste opcional de Gunicorn aquí. Por ejemplo, especificamos 3 procesos de trabajadores en este caso:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      

      Por último, agregaremos una sección [Install]. Esto indicará a systemd a qué deberá vincular este servicio si lo habilitamos para que se cargue en el inicio. Queremos que este servicio se inicie cuando el sistema multiusuario normal esté en funcionamiento:

      /etc/systemd/system/gunicorn.service

      [Unit]
      Description=gunicorn daemon
      Requires=gunicorn.socket
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myprojectdir
      ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn 
                --access-logfile - 
                --workers 3 
                --bind unix:/run/gunicorn.sock 
                myproject.wsgi:application
      
      [Install]
      WantedBy=multi-user.target
      

      Con eso, nuestro archivo de servicio systemd quedará completo. Guárdelo y ciérrelo ahora.

      Ahora podemos iniciar y habilitar el socket de Gunicorn. Con esto, ahora, se creará el archivo de socket en /run/gunicorn.sock y en el inicio. Cuando se establezca una conexión con ese socket, systemd iniciará gunicorn.service de forma automática para gestionarla:

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

      Podemos confirmar que la operación se haya completado con éxito revisando el archivo de sockets.

      Verificar el archivo de socket de Gunicorn

      Compruebe el estado del proceso para saber si pudo iniciar lo siguiente:

      • sudo systemctl status gunicorn.socket

      Debería obtener un resultado como este:

      Output

      ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

      A continuación, compruebe la existencia del archivo gunicorn.sock en el directorio /run:

      Output

      /run/gunicorn.sock: socket

      Si el comando systemctl status indica que se produjo un error o si no encuentra el archivo gunicorn.sock en el directorio, significa que no se pudo crear de forma correcta el socket de Gunicorn. Verifique los registros del socket de Gunicorn escribiendo lo siguiente:

      • sudo journalctl -u gunicorn.socket

      Vuelva a revisar su archivo /etc/systemd/system/gunicorn.socket para solucionar cualquier problema antes de continuar.

      Poner a prueba la activación de sockets

      En este punto, si solo inició la unidad gunicorn.socket, gunicorn.service aún no estará activo, ya que el socket aún no habrá recibido conexiones. Puede comprobarlo escribiendo lo siguiente:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

      Para probar el mecanismo de activación de sockets, podemos enviar una conexión al socket a través de curl escribiendo lo siguiente:

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

      Debería recibir el resultado HTML de su aplicación en la terminal. Esto indica que Gunicorn se inició y pudo presentar su aplicación de Django. Puede verificar que el servicio de Gunicorn funcione escribiendo lo siguiente:

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

      Si el resultado de curl o systemctl status indica que se produjo un problema, verifique los registros para obtener información adicional:

      • sudo journalctl -u gunicorn

      Verifique su archivo /etc/systemd/system/gunicorn.service en busca de problemas. Si realiza cambios en el archivo /etc/systemd/system/gunicorn.service, vuelva a cargar el demonio para volver a leer la definición de servicio y reiniciar el proceso de Gunicorn escribiendo lo siguiente:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn

      Asegúrese de resolver los problemas mencionados previamente antes de continuar.

      Configurar Nginx para un pase de autorización a Gunicorn

      Ahora que Gunicorn está configurado, debemos configurar Nginx para transferir tráfico al proceso.

      Comience por crear y abrir un nuevo bloque de servidor en el directorio sites-available de Nginx:

      • sudo nano /etc/nginx/sites-available/myproject

      Dentro de este, abra un nuevo bloque de servidor. Comenzaremos especificando que este bloque debe escuchar en el puerto normal 80 y responder al nombre de dominio o a la dirección IP de nuestro servidor:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      }
      

      A continuación, indicaremos a Nginx que ignore cualquier problema para encontrar un favicon. También le indicaremos dónde encontrar los activos estáticos que recolectamos en nuestro directorio ~/myprojectdir/static. Todos estos archivos tienen un prefijo URI de “/static”, para que podamos crear un bloque de ubicación que coincida con estas solicitudes:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      }
      

      Por último, crearemos un bloque location / {} para que coincida con todas las demás solicitudes. Dentro de esta ubicación, agregaremos el archivo proxy_params estándar incluido con la instalación de Nginx y, luego, transferiremos el tráfico directamente al socket de Gunicorn:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name server_domain_or_IP;
      
          location = /favicon.ico { access_log off; log_not_found off; }
          location /static/ {
              root /home/sammy/myprojectdir;
          }
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/run/gunicorn.sock;
          }
      }
      

      Guarde y cierre el archivo cuando termine. Ahora, podemos habilitar el archivo vinculándolo al directorio sites-enabled:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Pruebe su configuración de Nginx para descartar errores de sintaxis escribiendo lo siguiente:

      Si no se notifican errores, reinicie Nginx escribiendo lo siguiente:

      • sudo systemctl restart nginx

      Por último, debemos abrir nuestro firewall al tráfico normal en el puerto 80. Como ya no necesitamos acceso al servidor de desarrollo, podemos eliminar la regla para abrir también el puerto 8000:

      • sudo ufw delete allow 8000
      • sudo ufw allow 'Nginx Full'

      Ahora debería poder acceder al dominio o a la dirección IP de su servidor para ver su aplicación.

      Nota: Después de configurar Nginx, el siguiente paso debería ser proteger el tráfico hacia el servidor usando SSL/TLS. Esto es importante porque, si no se aplica, toda la información, incluidas las contraseñas, se envía a través de la red en texto simple.

      Si tiene un nombre de dominio, la alternativa más sencilla para obtener un certificado SSL para proteger su tráfico es usar Let’s Encrypt. Siga esta guía para configurar Let’s Encrypt con Nginx en Ubuntu 20.04. Siga el procedimiento usando el bloque de servidor de Nginx que creamos en esta guía.

      Resolver problemas en Nginx y Gunicorn

      Si con este último paso no se muestra su aplicación, deberá resolver problemas en su instalación.

      Nginx muestra la página predeterminada en lugar de la aplicación de Django

      Si Nginx muestra la página predeterminada en lugar de actualizar su aplicación, normalmente significa que deberá ajustar server_name dentro del archivo /etc/nginx/sites-available/myproject para apuntar a la dirección IP o al nombre de dominio de su servidor.

      Nginx usa el server_name para determinar el bloque de servidor que usará para responder a solicitudes. Si ve la página predeterminada de Nginx, significa que Nginx no pudo hacer coincidir la solicitud con un bloque de servidor de forma explícita, por lo cual sigue recurriendo al bloque por defecto definido en /etc/nginx/sites-available/default.

      El server_name del bloque de servidor de su proyecto debe ser más específico que el del bloque de servidor predeterminado que se seleccionará.

      Nginx muestra un error de puerta de enlace 502 en lugar de la aplicación de Django

      Un error 502 indica que Nginx no puede autorizar con éxito la solicitud. Con el error 502 se transmite una amplia variedad de problemas de configuración, por lo que se necesita más información para resolver los problemas de forma adecuada.

      Los registros de errores de Nginx son el recurso principal para buscar más información. Generalmente, esto le indicará las condiciones que ocasionaron problemas durante el evento de autorización. Siga los registros de errores de Nginx escribiendo lo siguiente:

      • sudo tail -F /var/log/nginx/error.log

      Ahora, realice otra solicitud en su navegador para generar un nuevo error (intente actualizar la página). Debería recibir un mensaje de error nuevo en el registro. Leer el mensaje lo ayudará a determinar el problema.

      Es probable que reciba el siguiente mensaje:

      connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

      Esto indica que Nginx no pudo encontrar el archivo gunicorn.sock en la ubicación en cuestión. Debería comparar la ubicación de proxy_pass definida en el archivo /etc/nginx/sites-available/myproject con la ubicación actual del archivo gunicorn.sock generado por la unidad de systemd gunicorn.sock.

      Si no puede encontrar un archivo gunicorn.sock en el directorio /run, por lo general significa que el archivo de socket de systemd no pudo crearlo. Regrese a la sección de verificación del archivo de socket de Gunicorn para seguir los pasos de resolución de problemas de Gunicorn.

      connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

      Esto indica que Nginx no pudo conectarse al socket de Gunicorn debido a problemas de permisos. Esto puede ocurrir cuando se sigue el procedimiento con un usuario root en lugar de un usuario sudo. Aunque systemd puede crear el archivo de socket de Gunicorn, Nginx no puede acceder a él.

      Esto puede ocurrir si hay permisos limitados en cualquier punto entre el directorio root (/) y el archivo gunicorn.sock. Podemos revisar los permisos y los valores de propiedad del archivo de socket y cada uno de sus directorios principales pasando la ruta absoluta a nuestro archivo de socket al comando namei:

      • namei -l /run/gunicorn.sock

      Output

      f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

      En el resultado se muestran los permisos de cada uno de los componentes del directorio. Al mirar los permisos (primera columna), el propietario (segunda columna) y el propietario del grupo (tercera columna), podemos averiguar el tipo de acceso permitido para el archivo de socket.

      En el ejemplo anterior, el archivo de sockets y cada directorio que conduce a este tienen permisos mundiales de lectura y ejecución (la columna de permisos para los directorios termina en r-x en lugar de ---). El proceso de Nginx debería poder acceder al socket de forma correcta.

      Si algunos directorios que conducen al socket no tienen permiso mundial de lectura y ejecución, Nginx no podrá acceder al socket sin otorgar permisos mundiales de lectura y ejecución ni asegurarse de que se otorgue propiedad del grupo a un grupo del que forme parte Nginx.

      Django muestra el mensaje “could not connect to server: Connection refused”

      Este es uno de los mensajes que puede recibir de Django al intentar acceder a ciertas partes de la aplicación en el navegador web:

      OperationalError at /admin/login/
      could not connect to server: Connection refused
          Is the server running on host "localhost" (127.0.0.1) and accepting
          TCP/IP connections on port 5432?
      

      Esto indica que Django no puede conectarse a la base de datos de Postgres. Asegúrese de que la instancia de Postgres esté en ejecución escribiendo lo siguiente:

      • sudo systemctl status postgresql

      Si esto no sucede, puede iniciarla y activarla para que se cargue automáticamente en el inicio (si aún no está cargada la configuración para ello) escribiendo lo siguiente:

      • sudo systemctl start postgresql
      • sudo systemctl enable postgresql

      Si todavía experimenta problemas, asegúrese de que los ajustes de la base de datos definidos en el archivo ~/myprojectdir/myproject/settings.py sean correctos.

      Solución de problemas adicionales

      Para resolver problemas adicionales, los registros pueden servir para reducir las causas raíces. Verifique cada uno de ellos por separado y busque mensajes que indiquen las áreas problemáticas.

      Los siguientes registros pueden ser útiles:

      • Verifique los registros de proceso de Nginx escribiendo lo siguiente: sudo journalctl -u nginx.
      • Verifique los registros de acceso de Nginx escribiendo lo siguiente: sudo less /var/log/nginx/access.log
      • Verifique los registros de errores de Nginx escribiendo lo siguiente: sudo less /var/log/nginx/error.log.
      • Verifique los registros de la aplicación de Gunicorn escribiendo lo siguiente: sudo journalctl -u gunicorn.
      • Verifique los registros de sockets de Gunicorn escribiendo lo siguiente: sudo journalctl -u gunicorn.socket.

      Cuando actualice su configuración o aplicación, es probable que necesite reiniciar los procesos para que asimilen sus cambios.

      Si actualiza su aplicación de Django, puede reiniciar el proceso de Gunicorn para que incorpore los cambios escribiendo lo siguiente:

      • sudo systemctl restart gunicorn

      Si cambia los archivos de socket y servicio de Gunicorn, vuelva a cargar el demonio y reinicie el proceso escribiendo lo siguiente:

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

      Si cambia la configuración de bloque del servidor de Nginx, pruébela y luego verifique Nginx escribiendo lo siguiente:

      • sudo nginx -t && sudo systemctl restart nginx

      Estos comandos son útiles para incorporar cambios cuando ajusta su configuración.

      Conclusión

      En esta guía, creamos un proyecto de Django en su propio entorno virtual. Configuramos Gunicorn para que traduzca las solicitudes de los clientes a fin de que Django pueda manejarlas. Posteriormente, configuramos Nginx para que actúe como proxy inverso a fin de manejar las conexiones de los clientes y presentar el proyecto correcto según la solicitud del cliente.

      Django simplifica la creación de proyectos y aplicaciones proporcionando muchas de las piezas comunes, lo que le permite centrarse en los elementos únicos. Al aprovechar la cadena general de herramientas descrita en este artículo, puede ofrecer fácilmente las aplicaciones que cree desde un servidor único.



      Source link