Nano Hash - криптовалюты, майнинг, программирование

Развертывание Django с Nginx, Gunicorn и Supervisor

Я пытаюсь развернуть свое приложение Django с Nginx и Gunicorn, следуя этому руководству, но я изменил некоторые шаги, чтобы использовать Conda вместо ViritualEnv.

Настройка выглядит так:

  1. Nginx отвечает моим приложением Vue
  2. Запросы от Vue отправляются на api.example.com
  3. Nginx слушает api.example.com и направляет запросы в unix-сокет Gunicorn

Вещи, которые я проверил:

  1. Я вижу запросы Vue в access.log.
  2. Я также могу видеть эти запросы в journalctl -f -u gunicorn, в supervisor.log и в журнале access.log.
  3. Когда мое приложение Django запускается, оно создает файл журнала, поэтому я вижу, что Gunicorn запускает его. Но Django не отвечает на запросы из сокета unix.
  4. Я вижу ответ от Django, когда вхожу по ssh и запускаю следующую команду: curl --no-buffer -XGET --unix-socket /var/www/example/run/gunicorn.sock http://localhost/about. Эта команда дает ответ только тогда, когда любой из моих ALLOWED_HOSTS используется вместо localhost.
  5. Мои конфигурации Nginx, Supervisor и Gunicorn используют полный путь к gunicorn.sock.

Должен ли я увидеть, что Django работает на порту 8000 или что-то еще, если я сделаю что-то вроде nmap localhost? Я видел еще одну публикацию, в которой упоминалось, что Nginx должен указывать на порт 8000 и что Gunicorn должен быть запущен либо с:

  1. gunicorn --bind 0.0.0.0:8000 <djangoapp>.wsgi --daemon
  2. gunicorn <djangoapp>.wsgi:application --bind <IP>:8000 --daemon
  3. gunicorn <djangoapp>.wsgi:application --bind=unix:/var/www/example/run/gunicorn.sock

Но разве раскрытие порта 8000 не уничтожает цель использования Nginx в качестве обратного прокси и unix-сокета Gunicorn? Разве экспонирование 8000 не увеличивает площадь для векторов атаки? Или лучше всего выставить порт 8000? Я немного сбит с толку, почему я должен использовать оба порта и Nginx, и Gunicorn.

Моя основная проблема: почему я могу получать ответы от Django через сокет unix с помощью curl, но не через запросы от Vue? Почему запросы Vue не поступают из Gunicorn в Django через сокет unix?

Я действительно застрял. Какие-либо предложения?

Конфигурация Frontend Nginx

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        # server_name example.com;
        # server_name myIP;
        root /var/www/example/frontend/dist;
        server_name example.com www.example.com;

        location =/robots.txt {
                root /opt/example;
        }

        location /thumbnail/ {
                alias /opt/example/static/img/thumbnail/;
        }

        location /bg/ {
                alias /opt/example/static/img/bg/;
        }

        location / {
                try_files $uri $uri/ /index.html;
        }
}

Конфигурация API Nginx

upstream backend_server {
        server unix:/var/www/example/run/gunicorn.sock fail_timeout=0;
}

server {
        listen 80;
        server_name api.example.com
        client_max_body_size 4G;

        access_log /var/log/nginx/api-access.log;
        error_log /var/log/nginx/api-error.log;

        location / {
                include proxy_params;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_headers_hash_max_size 512;
                proxy_headers_hash_bucket_size 128; 
                proxy_redirect off;
                if (!-f $request_filename) {
                        proxy_pass http://backend_server;
                }
        }
}

Конфигурация Gunicorn

#!/bin/bash

NAME=”backend”
DJANGODIR=/var/www/example/backend
SOCKFILE=/var/www/example/run/gunicorn.sock
USER=django
GROUP=example
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=backend.settings
DJANGO_WSGI_MODULE=backend.wsgi
CONDA_SRC=/home/justin/anaconda3/etc/profile.d/conda.sh
GUNICORN=/home/justin/anaconda3/envs/production/bin/gunicorn

echo “starting backend”

cd $DJANGODIR
    source $CONDA_SRC
conda activate production
    export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
    export PYTHONPATH=$DJANGODIR:$PYTHONPATH
    
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

exec $GUNICORN
 ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE \
  --log-level=debug \
  --log-file=- \
  --error-logfile=/var/www/example/backend/logs/gunicorn-error.log \
  --access-logfile=/var/www/example/backend/logs/gunicorn-access.log

Gunicorn access.log

- - [08/Sep/2020:01:51:24 -0400] "OPTIONS /c/about/ HTTP/1.0" 200 0 "http://example.com/c/about" "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Mobile Safari/537.36"
- - [08/Sep/2020:01:51:24 -0400] "POST /c/about/ HTTP/1.0" 400 143 "http://example.com/c/about" "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Mobile Safari/537.36"

  • как выглядит ваша конфигурация nginx? 08.09.2020
  • @yedpodtrzitko Я только что обновил пост своими конфигами nginx. 08.09.2020

Ответы:


1

Но разве раскрытие порта 8000 не уничтожает цель использования Nginx в качестве обратного прокси и unix-сокета Gunicorn?

В Gunicorn вам нужно открыть порт 8000 на локальном хосте, как это gunicorn --bind 127.0.0.1:8000 <djangoapp>.wsgi --daemon. Разоблачение его на 0.0.0.0, очевидно, будет уязвимостью безопасности, учитывая, что ваш nginx находится на том же сервере.

Разве экспонирование 8000 не увеличивает площадь для векторов атаки? Или лучше всего выставить порт 8000? Я немного сбит с толку, почему я должен использовать оба порта и Nginx, и Gunicorn.

Вам не нужно открывать порт 8000, вы можете открыть любой порт, но вам нужно указать gunicon прослушивать хотя бы один порт, чтобы nginx мог передавать ему запросы.

Что касается использования как nginx, так и gunicorn, они действительно разные и обрабатывают очень разные варианты использования / функции приложения.

Nginx использует управляемый событиями подход для обработки запросов, поэтому один рабочий процесс nginx может одновременно обрабатывать тысячи запросов. Но Gunicorn, с другой стороны, в основном (по умолчанию) использует синхронизирующий воркер, что означает, что запрос будет оставаться у воркера до тех пор, пока он не будет обработан. (опубликовал это дважды сегодня: p)

Итак, вам понадобятся оба, если вы удалите nginx, все ваши запросы будут возвращать 50X, за исключением тех, которые в настоящее время обрабатываются gunicorn, пока рабочий не освободится. Кроме того, Gunicorn не предназначен для обработки пользовательского трафика, а в более крупных приложениях такие вещи, как балансировка нагрузки, могут выполняться только nginx. Итак, у nginx есть собственное предназначение в приложении.

08.09.2020
  • Хорошо спасибо. Есть ли у вас какое-нибудь представление о том, почему запросы не поступают из Gunicorn в Django? 08.09.2020
  • так что .. просто спрашиваю .. проблема только тогда, когда вы используете сокет Unix, а не когда вы используете привязку локального хоста или порта хоста? 08.09.2020
  • Меня беспокоит то, что в вашем журнале доступа Gunicorn есть ошибка 400 ... он возвращает 400? по запросам vue? Если да, попробуйте _1 _... В целом я не очень хорошо понимаю, в чем проблема, но единственное, о чем я могу думать, это Allowed_host (который, как вы сказали, установлен правильно), попробуйте начать с его установки [*] и debug = True и посмотрим, поможет ли это ... если да, то ваш nginx не возвращает правильные хосты в django. Посмотрите, установлено ли для USE_X_FORWARDED_HOST значение "Ложь". 08.09.2020
  • Я просто попробовал установить DEBUG=True и ALLOWED_HOSTS=['*']. Я должен был делать звездочку без кавычек или с кавычками? Тоже не ставил изначально USE_X_FORWARDED_HOST. 08.09.2020
  • Идентификатор, если это (serverfault.com/q/363159/370473) - именно та проблема, с которой я столкнулся, но кажется актуальной поскольку мой Nginx также не передает порт с прокси-сервером. 08.09.2020

  • 2

    После того, как neeraj9194 указал на 400, я продолжил поиск проблем, связанных с Nginx, Gunicorn 400 и Django, и наткнулся на тонна подобных вопросов. Похоже, это в основном проблема Nginx. Ответ в этом блоге исправил мою проблему.

    Я заменил блок location в своей конфигурации API Nginx на:

    location / {
          proxy_set_header Host $host;
          proxy_pass http://backend_server;
          proxy_set_header X-Forwarded-Host $server_name;
          proxy_set_header X-Real-IP $remote_addr;
      }
    
    08.09.2020
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..