Comment configurer Django avec Postgres, Nginx et Gunicorn sur CentOS 7

introduction

Django est un puissant framework Web qui peut vous aider à faire décoller votre application ou votre site Web Python. Django inclut un serveur de développement simplifié pour tester votre code localement, mais pour tout ce qui est légèrement lié à la production, un serveur Web plus sécurisé et plus puissant est requis.

Dans ce guide, nous montrerons comment installer et configurer certains composants sur CentOS 7 afin de prendre en charge et de servir les applications Django. Nous allons configurer une base de données PostgreSQL au lieu d'utiliser la base de données SQLite par défaut. Nous allons configurer le serveur d’applications Gunicorn pour l’interface avec nos applications. Nous allons ensuite configurer Nginx pour inverser le proxy sur Gunicorn, nous donnant ainsi accès à ses fonctionnalités de sécurité et de performances pour servir nos applications.

Prérequis et objectifs

Afin de compléter ce guide, vous devez avoir une nouvelle instance de serveur CentOS 7 avec un utilisateur non root avec les privilègessudo configurés. Vous pouvez apprendre comment configurer cela en parcourant nosinitial server setup guide.

Nous installerons Django dans un environnement virtuel. L'installation de Django dans un environnement spécifique à votre projet permettra à vos projets et à leurs exigences d'être traités séparément.

Une fois que notre base de données et notre application seront opérationnelles, nous installerons et configurerons le serveur d’applications Gunicorn. Cela servira d'interface avec notre application, traduisant les requêtes client en HTTP en appels Python que notre application peut traiter. Nous installerons ensuite Nginx devant Gunicorn pour tirer parti de ses mécanismes de traitement des connexions hautes performances et de ses fonctionnalités de sécurité faciles à mettre en œuvre.

Commençons.

Installer les packages à partir d'EPEL et des référentiels CentOS

Pour commencer le processus, nous allons télécharger et installer tous les éléments dont nous avons besoin à partir des référentiels CentOS. Nous devrons également utiliser le référentiel EPEL, qui contient des packages supplémentaires non inclus dans les référentiels CentOS. Plus tard, nous utiliserons le gestionnaire de packages Pythonpip pour installer des composants supplémentaires.

Tout d’abord, activez le référentiel EPEL afin que nous puissions obtenir les composants dont nous avons besoin:

sudo yum install epel-release

Avec le nouveau référentiel disponible, nous pouvons installer toutes les pièces nécessaires en une seule commande:

sudo yum install python-pip python-devel postgresql-server postgresql-devel postgresql-contrib gcc nginx

Cela installerapip, le gestionnaire de paquets Python. Il installera également le système de base de données PostgreSQL et certaines bibliothèques et autres fichiers dont nous aurons besoin pour interagir avec ce dernier et en tirer parti. Nous avons inclus le compilateur GCC afin quepip puisse créer des logiciels et nous avons installé Nginx pour l'utiliser comme proxy inverse pour notre installation.

Configurer PostgreSQL pour Django

Nous allons nous lancer et configurer PostgreSQL pour notre installation.

Configurer et démarrer PostgreSQL

Pour commencer, nous devons initialiser la base de données PostgreSQL. Nous pouvons le faire en tapant:

sudo postgresql-setup initdb

Une fois la base de données initialisée, vous pouvez démarrer le service PostgreSQL en tapant:

sudo systemctl start postgresql

Une fois la base de données démarrée, nous devons en fait ajuster les valeurs de l’un des fichiers de configuration renseignés. Utilisez votre éditeur et la commandesudo pour ouvrir le fichier maintenant:

sudo nano /var/lib/pgsql/data/pg_hba.conf

Ce fichier est responsable de la configuration des méthodes d'authentification pour le système de base de données. Actuellement, il est configuré pour autoriser les connexions uniquement lorsque l'utilisateur système correspond à l'utilisateur de la base de données. Cela convient pour les tâches de maintenance locales, mais un autre utilisateur de notre instance Django sera configuré avec un mot de passe.

Nous pouvons configurer cela en modifiant les deux ligneshost au bas du fichier. Remplacez la dernière colonne (la méthode d'authentification) parmd5. Cela permettra l'authentification par mot de passe:

. . .

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
#host    all             all             ::1/128                 ident
host    all             all             ::1/128                 md5

Lorsque vous avez terminé, enregistrez et fermez le fichier.

Avec nos nouvelles modifications de configuration, nous devons redémarrer le service. Nous allons également activer PostgreSQL pour qu'il démarre automatiquement au démarrage:

sudo systemctl restart postgresql
sudo systemctl enable postgresql

Créer la base de données et l'utilisateur PostgreSQL

Maintenant que PostgreSQL est opérationnel comme nous le souhaitons, nous pouvons créer une base de données et un utilisateur de base de données pour notre application Django.

Pour travailler localement avec Postgres, il est préférable de passer temporairement à l'utilisateur système depostgres. Faites-le maintenant en tapant:

sudo su - postgres

Lorsque vous travaillez en tant qu'utilisateurpostgres, vous pouvez vous connecter directement à une session interactive PostgreSQL sans autre authentification. Cela est dû à la ligne que nousdidn’t change dans le fichierpg_hba.conf:

psql

Vous recevrez une invite PostgreSQL dans laquelle nous pourrons configurer nos exigences.

Commencez par créer une base de données pour votre projet:

CREATE DATABASE myproject;

Chaque commande doit se terminer par un point-virgule. Vérifiez donc que votre commande se termine par un point si vous rencontrez des problèmes.

Ensuite, créez un utilisateur de base de données pour notre projet. Assurez-vous de sélectionner un mot de passe sécurisé:

CREATE USER myprojectuser WITH PASSWORD 'password';

Maintenant, nous pouvons donner à notre nouvel utilisateur un accès pour administrer notre nouvelle base de données:

GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

Lorsque vous avez terminé, quittez l'invite de PostgreSQL en tapant:

\q

Maintenant, quittez la session shell de l’utilisateurpostgres pour revenir à la session shell de votre utilisateur normal en tapant:

exit

Créer un environnement virtuel Python pour votre projet

Maintenant que notre base de données est prête, nous pouvons commencer à préparer le reste des exigences de notre projet. Nous allons installer nos exigences Python dans un environnement virtuel pour une gestion plus facile.

Pour ce faire, nous devons d'abord accéder à la commandevirtualenv. Nous pouvons l'installer avecpip:

sudo pip install virtualenv

Avecvirtualenv installé, nous pouvons commencer à former notre projet. Créez un répertoire dans lequel vous souhaitez conserver votre projet et déplacez-vous ensuite dans le répertoire:

mkdir ~/myproject
cd ~/myproject

Dans le répertoire du projet, créez un environnement virtuel Python en tapant:

virtualenv myprojectenv

Cela créera un répertoire appelémyprojectenv dans votre répertoiremyproject. À l'intérieur, il installera une version locale de Python et une version locale depip. Nous pouvons l'utiliser pour installer et configurer un environnement Python isolé pour notre projet.

Avant d’installer les exigences Python de notre projet, nous devons activer l’environnement virtuel. Vous pouvez le faire en tapant:

source myprojectenv/bin/activate

Votre invite devrait changer pour indiquer que vous travaillez maintenant dans un environnement virtuel Python. Cela ressemblera à quelque chose comme ceci:(myprojectenv)user@host:~/myproject$.

Avec votre environnement virtuel actif, installez Django, Gunicorn et l'adaptateur PostgreSQLpsycopg2 avec l'instance locale depip:

pip install django gunicorn psycopg2

Créer et configurer un nouveau projet Django

Avec nos composants Python installés, nous pouvons créer les fichiers de projet Django réels.

Créer le projet Django

Comme nous avons déjà un répertoire de projet, nous demanderons à Django d’installer les fichiers ici. Il créera un répertoire de second niveau avec le code réel, ce qui est normal, et placera un script de gestion dans ce répertoire. La clé est le point à la fin qui indique à Django de créer les fichiers dans le répertoire actuel:

django-admin.py startproject myproject .

Ajuster les paramètres du projet

La première chose à faire avec nos fichiers de projet nouvellement créés est d’ajuster les paramètres. Ouvrez le fichier de paramètres dans votre éditeur de texte:

nano myproject/settings.py

Commencez par rechercher la section qui configure l'accès à la base de données. Il commencera parDATABASES. La configuration dans le fichier concerne une base de données SQLite. Nous avons déjà créé une base de données PostgreSQL pour notre projet, nous devons donc ajuster les paramètres.

Modifiez les paramètres avec les informations de votre base de données PostgreSQL. Nous disons à Django d'utiliser l'adaptateurpsycopg2 que nous avons installé avecpip. Nous devons donner le nom de la base de données, le nom d'utilisateur de la base de données, le mot de passe du nom d'utilisateur de la base de données, puis spécifier que la base de données se trouve sur l'ordinateur local. Vous pouvez laisser le paramètrePORT sous forme de chaîne vide:

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

Ensuite, déplacez-vous vers le bas du fichier et ajoutez un paramètre indiquant l'emplacement des fichiers statiques. Cela est nécessaire pour que Nginx puisse gérer les demandes relatives à ces éléments. La ligne suivante indique à Django de les placer dans un répertoire appeléstatic dans le répertoire du projet de base:

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

Enregistrez et fermez le fichier lorsque vous avez terminé.

Terminer la configuration initiale du projet

Maintenant, nous pouvons migrer le schéma de base de données initial vers notre base de données PostgreSQL en utilisant le script de gestion:

cd ~/myproject
./manage.py makemigrations
./manage.py migrate

Créez un utilisateur administratif pour le projet en tapant:

./manage.py createsuperuser

Vous devrez sélectionner un nom d'utilisateur, fournir une adresse électronique, puis choisir et confirmer un mot de passe.

Nous pouvons collecter tout le contenu statique dans l’emplacement du répertoire que nous avons configuré en tapant:

./manage.py collectstatic

Vous devrez confirmer l'opération. Les fichiers statiques seront ensuite placés dans un répertoire appeléstatic dans le répertoire de votre projet.

Enfin, vous pouvez tester votre projet en lançant le serveur de développement Django avec cette commande:

./manage.py runserver 0.0.0.0:8000

Dans votre navigateur Web, accédez au nom de domaine ou à l’adresse IP de votre serveur suivi de:8000:

http://server_domain_or_IP:8000

Vous devriez voir la page d'index par défaut de Django:

Django index page

Si vous ajoutez/admin à la fin de l'URL dans la barre d'adresse, vous serez invité à entrer le nom d'utilisateur et le mot de passe administratifs que vous avez créés avec la commandecreatesuperuser:

Django admin login

Après authentification, vous pouvez accéder à l'interface d'administration par défaut de Django:

Django admin interface

Lorsque vous avez terminé, appuyez sur CTRL-C dans la fenêtre du terminal pour arrêter le serveur de développement.

Tester la capacité de Gunicorn à servir le projet

La dernière chose que nous voulons faire avant de quitter notre environnement virtuel est de tester Gunicorn pour s’assurer qu’il peut servir l’application. Nous pouvons le faire facilement en tapant:

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

Ceci lancera Gunicorn sur la même interface que celle utilisée par le serveur de développement Django. Vous pouvez revenir en arrière et tester à nouveau l'application. Notez que le style ne sera pas appliqué à l'interface d'administration puisque Gunicorn ne connaît pas le contenu statique responsable de cela.

Nous avons transmis à Gunicorn un module en spécifiant le chemin du répertoire relatif au fichierwsgi.py de Django, qui est le point d’entrée de notre application, en utilisant la syntaxe du module de Python. À l'intérieur de ce fichier, une fonction appeléeapplication est définie, qui est utilisée pour communiquer avec l'application. Pour en savoir plus sur la spécification WSGI, cliquez surhere.

Lorsque vous avez terminé les tests, appuyez sur CTRL-C dans la fenêtre du terminal pour arrêter Gunicorn.

Nous avons maintenant fini de configurer notre application Django. Nous pouvons revenir en arrière de notre environnement virtuel en tapant:

deactivate

Créer un fichier de service Gunicorn Systemd

Nous avons testé la capacité de Gunicorn à interagir avec notre application Django, mais nous devrions implémenter une méthode plus robuste de démarrage et d’arrêt du serveur d’applications. Pour ce faire, nous allons créer un fichier de service Systemd.

Créez et ouvrez un fichier de service Systemd pour Gunicorn avec les privilègessudo dans votre éditeur de texte:

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

Commencez par la section[Unit], qui est utilisée pour spécifier les métadonnées et les dépendances. Nous allons mettre ici une description de notre service et dire au système init de ne le démarrer qu’après avoir atteint la cible réseau:

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

Ensuite, nous allons ouvrir la section[Service]. Nous spécifierons l’utilisateur et le groupe sous lesquels nous voulons traiter. Nous allons donner à notre compte utilisateur habituel la propriété du processus puisqu'il possède tous les fichiers pertinents. Nous attribuerons la propriété du groupe d’utilisateurs Nginx afin qu’il puisse communiquer facilement avec Gunicorn.

Nous allons ensuite mapper le répertoire de travail et spécifier la commande à utiliser pour démarrer le service. Dans ce cas, nous devrons spécifier le chemin complet de l’exécutable Gunicorn, qui est installé dans notre environnement virtuel. Nous allons le lier à un socket Unix dans le répertoire du projet puisque Nginx est installé sur le même ordinateur. C'est plus sûr et plus rapide que d'utiliser un port réseau. Nous pouvons également spécifier ici tous les réglages optionnels de Gunicorn. Par exemple, nous avons spécifié 3 processus de travail dans ce cas:

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

[Service]
User=user
Group=nginx
WorkingDirectory=/home/user/myproject
ExecStart=/home/user/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:/home/user/myproject/myproject.sock myproject.wsgi:application

Enfin, nous ajouterons une section[Install]. Cela indiquera à Systemd à quoi lier ce service si nous lui permettons de démarrer au démarrage. Nous voulons que ce service démarre lorsque le système multi-utilisateurs normal est opérationnel:

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

[Service]
User=user
Group=nginx
WorkingDirectory=/home/user/myproject
ExecStart=/home/user/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:/home/user/myproject/myproject.sock myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Avec cela, notre fichier de service Systemd est complet. Enregistrez et fermez-le maintenant.

Nous pouvons maintenant démarrer le service Gunicorn que nous avons créé et l'activer pour qu'il démarre au démarrage:

sudo systemctl start gunicorn
sudo systemctl enable gunicorn

Configurer Nginx to Proxy Pass to Gunicorn

Maintenant que Gunicorn est configuré, nous devons configurer Nginx pour transférer le trafic au processus.

Modifier le fichier de configuration Nginx

Nous pouvons continuer et modifier la configuration du bloc serveur en modifiant le fichier de configuration principal de Nginx:

sudo nano /etc/nginx/nginx.conf

À l'intérieur, ouvrez un nouveau bloc serveur juste au-dessus du bloc serveur déjà présent:

http {
    . . .

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

    server {
    }

    server {
        listen 80 default_server;

        . . .

Nous allons mettre toute la configuration de notre application Django à l'intérieur de ce nouveau bloc. Nous allons commencer par spécifier que ce bloc doit écouter sur le port normal 80 et qu’il doit répondre au nom de domaine ou à l’adresse IP de notre serveur:

server {
    listen 80;
    server_name server_domain_or_IP;
}

Ensuite, nous dirons à Nginx d’ignorer tout problème lié à la recherche d’un favicon. Nous lui indiquerons également où trouver les actifs statiques que nous avons collectés dans notre répertoire~/myproject/static. Tous ces fichiers ont un préfixe d'URI standard «/ static». Nous pouvons donc créer un bloc d'emplacement correspondant à ces demandes:

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/user/myproject;
    }
}

Enfin, nous allons créer un bloclocation / {} pour correspondre à toutes les autres requêtes. À l’intérieur de cet emplacement, nous allons définir des en-têtes HTTP standard pour permettre à Gunicorn d’avoir des informations sur la connexion du client distant. Nous allons ensuite transférer le trafic sur le socket spécifié dans notre fichier d'unité Gunicorn Systemd:

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/user/myproject;
    }

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://unix:/home/user/myproject/myproject.sock;
    }
}

Enregistrez et fermez le fichier lorsque vous avez terminé.

Ajuster l'appartenance au groupe et les autorisations

L'utilisateur denginx doit avoir accès au répertoire de notre application pour pouvoir servir des fichiers statiques, accéder aux fichiers de socket, etc. CentOS verrouille le répertoire personnel de chaque utilisateur de manière très restrictive, nous allons donc ajouter l'utilisateurnginx au groupe de nos utilisateurs afin que nous puissions ensuite ouvrir les autorisations minimales nécessaires pour que cela fonctionne.

Ajoutez l'utilisateurnginx à votre groupe avec la commande suivante. Remplacez lesuser par votre propre nom d'utilisateur dans la commande:

sudo usermod -a -G user nginx

Maintenant, nous pouvons donner à notre groupe d'utilisateurs des autorisations d'exécution sur notre répertoire personnel. Cela permettra au processus Nginx d’entrer et d’accéder au contenu dans:

chmod 710 /home/user

Une fois les autorisations définies, nous pouvons tester notre fichier de configuration Nginx pour rechercher des erreurs de syntaxe:

sudo nginx -t

Si aucune erreur n'est présente, redémarrez le service Nginx en tapant:

sudo systemctl start nginx

Dites au système init de démarrer le serveur Nginx au démarrage en tapant:

sudo systemctl enable nginx

Vous devez maintenant avoir accès à votre application Django dans votre navigateur via le nom de domaine ou l'adresse IP de votre serveur sans spécifier de port.

Conclusion

Dans ce guide, nous avons configuré un projet Django dans son propre environnement virtuel. Nous avons configuré Gunicorn pour traduire les demandes des clients afin que Django puisse les prendre en charge. Ensuite, nous avons configuré Nginx pour qu’il agisse en tant que proxy inverse pour gérer les connexions client et servir le projet approprié en fonction de la demande du client.

Django facilite la création de projets et d'applications en fournissant de nombreux éléments communs, vous permettant de vous concentrer sur des éléments uniques. En exploitant la chaîne d'outils générale décrite dans cet article, vous pouvez facilement desservir les applications que vous créez à partir d'un seul serveur.