djangofr / docs / howto / deployment / fastcgi.txt

.. _howto-deployment-fastcgi:

=================================================
Comment utiliser Django avec FastCGI, SCGI or AJP
=================================================

La `configuration préférée actuellement`_ est Apache_ avec `mod_python`_.
Toutefois, certains utilisateurs en hébergement mutualisé se voient proposer
les protocoles FastCGI, SCGI ou AJP comme seules options possibles.
Dans certaines offres, ces protocoles peuvent offrir une meilleure sécurité
-- et probablement de meilleures performances -- que mod_python.

.. admonition:: Note

    Ce document se concentre plus particulièrement sur FastCGI. Les autres
    protocoles comme SCGI ou AJP sont également supportés via le paquet
    python ``flup``. Référez-vous à la section "Protocoles" plus bas pour
    les éléments spécifiques à SCGI et AJP.

FastCGI est un moyen efficace de laisser une application externe servir des
pages à un serveur Web. Le serveur Web délègue les requêtes entrantes (via
une socket) à FastCGI. Celui-ci exécute le code et retourne la réponse au
serveur Web. Ce dernier retourne à son tour le résultat au navigateur de
l'internaute.

Avec FastCGI, et tout comme mod_python, le code est chargé en mémoire. Cela
permet aux requêtes d'être traitées sans temps d'initialisation.
Contrairement à mod_python (ou tout comme `mod_perl`_), un process FastCGI
n'est pas exécuté au sein d'un process du serveur Web, c'est un process 
autonome et persistant.

.. _configuration préférée actuellement: ../modpython/
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/

.. admonition:: Pourquoi exécuter du code dans un process distinct ?

    Le fonctionnement habituel des ``mod_*`` des langages de script dans
    Apache (et plus particulièrement PHP, Python et Perl) est de fonctionner
    au sein d'un process de votre serveur Web. Bien que cela réduise le temps
    d'initialisation -- puisque le code n'a pas à être lu à chaque requête --
    cela a un coût au niveau de la mémoire. Par exemple, pour mod_python, chaque
    process Apache contient son propre interpréteur Python, ce qui utilise
    un montant considérable de RAM.

    De part la nature de FastCGI, il est même possible de lancer des process sous
    des comptes utilisateurs différents de celui utilisé par le process du serveur
    Web. C'est très avantageux dans un environnement mutualisé, puisque cela
    signifie que votre code est isolé de celui des autres utilisateurs.

Prérequis : flup
================

Avant de pouvoir utiliser FastCGI avec Django, vous devez installer flup_.
Flup est une bibliothèque python qui gère FastCGI. Une version 0.5 ou supérieure
est recommandée.

.. _flup: http://www.saddi.com/software/flup/

Démarrer votre serveur FastCGI
==============================

FastCGI fonctionne dans un mode client-serveur, et dans la plupart des cas
vous allez démarrer vous-même le process FastCGI. Votre serveur (que ce soit
Apache, lighttpd ou n'importe quel autre serveur) contactera votre process
Django-FastCGI uniquement lorsqu'une page dynamique aura besoin d'être 
chargée. Puisque le service (daemon) est déjà lancé avec le code en mémoire,
il va pouvoir retourner une réponse très rapidement.

.. admonition:: Note

    Si vous êtes sur un environnement mutualisé, vous serez probablement
    obligé d'utiliser les processus FastCGI du serveur Web. Référez-vous à
    la section ci-dessous pour savoir comment utiliser Django dans le cadre
    d'un serveur lancé via des process FastCGI.

Un serveur web peut se connecter à un serveur FastCGI de deux façons : soit en
en utilisant une "domain socket" UNIX (un "named pipe" sur les systèmes Windows),
soit en utilisant une socket TCP. La sélection est une affaire de préférence.
La socket TCP est généralement plus simple à mettre en place au niveau des
permissions.

Pour démarrer le serveur, rendez-vous dans le répertoire racine de votre projet
(là où est situé votre ``manager.py``), et exécutez ``manage.py`` avec l'option 
``runfcgi``::

    ./manage.py runfcgi [options]

Si vous ajoutez ``help`` comme seul paramètre après ``runfcgi``, la liste des
options disponibles sera affichée.

Vous devrez définir soit une ``socket``, un ``protocol`` ou simultanément un ``hôte`
et ``port``. Ensuite, lors du paramétrage du serveur Web, il vous suffit de pointer
sur le couple hôte/port ou sur la socket que vous avez spécifié lorsque vous avez
lancé votre serveur FastCGI.

Protocoles
----------

Django supporte les mêmes protocoles que ceux supportés par flup_, c'est à dire
fastcgi_, `SCGI`_ et `AJP1.3`_ (le protocole Apache JServ, en version 1.3).
Choissisez le protocole de votre choix en utilisant le paramètre 
``protocol=<protocol_name>`` avec ``./manage.py runfcgi``, où 
``<protocole_name>`` est une valeur parmi : ``fcgi`` (par défaut),  ``scgi``
ou ``ajp``. Par exemple::

    ./manage.py runfcgi protocol=scgi

.. _flup: http://www.saddi.com/software/flup/
.. _fastcgi: http://www.fastcgi.com/
.. _SCGI: http://python.ca/scgi/protocol.txt
.. _AJP1.3: http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html

Exemples
--------

Lancer un serveur en mode "thread" sur un port TCP::

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

Lancer un serveur en mode "prefork" sur une "domain socket" Unix::

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

Lancer sans le service en tache de fond (utile pour débugguer)::

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

Arrêter le service (démon) FastCGI
----------------------------------

Si votre process n'est pas en tache de fond, il est aisé de l'arrêter : pressez
les touches ``Ctrl-C`` pour arrêter et éteindre votre serveur FastCGI. Par contre,
en utilisant les process en tâche de fond, vous devez utiliser la commande Unix 
``kill``.

Si vous spécifiez le paramètre ``pidfile`` à ``manage.py runfcgi``, vous pouvez
tuer votre service FastCGI de la façon suivante::

    kill `cat $PIDFILE`

...où ``$PIDFILE`` est le ``pidfile`` que vous avez spécifié.

Pour redémarrer aisément votre service FastCGI sur Unix, essayez ce petit
script::


    #!/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 d'Apache
======================

Pour utiliser Django avec Apache et FastCGI, vous avez besoin qu'Apache soit
installé et configuré avec `mod_fastcgi`_ installé et activé. Consultez la
documentation d'Apache pour plus d'information.

Une fois que cela est en place, pointez Apache sur votre instance Django FastCGI
en éditant le fichier de configuration d'Apache ``httpd.conf``. Vous devez faire
deux choses :

    * Utiliser la directive ``FastCGIExternalServer`` pour indiquer la 
      localisation de votre serveur FastCGI.
    * Utiliser ``mod_rewrite`` pour faire pointer vos urls FastCGI de façon
      appropriée

.. _mod_fastcgi: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html

Indiquer la location de votre serveur FastCGI
---------------------------------------------

La directive ``FastCGIExternalServer`` indique à Apache comment trouver votre 
serveur FastCGI. Comme l'explique la `documentation de FastCGIExternalServer`_,
vous devez indiquer une ``socket`` ou un ``hôte``. Ci-après des exemples::

    # 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 les deux cas, le fichier ``/home/user/public_html/mysite.fcgi`` n'a pas à
exister. C'est juste une URL interne utilisée par le serveur web -- un "hook"
pour indiquer quelles requêtes à une URL donnée doivent être traitées par
FastCGI (Plus de détails à ce sujet dans la section suivante).

.. _documentation de FastCGIExternalServer: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiExternalServer

Utilisation de mod_rewrite pour pointer vos URLs vers votre serveur FastCGI
---------------------------------------------------------------------------

La seconde étape est d'indiquer à Apache d'utiliser FastCGI pour les urls
correspondant à un certain motif. Pour faire ceci, utilisez le module
`mod_rewrite`_ et réécrivez vos URLs vers ``mysite.fcgi`` (ie, ce que vous
avez défini pour la directive ``FastCGIExternalServer``, comme expliqué
précédemment).

Dans cet exemple, nous indiquons à Apache d'utiliser FastCGI pour toutes
les requêtes ne correspondant pas à un fichier sur le système de fichiers
et qui ne commencent pas pas ``/media/``. Il s'agit probablement du cas
le plus courant, si vous utilisez l'interface 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>

.. _mod_rewrite: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html

Django utilisera automatiquement la version avant réécriture de l'URL quand
des URLs sont construites avec le template tag ``{% url %}`` (ou assimilé).

Configuration de lighttpd
=========================

lighttpd est un serveur léger utilisé habituellement pour servir des fichiers
statiques. Il supporte nativement FastCGI, et s'avère donc de fait un bon
choix pour servir à la fois des contenus statiques et dynamiques, si votre
site ne requiert pas explicitement Apache.

Assurez-vous que ``mod_fastcgi`` est dans votre liste de modules, quelque part
après ``mod_rewrite`` et ``mod_access``, mais avant ``mod_accesslog``. Vous
allez également vouloir ``mod_alias`` pour servir les éléments d'interface
d'administration.

Ajoutez ce qui va suive dans votre fichier de configuration de 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",
    )

Héberber plusieurs sites Django sur une instance de lighttpd
------------------------------------------------------------

lighttpd vous permet d'utiliser une "configuration conditionnelle" pour
personnaliser votre configuration par hôte. Pour utiliser plusieurs sites avec
FastCGI, ajoutez le block conditionnel suivant autour de la configuration
FastCGI de chaque site::

    # 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 exécuter plusieurs instances Django sur le même site
en spécifiant simplement plusieurs entrées dans la directive 
``fastcgi.server``. Ajouter une hôte FastCGI pour chacune d'entre-elles.

Héberger un projet Django sur un hébergement mutualisé avec Apache
==================================================================

Beaucoup d'hébergeurs mutualisés ne vous permettent pas d'exécuter vos
propres services ou d'éditer le fichier ``httpd.conf``. Dans ces cas il est
quand même possible d'utiliser Django en utilisant un serveur web qui
gère le lancement des processus FastCGI.

.. admonition:: Note

    Si vous utiliser un serveur web gérant les processus FastCGI, comme
    expliqué dans cette section, vous n'avez pas besoin de démarrer le serveur
    FastCGI de vous-même. Apache va générer un nombre de process, les augmentant
    autant que nécessaire.

Dans votre répertoire racine, ajoutez ceci dans un fichier nommé ``.htaccess`` ::

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

Ensuite, créez un petit script qui dit à Apache de recharger votre programme 
FastCGI. Créez un fichier ``mysite.fcgi`` et placez le dans votre répertoire
web et assurez-vous qu'il soit 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")

Relancer le process fastcgi
---------------------------

Si vous changez le moindre bout de code python sur votre site, vous devez
indiquer à FastCGI que votre code a changé. Pour autant, il n'y a pas besoin
de redémarrer Apache dans ce cas. Préférez plutôt de retransférer votre fichier
``mysite.fcgi`` ou d'éditer ce fichier. Ceci afin que la date du fichier
change. Quand Apache voit que le fichier a été mis à jour, il rechargera votre
application Django.

Si vous avez accès à une console sur un système Unix, vous pouvez le faire 
simplement en utilisant la commande ``touch`` ::

    touch mysite.fcgi

Servir les fichiers media de l'interface d'administration
=========================================================

Quelque soit le serveur et la configuration que vous avez décidé d'utiliser,
vous ne devez pas oublier de penser à servir les fichiers media de l'interface
d'administration. Les conseils donnés dans la documentation de modpython_
est applicable dans les configurations décrites précédemment.

.. _modpython: ../modpython/#serving-the-admin-files

Forcer le préfixe de l'URL à une valeur particulière
====================================================

Puisque beaucoup de solutions basées sur fastcgi requiert une réécriture 
d'URL à un moment ou à un autre au niveau du serveur web, la requête 
que traite finalement Django ne ressemble pas forcément à la requête 
initiale. Cela est un problème si l'application Django concernée fonctionne
avec un préfixe particulier et si vous souhaitez que le tag ``{% url %}``
ressemble au préfixe et non à l'url réécrite, qui peut contenir, par exemple,
``mysite.fcgi``.

Django tente de trouver par lui-même quel est le préfixe réel. En particulier,
si le serveur web fournit une valeur pour ``SCRIPT_URL`` (cas du mod_rewrite
d'Apache) ou ``REDIRECT_URL`` (cas de quelques serveurs, incluant le
mod_rewrite d'Apache dans certaines circonstances), alors Django trouvera le
préfixe initial automatiquement.

Dans les cas où Django ne parvient pas à trouver ce préfixe et que vous
souhaitez utiliser le préfixe initial dans vos urls, vous pouvez définir le
paramètre ``FORCE_SCRIPT_NAME`` dans votre fichier ``settings``. Ainsi fait, 
la valeur est définie uniformément pour toutes les URLs gérées via ce fichier
"settings". Par conséquent, vous devrez avoir différents fichiers "settings"
si vous voulez définir différents cas d'utilisation du préfixe. Notons que
ce dernier cas est assez rare.

Pour illustrer nos propos, if la configuration de votre application Django est
prévue pour gérer toutes les URLs sous ``'/'`` et que vous voulez utiliser ce
paramètre, vous ajouterez ceci dans votre fichier "settings" : 
``FORCE_SCRIPT_NAME = ''``.
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.