Розгортання Django з gunicorn та nginx


81

Це широке запитання, але я хотів би отримати канонічну відповідь. Я намагався розгорнути сайт за допомогою gunicorn та nginx у Django . Прочитавши безліч підручників, я досяг успіху, але не можу бути впевненим, що кроки, які я виконав, є достатньо хорошими для запуску сайту без проблем, або, можливо, є кращі способи зробити це. Ця невизначеність дратує.

Ось чому я шукаю дуже детальну та добре пояснену відповідь для новачків. Я не хочу занадто багато пояснювати, що я знаю, а що не знаю, оскільки це може дещо перекосити відповіді, а інші люди можуть отримати меншу користь від ваших відповідей. Однак деякі речі, про які я хотів би бачити, такі:

  • Яке "налаштування" ви бачили як найкраще працює? Я використав virtualenv і перемістив свій проект Django всередину цього середовища, однак я бачив інші установки, де є папка для віртуального середовища та інші для проектів.

  • Як я можу налаштувати речі таким чином, що дозволяє розміщувати кілька сайтів на одному сервері?

  • Чому одні люди пропонують використовувати, gunicorn_django -b 0.0.0.0:8000а інші пропонують gunicorn_django -b 127.0.0.1:8000? Я тестував останню в екземплярі Amazon EC2, але вона не працювала, поки перша працювала без проблем.

  • У чому полягає логіка конфігураційного файлу nginx? Існує стільки підручників, в яких використовуються кардинально різні конфігураційні файли, що я збентежений, який з них краще. Наприклад, одні люди використовують alias /path/to/static/folderта інші root /path/to/static/folder. Можливо, ви можете поділитися улюбленим файлом конфігурації.

  • Чому ми створюємо символічне зв’язок між site-availableі sites-enabledвсередині /etc/nginx?

  • Деякі найкращі практики, як завжди вітаються :-)

Дякую


Чи можете ви розмістити приклад на git стосовно цих nginx та gunicorn / uwsgi. Це буде кориснішим для нових учнів, таких як я.
Шива,

@Shiva Насправді відповідь miki725 містить дуже повний зразок конфігураційного файлу. Якщо ви хочете дуже детально ознайомитись із тим, що відбувається з nginx, я рекомендую вам <a href=" amazon.com/Nginx-HTTP-Server-Cl%C3%A9ment-Nedelcu/dp/… book</a>. інтеграція gunicorn дуже просто Він викладений <a href=" docs.djangoproject.com/en/dev/howto/deployment/wsgi/gunicorn/...> .
Роберт Сміт

Відповіді:


106

Яке "налаштування" ви бачили як найкраще працює? Я використав virtualenv і перемістив свій проект django всередину цього середовища, однак я бачив і інші установки, де є папка для віртуального середовища та інші для проектів.

virtualenv - це спосіб ізолювати середовища Python; як такий, він не має великої ролі при розгортанні, проте під час розробки та тестування це є вимогою, якщо не настійно рекомендується.

Цінність, яку ви отримаєте від virtualenv, полягає в тому, що вона дозволяє вам переконатися, що для програми встановлені правильні версії бібліотек. Тож не має значення, куди ви вкладаєте саме віртуальне оточення. Тільки переконайтеся, що ви не включаєте його як частину системи версій вихідного коду.

Макет файлової системи не є критичним. Ви побачите безліч статей, які прославляють достоїнства макетів каталогів і навіть скелетні проекти, які ви можете клонувати як вихідну точку. Я вважаю, що це більше особисті переваги, ніж важка вимога. Звичайно, це приємно мати; але якщо ви не знаєте чому , це не додає ніякої цінності вашому процесу розгортання - тому не робіть цього, оскільки деякі блоги рекомендують це, якщо це не має сенсу для вашого сценарію. Наприклад - немає необхідності створювати setup.pyфайл, якщо у вас немає приватного сервера PyPi, який є частиною вашого робочого процесу розгортання.

Як я можу налаштувати речі таким чином, що дозволяє розміщувати кілька сайтів на одному сервері?

Існує дві речі, які потрібно зробити для кількох налаштувань сайту:

  1. Сервер, який прослуховує загальнодоступний IP на порту 80 та / або порту 443, якщо у вас SSL.
  2. Купа "процесів", на яких запущений власне вихідний код django.

Люди використовують nginx для №1, оскільки він дуже швидкий проксі-сервер, і він не постачається із накладними витратами на такий серверний сервер, як Apache. Ви можете користуватися Apache, якщо вам це зручно. Немає вимоги, що "для кількох сайтів використовуйте nginx"; вам просто потрібна послуга, яка прослуховує цей порт, знає, як перенаправити (проксі-сервер) на ваші процеси, що виконують фактичний код django.

Для №2 існує кілька способів запустити ці процеси. gevent / uwsgi - найпопулярніші. Єдине, що слід пам’ятати, це не використовувати runserver у виробництві .

Це абсолютні мінімальні вимоги. Зазвичай люди додають якийсь диспетчер процесів, щоб керувати всіма запущеними «серверами django» (№2). Тут ви побачите upstartі згадаєте supervisor. Я віддаю перевагу супервізору, оскільки йому не потрібно брати на себе всю систему (на відміну від запуску). Однак знову ж таки - це не важка вимога . Ви могли б чудово провести купу screenсеансів і відокремити їх. Недоліком є ​​те, що якщо ваш сервер перезапуститься, вам доведеться перезапустити сеанси екрану.

Особисто я б порекомендував:

  1. Nginx для №1
  2. Вибирайте між uwsgi та gunicorn - я використовую uwsgi.
  3. супервізор для управління серверними процесами.
  4. Індивідуальні системні облікові записи (користувачі) для кожної програми, яку ви розміщуєте.

Причиною, яку я рекомендую №4, є ізоляція дозволів; знову ж таки, не вимога.

Чому деякі люди пропонують використовувати gunicorn_django -b 0.0.0.0:8000, а інші пропонують gunicorn_django -b 127.0.0.1:8000? Я тестував останню в екземплярі Amazon EC2, але вона не працювала, поки перша працювала без проблем.

0.0.0.0означає "всі IP-адреси" - це мета-адреса (тобто адреса заповнювача). 127.0.0.1- це зарезервована адреса, яка завжди вказує на локальну машину. Ось чому його називають "localhost". Він доступний лише для процесів, що працюють в одній системі.

Зазвичай передній сервер (№1 у списку вище) прослуховує загальнодоступну IP-адресу. Вам слід явно прив’язати сервер до однієї IP-адреси .

Однак, якщо з якихось причин ви використовуєте DHCP або не знаєте, якою буде IP-адреса (наприклад, її нещодавно надана система), ви можете сказати nginx / apache / будь-який інший процес, до якого потрібно прив’язатись 0.0.0.0. Це має бути тимчасовим запобіжним заходом .

Для робочих серверів у вас буде статичний IP. Якщо у вас є динамічний IP (DHCP), ви можете залишити 0.0.0.0. Дуже рідко ви отримуєте DHCP для своїх виробничих машин.

Прив'язувати gunicorn / uwsgi до цієї адреси не рекомендується у виробництві. Якщо ви прив'яжете свій серверний процес (gunicorn / uwsgi) до 0.0.0.0, він може стати доступним "безпосередньо", минаючи ваш інтерфейсний проксі (nginx / apache / і т.д.); хтось може просто запитати http://your.public.ip.address:9000/та отримати безпосередній доступ до вашої програми, особливо якщо ваш інтерфейсний сервер (nginx) та ваш внутрішній процес (django / uwsgi / gevent) працюють на одній машині .

Ви можете це зробити, якщо не хочете клопоту з запуском інтерфейсного проксі-сервера.

У чому полягає логіка конфігураційного файлу nginx? Існує стільки підручників, в яких використовуються кардинально різні конфігураційні файли, що я збентежений, який з них краще. Наприклад, деякі люди використовують "псевдонім / шлях / до / static / папки", а інші - "root / path / to / static / folder". Можливо, ви можете поділитися улюбленим файлом конфігурації.

Перше, що ви повинні знати про nginx, це те, що це не веб-сервер, як Apache або IIS. Це проксі. Отже, ви побачите різні терміни, такі як "вище за течією" / "нижче за течією" та кілька "серверів", які визначаються. Витратьте трохи часу і спершу перегляньте посібник nginx.

Існує безліч різних способів налаштування nginx; але ось одна відповідь на питання про aliasVS. root. rootце явна директива, яка пов'язує корінь документа ("домашній каталог") nginx. Це каталог, який він буде дивитись, коли ви надсилаєте запит без такого шляхуhttp://www.example.com/

aliasозначає "зіставити ім'я з каталогом". Псевдоні каталоги можуть не бути підкаталогом кореневого документа.

Чому ми створюємо символічне посилання між доступними сайтами та сайтами з підтримкою в / etc / nginx?

Це щось унікальне для debian (і подібних до debian систем, таких як ubuntu). sites-availableперераховує файли конфігурації для всіх віртуальних хостів / сайтів у системі. Символьне посилання з sites-enabledна sites-available"активує" цей сайт або віртуальний хост. Це спосіб відокремити конфігураційні файли та легко ввімкнути / вимкнути хости.


1
Чудова відповідь! З'ясовано багато питань. Чи можете ви трохи детальніше пояснити (або додати приклад), що ви маєте на увазі, явно прив’язавши сервер до IP-адреси, і що прив’язка gunicorn / uwsgi повинна бути прив’язана до 0.0.0.0? На жаль, я думаю, що цим я займався. Дякую!
Роберт Сміт,

7
Типовий комп'ютер буде мати принаймні дві IP-адреси: 127.0.0.1і ту, яку йому присвоює мережа; це мінімум - ваша машина може мати кілька інтерфейсів та кілька IP-адрес. Ви повинні налаштувати свій веб-сервер (або будь-який інший процес, насправді); прослуховувати одну IP-адресу - це те, що я маю на увазі, кажучи явно Коли ви прив’язуєтесь 0.0.0.0, ви просите програму прослуховувати всі IP-адреси, включаючи будь-які нові, які можуть бути призначені вашій машині . Це не є доброю практикою з різних причин (безпека - одна з них).
Бурхан Халід,

Зрозумів. Я вже правильно налаштував Gunicorn. Дуже дякую!
Роберт Сміт,

nginx може обслуговувати статичний вміст.
Marcin

як сервер дізнається, в якому файлі ми налаштували адресу сервера/etc/nginx/sites-enabled
Шива,

11

Я не гуру розгортання, але поділюсь деякими своїми практиками щодо розгортання Django з gevent (хоча має бути схожим на gunicorn).

virtualenvчудово з причин, якими я не займусь. Однак я знайшов virtualenv-wrapper( docs ) дуже корисним, особливо коли ви працюєте над багатьма проектами, оскільки це дозволяє легко перемикатися між різними віртуальними програмами. Це насправді не стосується середовища розгортання, однак, коли мені потрібно усунути неполадки на сервері за допомогою SSH, я знайшов це дуже корисним. Ще однією перевагою його використання є те, що він управляє каталогом virtualenv, тому менше ручної роботи для вас. Virtualenvs призначені для одноразового використання, так що у випадку, якщо у вас є проблеми з версією або будь-які інші проблеми з установкою, ви можете просто скинути env і створити нову. Як результат, найкращою практикою є не включати будь-який код вашого проекту до virtualenv. Його слід тримати окремо.

Що стосується налаштування декількох сайтів, virtualenvце майже відповідь. Ви повинні мати окремий virutalenv для кожного проекту. Тільки це одне може вирішити багато питань. Тоді при розгортанні інший процес Python запускатиме різні сайти, що дозволяє уникнути можливих конфліктів між розгортаннями. Одним із інструментів, який мені особливо знайшов дуже корисним для управління кількома сайтами на одному сервері, є supervisor( docs). Він забезпечує простий інтерфейс для запуску, зупинки та перезапуску різних екземплярів Django. Він також може автоматично перезапустити процес, коли він виходить з ладу або коли комп'ютер запускається. Так, наприклад, якщо піднято якесь виняток і його ніщо не вловлює, весь веб-сайт може зайти. Супервайзер схопить це і автоматично перезапустить екземпляр Django. Нижче наведено зразок програми нагляду (єдиний процес):

[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

Для Nginx я знаю, що спочатку це може бути приголомшливим. Я знайшов Nginx книгу про дуже корисною. Це пояснює всі основні директиви nginx.

Під час моєї інсталяції nginx я виявив, що найкращою практикою є встановлення у nginx.confфайлі лише основних конфігурацій, а потім у мене є окрема папка, sitesде я зберігаю конфігурації nginx для кожного з розміщених на мене сайтів. Тоді я просто включаю всі файли з цієї папки до основного конфігураційного файлу. Я використовую директиву include sites/+*.conf;. Таким чином він включає лише файли, що починаються з+ символу в sitesпапці. Таким чином, просто за назвою файлу я можу контролювати, які файли конфігурації завантажуватимуться. Отже, якщо я хочу відключити певний сайт, мені просто потрібно перейменувати файл конфігурації та перезапустити nginx. Не зовсім впевнений, що ви мали на увазі під вашим запитанням під назвою "символічне посилання між сайтами, доступними для сайтів та з увімкненими сайтами в / etc / nginx", оскільки це папки з іменем Apache, але вони виконують подібне завдання, як includeдиректива.

Що стосується rootі aliasдиректив, вони майже однакові, за винятком випадків, коли обчислюється їх корінь. В alias, що б там не булоlocation в впало, тоді як в корінь в ньому ні. Зображення, яке ви маєте наступну конфігурацію nginx:

location /static {
    alias /some/path/;
}
location /static2 {
    root /some/other/path/;
}

Якщо користувач переходить до цих URL-адрес, то nginx спробує шукати файли в таких місцях системи:

/static/hello/world.pdf => /some/path/hello/world.pdf
/static2/hello/world.pdf => /some/other/path/static2/hello/world.pdf

Це проста конфігурація для сайту nginx:

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;
    }
}

Сподіваємось, це трохи допоможе вам.


Насправді ваша відповідь дуже допомагає! Supervisor звучить чудово, і це одна з небагатьох речей, де, схоже, існує консенсус серед блогерів. Чудова порада щодо віртуального середовища та його обгортки. У мене виникло спокуса додати до суміші virtualenv-wrapper, але я не хотів зайво збільшувати складність у цьому питанні. Що стосується сайтів, доступних та сайтів, nginx містить ці каталоги. Де ви створюєте конфігураційний файл для nginx? Усередині вашого проекту Django?
Роберт Сміт,

Я їх особисто зберігаю в конфігураційній папці nginx. У моєму випадку це так /usr/local/nginx/config/sites. Однак не впевнений, чи це правильний чи кращий метод. Причина, по якій я їх там зберігаю, полягає в тому, що якщо я винесу її, то якось мені доведеться включити її в nginx, або вручну, включивши includeдирективу, або зробивши символічні посилання. У будь-якому випадку це ручна праця, тому я просто зберігаю її в основному конфігураційному місці.
miki725

Я читаю книгу, яку ви рекомендували :-) Це чудово, і, як ви пам’ятаєте, /sites/*.conf - один із запропонованих способів зробити це. У будь-якому разі, дякую за вашу відповідь.
Роберт Сміт,

Будь ласка. Один розділ про книгу, хоч і не дуже корисний, - це те, як використовувати Django з nginx. Book рекомендує використовувати fastcgi, який не є акуратним, оскільки використовується проксі-пропуск. Тож ви можете пропустити розділ 6.
miki725

Я щойно закінчив читати книгу. Це чудово. Я насправді читав 6-й розділ, бо хотів знати, як працює хой fastcgi, але ти маєш рацію ... це було не дуже корисно. Дякую!
Роберт Сміт,

2

Що ж стосується найкращих практик, які ви задавали у своєму питанні, я не можу не поділитися інструментом, який творив для мене чудеса, буквально! Я сам заплутувався в декількох конфігураційних файлах gunicorn, nginx, supervisorD для кількох сайтів! Але я прагнув якось автоматизувати весь процес, щоб я міг внести зміни до свого додатка / сайту та негайно розгорнути його. Його назва - джанго-фагунгіс. Ви можете знайти деталі мого досвіду роботи з автоматизацією розгортання Django тут . Я щойно налаштував fabfile.py РАЗ (django-fagungis використовує тканину для автоматизації всього процесу і робить virtualenv на віддаленому сервері, ДУЖЕ зручнимдля управління залежностями декількох сайтів, розміщених на одному сервері. Він використовує nginx, gunicorn і supervisorD для обробки проекту Django / розгортання сайту) і django-fagungis клонує мій останній проект з bitbucket (який я використовую для підриву) і розгортає його на своєму віддаленому сервері, і мені просто потрібно ввести три команди в оболонці моєї місцевої машини і що це !! Для мене це виявилося найкращою та безпроблемною практикою розгортання Django.


Дякую!. Я подивлюсь на це.
Robert Smith

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.