• en
  • Langue : fr
  • dev
  • Version de la documentation : 1.8

Comment utiliser Django avec FastCGI, SCGI ou AJP

Obsolète depuis la version 1.7: La prise en charge de FastCGI est obsolète et sera supprimée dans Django 1.9.

Bien que WSGI soit la plateforme de déploiement de préférence pour Django, beaucoup utilisent des hébergeurs mutualisés sur lesquels des protocoles tels que FastCGI, SCGI ou AJP sont les seules options viables.

Note

Ce document se concentre sur FastCGI. D’autres protocoles, tels que SCGI et AJP, sont également supportés par le biais du paquet Python flup. Voir la section Protocoles ci-dessous pour les détails concernant SCGI et AJP.

Fondamentalement, FastCGI est un moyen efficace de permettre à des applications externes de servir des pages à un serveur web. Le serveur web délègue les requêtes web entrantes (via une socket) à FastCGI, qui exécute le code et retourne une réponse au serveur web qui, à son tour, transmet cette réponse en réponse au navigateur web du client.

À l’instar de WSGI, FastCGI permet de garder le code en mémoire, permettant ainsi de servir les requêtes sans délai de démarrage. Alors que p. ex. mod_wsgi peut être configuré comme processus intégré au processus du serveur web Apache ou comme daemon, un processus FastCGI ne s’exécute jamais à l’intérieur du processus du serveur web, toujours comme processus séparé et persistant.

Pourquoi exécuter le code dans un processus séparé ?

Les configurations traditionnelles mod_* d’Apache incorporent divers langages de script (plus particulièrement PHP, Python et Perl) à l’intérieur de l’espace du processus du serveur Web. Bien que cela réduise le temps de démarrage car le code ne doit pas être rechargé depuis le disque à chaque requête, cette optimisation se fait aux dépends d’une plus grande quantité de mémoire utilisée.

En raison de la nature de FastCGI, il est même possible d’avoir des processus lancés avec un compte utilisateur différent de celui du processus du serveur Web. C’est un bénéfice de sécurité bienvenu sur les systèmes partagés, car cela permet de protéger votre code de l’accès par d’autres utilisateurs.

Prérequis : flup

Avant de pouvoir vous servir de FastCGI avec Django, il vous faut installer flup, une bibliothèque Python permettant d’interagir avec FastCGI. La version 0.5 ou plus récente devrait fonctionner.

Démarrer votre serveur FastCGI

FastCGI fonctionne sur un modèle client-serveur, et dans la majorité des cas vous démarrez le processus FastCGI vous-même. Votre serveur web (que ce soit Apache, lighttpd ou autre) ne contacte votre processus Django-FastCGI que lorsque le serveur demande à charger une page dynamique. Par le fait que le daemon tourne déjà avec le code en mémoire, il peut ainsi servir la réponse très rapidement.

Note

Si le système que vous utilisez est partagé, vous serez probablement forcé d’utiliser des processus FastCGI gérés par le serveur Web. Consultez la section ci-dessous sur le fonctionnement de Django avec des processus gérés par le serveur Web pour obtenir plus d’informations.

Un serveur Web peut se connecter à un serveur FastCGI de deux façons : soit en utilisant un socket de domaine Unix (un « tuyau nommé » sur les systèmes Win32), soit en utilisant un socket TCP. Ce choix est une question de préférence ; un socket TCP est généralement plus simple au niveau des permissions.

Pour démarrer votre serveur, placez-vous d’abord dans le répertoire de votre projet (à l’endroit où manage.py se trouve) et lancez la commande runfcgi:

./manage.py runfcgi [options]

Si vous indiquez help comme unique option après runfcgi, vous verrez apparaître la liste de toutes les options disponibles.

Vous devez indiquez soit l’option socket, soit l’option protocol ou encore les deux options host and port. Puis, lors de la configuration du serveur Web, il suffira de lui indiquer le couple hôte/port ou le socket défini lors du démarrage du serveur FastCGI. Consultez les exemples ci-dessous.

Protocoles

Django prend en charge tous les protocoles gérés par flup, notamment fastcgi, SCGI et AJP1.3 (le protocole Apache JServ, version 1.3). Choisissez votre protocole préféré en utilisant l’option protocol=<nom_du_protocole> avec ./manage.py runfcgi, où <nom_du_protocole> peut être : fcgi (valeur par défaut), scgi ou ajp. Par exemple :

./manage.py runfcgi protocol=scgi

Exemples

Lancement d’un serveur en mode « threaded » sur un port TCP :

./manage.py runfcgi method=threaded host=127.0.0.1 port=3033

Lancement d’un serveur en mode « prefork » sur un socket de domaine Unix :

./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid

Sécurité des connecteurs

La valeur umask par défaut de Django nécessite que le serveur Web et le processus FastCGI Django soient lancés avec le même groupe et le même utilisateur. Pour plus de sécurité, vous pouvez les lancer avec le même groupe, mais avec différents utilisateurs. Si vous faites cela, vous devez définir la valeur umask à 0002 en utilisant l’option umask de runfcgi.

Lancement sans la mise en arrière-plan du processus (utile pour le débogage) :

./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1

Arrêt du démon FastCGI

Si le processus est lancé au premier plan, il est très simple de l’arrêter : il suffit de saisir Ctrl-C et le serveur FastCGI s’arrête et quitte. Cependant, lorsque vous avez affaire à des processus en arrière-plan, vous devez faire appel à la commande Unix kill.

Si l’option pidfile a été indiquée au lancement de runfcgi, le processus FastCGI peut être arrêté comme ceci :

kill `cat $PIDFILE`

...où $PIDFILE correspond à l’option pidfile que vous avez indiquée.

Pour relancer facilement le démon FastCGI sous Unix, essayez ce petit script shell :

#!/bin/bash

# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"

cd $PROJDIR
if [ -f $PIDFILE ]; then
    kill `cat -- $PIDFILE`
    rm -f -- $PIDFILE
fi

exec /usr/bin/env - \
  PYTHONPATH="../python:.." \
  ./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE

Configuration Apache

Pour utiliser Django avec Apache et FastCGI, le serveur Apache doit être installé et configuré avec le module mod_fastcgi activé. Consultez la documentation d’Apache pour les instructions.

Une fois que cette partie est faite, indiquez à Apache l’emplacement de l’instance Django FastCGI en modifiant le fichier httpd.conf (configuration Apache). Deux choses sont nécessaires :

  • Utiliser la directive FastCGIExternalServer pour indiquer l’emplacement du serveur FastCGI.

  • Utiliser mod_rewrite pour faire pointer convenablement les URL sur l’instance FastCGI.

Indication de l’emplacement du serveur FastCGI

La directive FastCGIExternalServer indique à Apache comment trouver votre serveur FastCGI. Comme l’explique la documentation de FastCGIExternalServer, vous pouvez indiquer un socket ou un host. Voici des exemples pour les deux cas :

# Connect to FastCGI via a socket / named pipe.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock

# Connect to FastCGI via a TCP host/port.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033

Dans chaque cas, le fichier /home/user/public_html/mysite.fcgi n’a pas besoin d’exister réellement. Ce n’est qu’une URL utilisée en interne par le serveur Web, un point d’accrochage pour indiquer les requêtes d’URL devant être traitées par FastCGI (la prochaine section en dit plus sur ce sujet).

Utilisation de mod_rewrite pour diriger les URL vers FastCGI

La seconde étape est d’indiquer à Apache d’utiliser FastCGI pour les URL correspondant à un certain motif. Pour cela, utilisez le module mod_rewrite et redirigez les URL vers mysite.fcgi (ou toute autre valeur indiquée dans la directive FastCGIExternalServer, comme expliqué dans la section précédente).

Dans cet exemple, nous demandons à Apache d’utiliser FastCGI pour traiter les requêtes qui ne représentent pas de fichier sur le système de fichiers et qui ne commencent pas par /media/. C’est probablement le cas le plus courant si vous utilisez le site d’administration de Django :

<VirtualHost 12.34.56.78>
  ServerName example.com
  DocumentRoot /home/user/public_html
  Alias /media /home/user/python/django/contrib/admin/media
  RewriteEngine On
  RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</VirtualHost>

Django utilise automatiquement la version non réécrite de l’URL lors de la construction des URL à l’aide de la balise de gabarit {% url %} (ou d’autres méthodes similaires).

Utilisation de mod_fcgid comme alternative à

Une autre façon de servir des applications par FastCGI est d’utiliser le module mod_fcgid d’Apache. Comparé à mod_fastcgi, mod_fcgid traite différemment les applications FastCGI dans la mesure où il s’occupe lui-même de la génération des processus de travail et ne propose donc pas de configuration semblable à FastCGIExternalServer. Cela signifie que la configuration est un peu différente.

En pratique, vous devez suivre la voie de l’ajout d’un gestionnaire de script un peu comme ce qui est décrit plus loin concernant le fonctionnement de Django dans un environnement d’hébergement partagé. Pour plus de détails, consultez la référence de mod_fcgid.

Configuration

lighttpd est un serveur Web léger utilisé couramment pour servir des fichiers statiques. Il prend nativement en charge FastCGI, c’est donc un bon choix pour servir à la fois des pages statiques et des pages dynamiques, tant que votre site n’a pas d’exigences spécifiques à Apache.

Vérifiez que mod_fastcgi est présent dans la liste des modules, quelque part après mod_rewrite et mod_access, mais pas après mod_accesslog. Il est probable que mod_alias soit aussi nécessaire pour servir les fichiers statiques de l’administration.

Ajoutez ce qui suit dans votre fichier de configuration lighttpd :

server.document-root = "/home/user/public_html"
fastcgi.server = (
    "/mysite.fcgi" => (
        "main" => (
            # Use host / port instead of socket for TCP fastcgi
            # "host" => "127.0.0.1",
            # "port" => 3033,
            "socket" => "/home/user/mysite.sock",
            "check-local" => "disable",
        )
    ),
)
alias.url = (
    "/media" => "/home/user/django/contrib/admin/media/",
)

url.rewrite-once = (
    "^(/media.*)$" => "$1",
    "^/favicon\.ico$" => "/media/favicon.ico",
    "^(/.*)$" => "/mysite.fcgi$1",
)

Plusieurs sites Django avec un seul

lighttpd permet d’utiliser une « configuration conditionnelle » pour pouvoir personnaliser la configuration pour chaque hôte. Afin d’indiquer plusieurs sites FastCGI, il suffit d’entourer la configuration FastCGI de chaque site par un bloc conditionnel :

# If the hostname is 'www.example1.com'...
$HTTP["host"] == "www.example1.com" {
    server.document-root = "/foo/site1"
    fastcgi.server = (
       ...
    )
    ...
}

# If the hostname is 'www.example2.com'...
$HTTP["host"] == "www.example2.com" {
    server.document-root = "/foo/site2"
    fastcgi.server = (
       ...
    )
    ...
}

Vous pouvez également faire fonctionner plusieurs installations de Django sur le même site en indiquant simplement plusieurs lignes dans la directive fastcgi.server. Ajoutez un hôte FastCGI pour chaque instance.

Configuration Cherokee

Cherokee est un serveur Web très rapide, souple et simple à configurer. Il prend en charge les technologies répandues actuellement : FastCGI, SCGI, PHP, CGI, SSI, les connexions chiffrées TLS et SSL, les hôtes virtuels, l’authentification, le codage à la volée, la répartition de charge, les fichiers journaux compatibles Apache, la répartition entre bases de données, les proxys HTTP inverses et bien plus encore.

Le projet Cherokee fournit une documentation sur la configuration de Django avec Cherokee.

Django dans un environnement d’hébergement partagé avec Apache

Bien des fournisseurs d’hébergement partagé n’autorisent pas le lancement de ses propres processus serveur ni la modification du fichier httpd.conf. Dans ces situations, il est tout de même possible de faire fonctionner Django en utilisant des processus générés par le serveur Web.

Note

Si vous utilisez des processus générés par le serveur Web, comme expliqué dans cette section, il n’est pas nécessaire de lancer soi-même un serveur FastCGI. Apache génère un certain nombre de processus en adaptant leur nombre au besoin.

Dans le répertoire Web racine, ajoutez ceci dans un fichier nommé .htaccess:

AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

Puis, créez un petit script indiquant à Apache comment provoquer le lancement du programme FastCGI. Créez un fichier mysite.fcgi et placez-le dans votre répertoire Web en vous assurant de le rendre exécutable :

#!/usr/bin/python
import sys, os

# Add a custom Python path.
sys.path.insert(0, "/home/user/python")

# Switch to the directory of your project. (Optional.)
# os.chdir("/home/user/myproject")

# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"

from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")

Cela fonctionne si votre serveur utilise mod_fastcgi. Si vous utilisez plutôt mod_fcgid, la configuration est presque identique à l’exception d’une petite modification dans le fichier .htaccess. Au lieu d’ajouter un gestionnaire de script fastcgi, vous devez ajouter un gestionnaire fcgid-script :

AddHandler fcgid-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

Redémarrage du serveur FastCGI

Si vous modifiez du code Python de votre site, il est nécessaire d’indiquer à FastCGI que le code a changé. Il n’y a cependant pas besoin de relancer Apache dans ce cas. Il suffit de renvoyer le fichier mysite.fcgi ou de le modifier pour changer l’horodatage du fichier. Lorsque Apache constate que le fichier a été mis à jour, il redémarrera l’application Django pour vous.

Si vous avez accès à une console sur un système Unix, vous pouvez accomplir cela facilement en employant la commande touch:

touch mysite.fcgi

Service des fichiers statiques de l’interface d’administration

Indépendamment du serveur et de la configuration que vous aurez finalement choisi de mettre en œuvre, il sera aussi nécessaire de réfléchir à la façon de servir les fichiers statiques de l’interface d’administration. Le conseil donné dans la documentation de mod_wsgi s’applique également dans les configurations décrites ci-dessus.

Contrainte du préfixe d’URL à une valeur particulière

Comme beaucoup de ces solutions basées sur FastCGI nécessitent la réécriture des URL à un moment ou un autre au niveau du serveur Web, l’information du chemin vue par Django peut ne plus ressembler à l’URL originale qui a été demandée. Cela peut être un problème si l’application Django est servie sous un préfixe particulier et que vous vouliez que les URL produites par la balise {% url %} contiennent le préfixe, au contraire de la version réécrite qui pourrait par exemple contenir

Django tente vraiment de déterminer le préfixe du nom de script réel tel qu’il devrait être. En particulier, si le serveur Web définit la variable SCRIPT_URL (spécifique au module mod_rewrite d’Apache) ou REDIRECT_URL (définie par quelques serveurs, y compris Apache/mod_rewrite dans certaines situations), Django détermine automatiquement le préfixe original.

Dans les cas où Django n’a pas la possibilité de déterminer correctement le préfixe et où vous souhaitez que la valeur originale soit utilisée dans les URL, vous pouvez définir le réglage FORCE_SCRIPT_NAME dans votre fichier settings principal. Cela définit uniformément le nom du script pour toutes les URL servies par l’intermédiaire de ce fichier de réglages. Il sera donc nécessaire d’utiliser des fichiers de réglages différents si vous souhaitez différents ensembles d’URL avec des noms de script différents, mais cette situation est rare.

Comme exemple concret, si votre configuration Django sert toutes les URL sous '/' et que vous souhaitiez utiliser ce réglage, vous définiriez FORCE_SCRIPT_NAME = '' dans votre fichier de réglages.

Back to Top