Wdrażanie Django z gunicorn i nginx

To szerokie pytanie, ale chciałbym uzyskać kanoniczną odpowiedź. Próbowałem wdrożyć stronę używając gunicorni nginxw Django. Po przeczytaniu mnóstwa samouczków odniosłem sukces, ale nie mogę być pewien, że kroki, które wykonałem, są wystarczająco dobre, aby uruchomić witrynę bez problemów, a może są lepsze sposoby, aby to zrobić. Ta niepewność jest irytująca.

Dlatego szukam bardzo szczegółowej i dobrze wyjaśnionej odpowiedzi dla początkujących. Nie wiem. chcę wyjaśnić za dużo tego, co wiem, a czego Nie wiem, ponieważ może to nieco przekrzywić odpowiedzi, a inni ludzie mogą skorzystać w mniejszym stopniu z twoich odpowiedzi. Jednak niektóre rzeczy, które chciałbym zobaczyć wymienione są:

  • Jaką "konfigurację" widziałeś najlepiej? Użyłem virtualenv i przeniosłem mój projekt Django wewnątrz tego środowiska, jednak widziałem inne ustawienia, w których znajduje się folder dla środowisk wirtualnych i innych dla projekty.

  • Jak mogę skonfigurować rzeczy w sposób, który pozwala na hostowanie kilku witryn na jednym serwerze?

  • Dlaczego niektórzy sugerują użycie gunicorn_django -b 0.0.0.0:8000, a inni sugerują gunicorn_django -b 127.0.0.1:8000? Przetestowałem ten ostatni w instancji Amazon EC2, ale nie zadziałał, podczas gdy ten pierwszy działał bez problemu.

  • Jaka jest logika pliku konfiguracyjnego nginx? Jest tak wiele samouczków używających drastycznie różnych plików konfiguracyjnych, że nie wiem, który z nich jest lepiej. Na przykład niektórzy używają alias /path/to/static/folder, a inni root /path/to/static/folder. Może możesz udostępnić preferowany plik konfiguracyjny.

  • Dlaczego tworzymy dowiązanie symboliczne pomiędzy site-available i sites-enabled w /etc/nginx?

  • Niektóre najlepsze praktyki są jak zawsze mile widziane :-)

Dzięki

Author: JJD, 2012-10-22

4 answers

Jaką" konfigurację " widziałeś najlepiej? Użyłem virtualenv i przeniosłem mój projekt django wewnątrz tego środowiska, jednak widziałem inny konfiguracjach, gdzie znajduje się folder dla środowisk wirtualnych i innych dla projekty.

Virtualenv jest sposobem na izolowanie środowisk Pythona; jako taki nie ma dużej roli do odegrania przy wdrożeniu - jednak podczas rozwoju i testowania jest wymaganiem, jeśli nie bardzo polecam.

Wartość, którą można uzyskać z virtualenv, polega na tym, że pozwala ona upewnić się, że odpowiednie wersje bibliotek są zainstalowane dla aplikacji. Więc nie ma znaczenia, gdzie przyklejasz wirtualne środowisko. Upewnij się tylko, że nie dołączasz go do systemu wersjonowania kodu źródłowego.

Układ systemu plików nie jest krytyczny. Zobaczysz wiele artykułów wychwalających zalety układów katalogów, a nawet szkieletowe projekty, które możesz sklonować jako punkt wyjścia. Uważam, że jest to bardziej osobiste preferencje niż trudne wymagania. Oczywiście, że jest miło; ale chyba, że wiesz, dlaczego, nie dodaje to żadnej wartości do procesu wdrażania - więc nie rób tego, ponieważ jakiś blog zaleca to, chyba że ma to sens dla Twojego scenariusza. Na przykład-nie ma potrzeby tworzenia pliku setup.py, jeśli nie masz prywatnego serwera PyPi, który jest częścią procesu wdrażania.

Jak mogę skonfigurować rzeczy w sposób, który pozwala na kilka strony do hostingu na jednym serwerze?

Są dwie rzeczy, które musisz zrobić wiele ustawień witryny:

  1. serwer, który nasłuchuje na publicznym IP na porcie 80 i / lub porcie 443, jeśli masz SSL.
  2. grupa "procesów", które uruchamiają rzeczywisty kod źródłowy django.
[19]}ludzie używają nginx dla #1, ponieważ jest to bardzo szybki serwer proxy i nie ma narzutu kompleksowego serwera, takiego jak Apache. Możesz swobodnie korzystać z Apache, jeśli jesteś wygodnie. Nie ma wymogu, aby "dla witryn mulitple, używaj nginx"; potrzebujesz tylko usługi, która nasłuchuje na tym porcie, wie jak przekierować (proxy) do Twoich procesów uruchamiających rzeczywisty kod django.

Dla #2 Istnieje kilka sposobów na rozpoczęcie tych procesów. gevent / uwsgi są najbardziej popularne. Jedyną rzeczą do zapamiętania jest to, że nie używaj runserver w produkcji.

Są to bezwzględne minimalne wymagania. Zazwyczaj ludzie dodają jakiś rodzaj menedżera procesów do kontrolowania wszystkich uruchomionych "serwerów django" (#2). Zobacz teżupstart oraz supervisor wspominany. Wolę Supervisora, ponieważ nie musi on przejmować całego systemu (w przeciwieństwie do upstartu). Jednak znowu-nie jest to trudne Wymaganie . Można doskonale uruchomić kilka screen sesje i odłączyć je. Minusem jest to, że po ponownym uruchomieniu serwera będziesz musiał ponownie uruchomić sesje ekranowe.

Osobiście chciałbym polecam:

  1. Nginx dla # 1
  2. Wybierz między uwsgi i gunicorn-używam uwsgi.
  3. supervisor do zarządzania procesami backendowymi.
  4. Indywidualne Konta systemowe (użytkownicy) dla każdej aplikacji, którą hostujesz.

Zalecam # 4, aby wyizolować uprawnienia; ponownie, nie jest to wymóg.

Dlaczego niektórzy sugerują użycie gunicorn_django-b 0.0.0.0: 8000 i inni sugerują gunicorn_django-b 127.0.0.1:8000? Testowałem te ostatnie w instancji Amazon EC2, ale nie zadziałało, gdy ta pierwsza działała bez problemu.

0.0.0.0 oznacza "wszystkie adresy IP" - jest to adres meta (czyli adres zastępczy). {[5] } jest zarezerwowanym adresem, który zawsze wskazuje na lokalną maszynę. Dlatego nazywa się "localhost". Jest osiągalny tylko dla procesów działających na tym samym systemie.

Zazwyczaj masz serwer front-end (#1 na liście powyżej) nasłuchujący publicznie Adres IP. Użytkownik powinien jawnie powiązać serwer z jednym adresem IP .

Jeśli jednak z jakiegoś powodu korzystasz z DHCP lub nie wiesz, jaki będzie adres IP (na przykład nowo udostępniony system), możesz powiedzieć nginx/apache/każdemu innemu procesowi, aby powiązał się z 0.0.0.0. to powinna być tymczasowa miara stop-gap.

Dla serwerów produkcyjnych będziesz miał statyczny adres IP. Jeśli masz dynamiczny adres IP (DHCP), możesz zostawić w 0.0.0.0. Jest to bardzo rzadkie, że będziesz mieć DHCP dla swoich maszyn produkcyjnych.

Wiązanie gunicorn / uwsgi do tego adresu jest nie zalecane w produkcji. Jeśli połączysz proces backendu (gunicorn / uwsgi) z 0.0.0.0, może on stać się dostępny "bezpośrednio", omijając serwer proxy front-end (nginx / apache / etc); ktoś może po prostu poprosić http://your.public.ip.address:9000/ i uzyskać bezpośredni dostęp do Twojej aplikacji zwłaszcza jeśli twój serwer front-end (nginx) i twój proces back-end (django / uwsgi / gevent) są działa na tej samej maszynie.

Możesz to zrobić, jeśli nie chcesz mieć kłopotów z uruchomieniem serwera proxy front-end.

Jaka jest logika pliku konfiguracyjnego nginx? Jest tak wiele tutoriale z wykorzystaniem różnych plików konfiguracyjnych, które Nie wiem, który jest lepszy. Na przykład, niektórzy ludzie używają " alias /path / to/static / folder "i inne" root / path / to/static / folder". Może możesz podzielić się preferowanym plik konfiguracyjny.

Po pierwsze powinieneś wiedzieć o nginx, że jest to a nie serwer WWW jak Apache czy IIS. To jest Pełnomocnik. Zobaczysz więc różne terminy, takie jak "upstream"/ "downstream" i wiele "serwerów", które są zdefiniowane. Poświęć trochę czasu i najpierw przejrzyj instrukcję nginx. Jest wiele różnych sposobów, aby skonfigurować nginx, ale oto jedna odpowiedź na twoje pytanie na temat alias vs. root. root jest jawną dyrektywą, która wiąże główny dokument ( "katalog domowy") firmy nginx. Jest to katalog, na który będzie patrzeć, gdy podasz żądanie bez ścieżki, takiej jak http://www.example.com/

alias oznacza "mapowanie nazwy do katalogu". Aliasowane katalogi nie mogą być podkatalogiem głównego dokumentu.

Dlaczego tworzymy dowiązanie symboliczne między witryną-dostępną i witrynami-włączonymi w / etc / nginx?

Jest to coś unikalnego dla Debiana (i systemów podobnych do Debiana, takich jak ubuntu). sites-available wyświetla listę plików konfiguracyjnych dla wszystkich wirtualnych hostów/witryn w systemie. Dowiązanie symboliczne od sites-enabled do sites-available "aktywuje" tę stronę lub wirtualny host. Jest to sposób na oddzielenie plików konfiguracyjnych i łatwe włączanie / wyłączanie hostów.

 104
Author: Burhan Khalid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-23 05:16:40

Nie jestem guru wdrażania, ale podzielę się niektórymi z moich Praktyk Wdrażania Django z gevent (powinno być podobne do gunicorn).

virtualenv jest świetny z powodów, do których nie pójdę. Jednak znalazłem virtualenv-wrapper (docs) bardzo przydatne, zwłaszcza gdy pracujesz nad wieloma projektami, ponieważ pozwala na łatwe przełączanie się między różnymi wirtualnymi plikami. Nie dotyczy to tak naprawdę środowiska wdrażania, jednak gdy muszę rozwiązywać problemy na serwerze za pomocą SSH, uznałem to za bardzo przydatne. Kolejną zaletą korzystania z niego jest to, że zarządza katalogiem virtualenv, więc mniej pracy ręcznej dla Ciebie. Virtualenvs mają być jednorazowe, więc w przypadku problemów z wersją lub innymi problemami z instalacją, możesz po prostu zrzucić env i utworzyć nowy. W rezultacie najlepszą praktyką jest nie dołączanie żadnego kodu projektu do virtualenv. Powinien być oddzielony.

Jeśli chodzi o konfigurację wielu witryn, virtualenv jest w zasadzie odpowiedzią. Ty powinien mieć oddzielny virutalenv dla każdego projektu. To samo może rozwiązać wiele problemów. Następnie podczas wdrażania inny proces Pythona uruchomi różne witryny, co pozwoli uniknąć ewentualnych konfliktów między wdrożeniami. Jednym z narzędzi, które szczególnie przydały mi się w zarządzaniu wieloma witrynami na tym samym serwerze jest supervisor (docs ). Zapewnia łatwy interfejs do uruchamiania, zatrzymywania i restartowania różnych instancji Django. Jest również w stanie automatycznie zrestartować proces, gdy awarii lub po uruchomieniu komputera. Więc na przykład, jeśli jakiś wyjątek zostanie podniesiony i nic go nie złapie, cała strona internetowa może zejść. Supervisor to złapie i automatycznie uruchomi instancję Django. Poniżej znajduje się przykładowy program nadzorujący (pojedynczy proces) config:

[program:foo]
command=/path/toviertualenv/bin/python deploy.py
directory=/path/where/deploy.py/is/located/
autostart=true
autorestart=true
redirect_stderr=True
user=www
Dla Nginx, wiem, że to może być przytłaczające na początku. Jest to jedna z najbardziej popularnych gier na świecie. To wyjaśnia wszystkie główne dyrektywy nginx. W mojej instalacji nginx znalazłem najlepsze praktyka polega na ustawieniu tylko core configs w pliku nginx.conf, a następnie mam oddzielny folder sites, w którym trzymam konfiguracje nginx dla każdej z witryn, które hostuję. Następnie dołączam wszystkie pliki z tego folderu do pliku core config. Używam dyrektywy include sites/+*.conf;. W ten sposób zawiera tylko pliki zaczynające się od symbolu + w folderze sites. W ten sposób poprzez nazwę pliku mogę kontrolować, które Pliki konfiguracyjne mają być ładowane. Więc jeśli chcę wyłączyć pewną stronę, po prostu muszę zmienić nazwę plik konfiguracyjny i uruchom ponownie nginx. Nie jestem pewien, co miałeś na myśli mówiąc "łącze symboliczne między witryną-dostępną i witrynami-włączonymi w /etc/nginx" w twoim pytaniu, ponieważ są to foldery nazwane Apache, ale wykonują podobne zadanie jak dyrektywa include.

Jeśli chodzi o dyrektywy root i alias, są one prawie takie same, z wyjątkiem przypadków, w których ich korzeń jest obliczany. In alias, whatever in the location in dropped, whether in root in it not. Obraz, który masz następujący nginx config:

location /static {
    alias /some/path/;
}
location /static2 {
    root /some/other/path/;
}
Jeśli użytkownik korzysta z tych adresów URL, nginx spróbuje wyszukać pliki w następujących miejscach w systemie:]}
/static/hello/world.pdf => /some/path/hello/world.pdf
/static2/hello/world.pdf => /some/other/path/static2/hello/world.pdf
To jest prosty config dla strony nginx: [19]}
server {
    server_name .foodomain.com;
    listen 80;

    access_log logs/foodomain.log;

    gzip                on;
    gzip_http_version   1.0;
    gzip_comp_level     2;
    gzip_proxied        any;
    gzip_min_length     1100;
    gzip_buffers        16 8k;
    gzip_types          text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    # Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    # Set a vary header so downstream proxies don't send cached gzipped content to IE6
    gzip_vary on;

    location / {
        proxy_read_timeout      30s;
        proxy_pass              http://localhost:8000;
        proxy_set_header        Host                 $host;
        proxy_set_header        User-Agent           $http_user_agent;
        proxy_set_header        X-Real-IP            $remote_addr;
    }

    location /media {
        alias   /path/to/media/;
        expires 1y;
    }

    location /static {
        autoindex on;
        expires   1y;
        alias     /path/to/static/;
    }

     location /favicon.ico {
        alias /path/to/favicon.ico;
    }
}

Mam nadzieję, że to ci trochę pomoże.

 11
Author: miki725,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-22 04:00:40

Cóż, jeśli chodzi o najlepsze praktyki, które zadałeś w swoim pytaniu, nie mogę pomóc w udostępnieniu narzędzia, które działało cuda dla mnie, dosłownie! Sam kiedyś się pomyliłem w kilku plikach konfiguracyjnych gunicorn, nginx, supervisorD dla kilku stron! Ale chciałem w jakiś sposób zautomatyzować cały proces, aby móc wprowadzić zmiany w mojej aplikacji/witrynie i wdrożyć go natychmiast. Jego nazwa to django-fagungis. Możesz znaleźć szczegóły mojego doświadczenia z Django Deployment automation tutaj . Właśnie skonfigurowałem fabfile.py ONCE (django-fagungis używa fabric do automatyzacji całego procesu i tworzy virtualenv na Twoim zdalnym serwerze, który jest bardzo przydatny do zarządzania zależnościami kilku witryn hostowanych na jednym serwerze. Używa nginx, gunicorn i supervisorD do obsługi projektu Django/site deployment) i django-fagungis klonuje mój najnowszy projekt z bitbucket (którego używam do wywrotowania) i wdraża go na moim zdalnym serwerze i muszę tylko wpisać trzy polecenia na powłoce mojej lokalnej Maszyny i że to!! Dla mnie okazało się to najlepszą i bezproblemową praktyką dla wdrożenia Django.

 2
Author: Ali Raza Bhayani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 15:21:04

Sprawdź to dla minimalnej konfiguracji gunicorn i nginx wymaganej dla projektu Django. http://agiliq.com/blog/2013/08/minimal-nginx-and-gunicorn-configuration-for-djang/

 2
Author: Akshar Raaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-16 20:47:03