Django - provoz aplikace na serveru

Django je webový framework v jazyce Python, který je oceňován zejména díky možnosti rychlého vývoje. Ti, co neprogramují weby pro obživu ani jako koníček (jako třeba já), navíc ocenění, že jsou ušetřeni znovuvymýšlení kola. :) Zde je nástřel, jak může vypadat jedna z variant serveru, na kterém django aplikace provozovat.

Použité technologie:

  • gunicorn - Python WSGI HTTP Server
  • nginx - HTTP server a reverzní proxy
  • virtualenv - nástroj na vytváření izolavaných Python environments
  • pip - nástroj na instalaci a managování Python balíčků

Jak je vidět, v seznamu není apache ani mod_python, tento sw nebude vůbec použit. Jako výdejový server poslouží nginx. Bude se starat o vydávání statického obsahu (obrázky, styly atd.) a požadavek na dynamický obsah bude proxovat na aplikační server. Takováto role se nazývá reverzní proxy.
Aplikační server (meta server), poběží na jiném portu a pouze na localhostu, tzn. nebude nijak přístupný zvenčí. Jako meta server použijeme gunicorn.

Příprava prostředí

Budeme používat systém izolovaných Python prostředí, který jsem podrobněji popsal v textu o virtualenv. Uvedený příklad bude předpokládat, že djangovský projekt i virtual environment umístíme do adresáře /www. Předpokládám, že každý si nakonec zvolí svůj způsob organizace projektů na filesystému serveru.

Takže vytvoříme nové virtuální prostředí a přepneme se do něho:

cd /www
virtualenv --no-site-packages .virtualenv
source /www/.virtualenv/bin/activate

Instalace

Django a další potřebné pythoní balíčky nainstalujeme pipem (pokud pip nemáme, je potřeba ho před tím v systému doinstalovat):

pip install django pysqlite

Vytvoření projektu

Stále se nacházíme v adresáři /www. Vytvoříme nový django projekt...

django-admin.py startproject hello

... nastavíme setting.py, přidáme svoji aplikaci, atd. Kdo ještě napsaného nic nemá, tak doporučuji nepokračovat a začít podle tohoto návodu někde u sebe na stanici. :) Nebo zkusit rozjet něco hotového, například blog systém Mezzanine podle autorova quick startu je pěkný příklad.

Otestujeme, zda všechno funguje. Zatím ještě pod jednoduchým vestavěným vývojovým serverem.

cd hello
python manage.py runserver 0.0.0.0:8000

Gunicorn

Díky výše použitému vývojovému serveru je možné okamžitě vyvíjet. Nemusíme se sice starat o jeho konfiguraci, ale pro produkční použití je poměrně nevhodný, viz. dokumentace.

V produkci se používá asi nejčastějí apache, ale v našem případě sáhneme po něčem jiném. Gunicorn je Python WSGI HTTP Server pro UNIX, který Django podporuje nativně. Je postaven na pre-fork modelu s automatickým process managementem, je celkem rychlý a nenáročný na prostředky.
Nainstalujeme ho stejně jako jiné Python balíky:

pip install gunicorn

Díky připravenému skriptu je spuštění jednoduché. Opět v adresáři /www/hello:

gunicorn_django -b 0.0.0.0:8000

Na url http://adresa_serveru:8000 by server měl vydávat obsah. Ale bez stylů a ostatních statických prvků (ty budeme vydávat nginxem - viz. dále).
Pro produkční použití je potřeba ještě doplnit některé parametry a zajistit automatické spouštění po bootu. To se bude lišit v každé distribuci, takže není možné to zde popsat konkrétně. Stručně řečeno, je potřeba si v systému vytvořit init skript, ve kterém se správně nastaví virtual environment a gunicorn se spustí se správnými parametry. Inspirace, jak by to uvnitř init skriptu mohlo vypadat, je v příkladu níže. Já osobně na spouštění služeb používám daemontools.

..
APPNAME=hello
BASEDIR=/www
VENVDIR=${BASEDIR}/.virtualenv
APPDIR=${BASEDIR}/${APPNAME}
PIDFILE=${BASEDIR}/tmp/${APPNAME}.pid

HOST=127.0.0.1
PORT=8000
WORKERS=5
USER=www
GROUP=www

source ${VENVDIR}/bin/activate

exec ${VENVDIR}/bin/gunicorn_django \
--pid=${PIDFILE} \
--bind=${HOST}:${PORT} \
--workers=${WORKERS} \
--user=${USER} \
--group=${GROUP} \
--daemon
..

Popis parametrů je dostupný například v nápovědě gunicorn_django --help nebo na webu.

Reverzní proxy

Nginx je ideální volba. Je používán na mnoha velkých projektech, díky vysokému výkonu a nízkým nárokům.
V jeho konfiguráku si založíme sekci (virtual host) pro svůj projekt:

server {
        listen          *:80;
        server_name     www.domena.cz;

        access_log      /www/log/hello_access_log main;
        error_log       /www/log/hello_error_log info;

        location ~* ^.+\.(jpg|gif|png|css|txt|js|html) {
                root /www/media/static;
                access_log   off;
                expires      7d;
        }

        location / {
                proxy_pass  http://localhost:8000;
                proxy_redirect  default;
        }
}

Jak je vidět, krom vyjmenovaných statických souborů se vše přeproxuje na aplikační server. Cesta ke statickým souborům (root) by měla pasovat k hodnotě STATIC_URL v souboru settings.py. V případě problémů je potřeba si prohlédnout vydaný html kód a zkontrolovat cesty v odkazech, zda korespondují se skutečností.

Další vytunění proxy je záležitost analýzy očekávaného chování a počtu requestů a následné nastavení workerů a dalších parametrů v sekci http. Viz. dobrá dokumentace. Za zmíňku stojí např. i parametr proxy_set_header a docílení toho, aby v logu aplikačního serveru jako klientova IP adresa nebyla adresa proxy.


Václav Vinklát 31.10.2012

TOPlist