Развертывание Django с помощью пушки и nginx

Это широкий вопрос, но я хотел бы получить канонический ответ. Я пытаюсь развернуть сайт с использованием 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?

  • Некоторые рекомендации всегда приветствуются: -)

Спасибо

Ответ 1

Какую "настройку" вы видели лучше всего? Я использовал virtualenv и переехал django в этой среде, однако я видел другую где есть папка для виртуальных сред и другая для проектов.

virtualenv - способ изолировать среды Python; как таковой, он не играет большой роли при развертывании - однако во время разработки и тестирования это требование, если не рекомендуется.

Значение, которое вы получите от virtualenv, состоит в том, что оно позволяет вам убедиться, что для приложения установлены правильные версии библиотек. Таким образом, неважно, где вы придерживаетесь виртуального envrionment. Просто убедитесь, что вы не включили его как часть системы управления версиями исходного кода.

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

Как я могу настроить вещи таким образом, чтобы можно было разместить несколько сайтов на одном сервере?

Для настройки нескольких сайтов требуется две вещи:

  • Сервер, который прослушивает открытый IP-адрес на порту 80 и/или порт 443, если у вас есть SSL.
  • Множество "процессов", на которых запущен исходный код django.

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

Для # 2 существует несколько способов запуска этих процессов. gevent/uwsgi - самые популярные. Единственное, что нужно запомнить здесь, - это не использовать серверный сервер в производстве.

Это абсолютные минимальные требования. Обычно люди добавляют своего рода диспетчер процессов для управления всеми серверами "django" (# 2). Здесь вы увидите upstart и supervisor упоминается. Я предпочитаю супервизора, так как ему не нужно брать всю систему (в отличие от выскочки). Однако, опять же - это не сложно. Вы могли бы отлично провести кучу сеансов screen и отменить их. Недостатком является то, что если ваш сервер перезагрузится, вам придется перезапустить сеансы экрана.

Лично я бы рекомендовал:

  • Nginx для # 1
  • Возьмите свой выбор между uwsgi и gunicorn - я использую uwsgi.
  • supervisor для управления бэкэнд-процессами.
  • Индивидуальные системные учетные записи (пользователи) для каждого приложения, которое вы размещаете.

Я рекомендую # 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 для своих производственных машин.

Привязка пушки /uwsgi к этому адресу не рекомендуется в производстве. Если вы привяжете свой бэкэнд-процесс (gunicorn/uwsgi) к 0.0.0.0, он может стать доступным "напрямую", минуя ваш внешний прокси (nginx/apache/etc); кто-то может просто запросить http://your.public.ip.address:9000/ и получить доступ к вашему приложению напрямую , особенно если ваш передний сервер (nginx) и ваш конечный процесс (django/uwsgi/gevent) работают на одном компьютере.

Вы можете сделать это, если не хотите, чтобы у вас был простой прокси-сервер.

Какова логика конфигурационного файла nginx? Существует так много уроки, использующие совершенно разные файлы конфигурации, которые я смущенный, на котором лучше. Например, некоторые люди используют "псевдоним" /path/to/static/folder "и другие" root/path/to/static/folder ". Возможно, вы можете поделиться своим предпочтительным конфигурационным файлом.

Первое, что вам нужно знать о nginx, - это не веб-сервер, такой как Apache или IIS. Это прокси. Таким образом, вы увидите различные термины, такие как "upstream" / "downstream" и несколько "серверов". Потратьте некоторое время и сначала просмотрите руководство nginx.

Существует множество различных способов настройки nginx; но вот один ответ на ваш вопрос на alias vs. root. root - это явная директива, которая связывает корень документа ( "домашний каталог" ) nginx. Это каталог, на который он будет смотреть, когда вы даете запрос без пути, например http://www.example.com/

alias означает "сопоставить имя в каталоге". Алиасные каталоги могут не быть подкаталогом корня документа.

Почему мы создаем символическую связь между доступными сайтами и сайтами в /И т.д. /Nginx?

Это нечто уникальное для дебианских (и подобных debian систем, таких как ubuntu). sites-available перечисляет файлы конфигурации для всех виртуальных хостов/сайтов в системе. Символьная ссылка от sites-enabled до sites-available "активирует" этот сайт или виртуальный хост. Это способ разделить файлы конфигурации и легко включить/отключить хосты.

Ответ 2

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

virtualenv отлично по причинам, по которым я не буду вдаваться. Однако я нашел virtualenv-wrapper (docs), особенно когда вы работаете над многими проектами, поскольку он позволяет легко переключаться между различными виртуальными. Это действительно не относится к среде развертывания, однако, когда мне нужно устранить неполадки на сервере с помощью SSH, я нашел это очень полезным. Другим преимуществом использования этого является то, что он управляет каталогом virtualenv, поэтому для вас менее ручная работа. Virtualenvs предназначены для одноразового использования, так что если у вас есть проблемы с версией или любые другие проблемы с установкой, вы можете просто сбросить env и создать новый. В результате лучше всего не включать какой-либо из вашего кода проекта в virtualenv. Его следует хранить отдельно.

Что касается настройки нескольких сайтов, virtualenv - это в значительной степени ответ. У вас должен быть отдельный вирутален для каждого проекта. Только это может решить многие проблемы. Затем при развертывании другой процесс 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 при отбрасывании, тогда как в root в нем нет. У вас есть следующая конфигурация 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;
    }
}

Надеюсь, это поможет вам немного.

Ответ 3

Хорошо, что касается лучших практик, которые вы задали в своем вопросе, я не могу помочь разделить инструмент, который произвел чудеса для меня, буквально! Я сам путался в нескольких файлах конфигурации gunicorn, nginx, supervisorD для нескольких сайтов! Но я жаждал как-то автоматизировать весь процесс, чтобы я мог внести изменения в свое приложение/сайт и развернуть его мгновенно. Его имя django-fagungis. Вы можете найти подробную информацию о моем опыте с Django Deployment automation здесь. Я только что настроил fabfile.py ONCE (django-fagungis использует тканью для автоматизации всего процесса и делает virtualenv на удаленном сервере ОЧЕНЬ удобным для управления зависимостями нескольких сайтов, размещенных на одном сервере. Он использует nginx, gunicorn и supervisorD для обработки развертывания проекта/сайта Django), а django-fagungis клонирует мой последний проект из bitbucket (который я использую для подрывной работы) и развертывает его на удаленном сервере, и мне просто нужно ввести три команды на оболочку моей локальной машины и это! Для меня это оказалось лучшим и затруднительным для практики Django.