Порты, NGINX

Порт — это механизм маршрутизации пакетов данных, способ передать запрос тому приложению, которому он предназначен.
Представьте, что сервер — бизнес-центр. В нём работает множество компаний (программ, процессов), каждая из которых занимается своими задачами и обменивается данными с внешним миром: курьеры с бандеролями (пакетами данных) снуют туда-сюда.
В одном офисе работает почтовое отделение (почтовый сервер), в другом сидят архивариусы с каталогами (база данных), в третьем — служба «горячей линии»: там получают вопросы и отправляют ответы (ваш веб-проект), в четвёртом — отдел погрузок и разгрузок (ftp-сервер, передача файлов).
Для курьеров каждой компании прорублен свой вход в здание. Каждый вход — это и есть порт. Курьеры с почтовыми данными идут через свой вход, курьеры с файлами для ftp — через свой. Никто не ошибётся офисом, все сразу попадают по назначению.
У одного офиса (процесса) может быть и несколько портов: например, почтовое соединение по протоколу POP традиционно идёт через порт 110, а почтовый протокол IMAP работает через порт 143; но данные, приходящие через эти порты, обрабатывает один и тот же почтовый сервер.
У каких-то процессов порты могут работать, но быть закрыты для доступа извне. Например, внешний доступ к базе данных может быть закрыт, дверь заколочена. Однако приложения, работающие на том же сервере могут иметь доступ к БД: веб-проект может отправить внутренний запрос к базе данных: для этого нужно указать порт этой БД.
Номера портов для серверных приложений можно изменить, но традиционно веб-приложения работают на порте 80 (протокол http, без шифрования) и 443 (протокол https, шифрованное соединение), ftp — на 21 порте, ssh — на 22. Свои стандартные порты есть и для других популярных серверных приложений.

Где порт?

Ваш Django-проект работает на порте 8000, и если отправить на сервер запрос без указания порта — сервер не ответит: если в http-запросе порт не указан явно — он по умолчанию направляется на порт 80.
Решить эту проблему можно так: по внутренней сети («внутри бизнес-центра») перенаправить запрос с 80 порта на 8000: именно от этого порта ждёт запросов ваше веб-приложение.
Это перенаправление сделает веб-сервер nginx.

nginx

HTTP-сервер nginx принимает HTTP-запросы и решает, что с ними делать: nginx умеет раздавать статические файлы, перенаправлять запросы, кэшировать результат. Со всеми этими задачами nginx справляется отлично — он быстрый и гибко настраиваемый.
На nginx не получится создать сервер с какой-то сложной логикой, он умеет раздавать только статические файлы. Поэтому nginx должен работать в связке с другим веб-сервером, который отвечает за логику.
Распределение обязанностей будет таким:
  • если нужно отдать статический файл или перенаправить запрос, мы поручаем это nginx;
  • если нужно выполнить какие-то логические задачи — это возьмёт на себя WSGI-сервер (правильно, наш знакомый Gunicorn).
image
nginx будет работать как обратный прокси-сервер: он будет принимать запросы извне и перенаправлять их во внутреннюю сеть. Получив из внутренней сети ответ, nginx отправит его клиенту.
Настроим nginx так, чтобы он «слушал» (отслеживал) запросы на 80 порте и перенаправлял их на 8000 порт, где работает приложение.
Но чтобы настроить nginx — нужно, для начала, его установить.
Зайдите на удалённый сервер и установите nginx: из любой директории выполните команду
Скопировать кодBASH
sudo apt install nginx -y
Сервер nginx установлен.
Теперь нужно настроить файрвол.
Файрвол (англ. firewall: брандмауэр, стена для защиты от распространения огня, так называют программы для защиты компьютеров от вторжения) — это программа-прослойка между сервером и внешним миром, которая решает, какие запросы пропустить на сервер, а какие сразу отклонить. Файрвол закрывает все порты для доступа снаружи (чтобы все двери были заперты) и оставляет открытыми лишь те, которые явно укажет администратор.
В операционной системе Ubuntu по умолчанию установлен файрвол ufw, но пока что он выключен. Настройте и включите его.
В настройках надо разрешить запросы по протоколам http, https и ssh:
Скопировать кодBASH
sudo ufw allow 'Nginx Full' sudo ufw allow OpenSSH
Команда sudo ufw allow 'Nginx Full'разрешит принимать запросы на порты — 80 и 443: на них по умолчанию приходят запросы по http и https.
Команда sudo ufw allow OpenSSH открывает порт 22 — это стандартный порт для соединения по ssh. Если этот порт не открыть, то после запуска файрвола доступ по ssh будет заблокирован: замок защёлкнулся, а ключ остался внутри.
Теперь нужно включить файрвол:
Скопировать кодBASH
sudo ufw enable
Проверьте внесённые изменения:
Скопировать кодBASH
sudo ufw status
ufw сообщит вам, что у него всё в порядке и доложит об открытых портах:
image
Запустите nginx:
Скопировать кодBASH
sudo systemctl start nginx
Откройте в браузере IP-адрес своего сервера, на экране отобразится такая страница:
image
Это значит, что nginx запустился на 80 порту, он отслеживает и обрабатывает все запросы.
Но сейчас nginx отдаёт свою стандартную html-страницу: про ваш Django-проект nginx ничего не знает, запросы не доходят до проекта.
Следующая задача — настроить nginx так, чтобы он перенаправлял запросы по внутренней сети на порт 8000. Обращение к этому порту увидит Gunicorn — и передаст запрос в Django-проект.

Подготовить Django-проект

Для того, чтобы nginx правильно работал, статические файлы (картинки, шрифтовые и стилевые файлы) должны быть собраны в отдельную папку, а в конфиге nginx должен быть указан путь к этой директории.
В Django есть встроенная команда, которая собирает всю «статику» проекта и кладет её в определенную папку. Вы решали эту задачу в курсе по Django, но если этого не сделано — проделайте это сейчас.
Опишите в settings.py вашего Django-проекта настройки для статики:
Скопировать кодPYTHON
STATIC_URL = '/static/' # префикс для url STATIC_ROOT = os.path.join(BASE_DIR, 'static/') # папка, в которой будет лежать статика
И выполните команду:
Скопировать кодPYTHON
python manage.py collectstatic
Вся статика будет собрана в директорию static/.

Настроить nginx

Измените конфигурационный файл nginx. Откройте его в nano:
Скопировать кодBASH
sudo nano /etc/nginx/sites-enabled/default
Измените настройки:
Скопировать кодBASH
# инструкции для nginx server { # следи за портом 80 на сервере с IP <ваш-ip> listen 80; server_name <ваш-ip>; # если в адресе запроса есть аргумент '/static/' - верни файл из директории static/ location /static/ { root /home/<имя_пользователя>/<название_проекта>/; } # медиа файлы location /media/ { root /home/<имя_пользователя>/<название_проекта>/; } # любой другой запрос передай серверу Gunicorn location / { include proxy_params; # передавать запросы нужно на внутренний IP на порт 8000 proxy_pass http://127.0.0.1:8000; } }
IP 127.0.0.1 — это зарезервированный IP, по которому любой процесс может обратиться к тому компьютеру (серверу), на котором он запущен. Это адрес «внутренней сети», по которой данные передаются между приложениями на одном сервере. Именно здесь и применяются порты, открытые только «внутрь».

Предстартовая подготовка и запуск nginx

Протестируйте работоспособность новой конфигурации — нет ли синтаксических ошибок в конфиге. Вы могли допустить опечатку или что-то сделать не так — и после перезапуска всё упадет.
Скопировать кодBASH
sudo nginx -t # текст успешной проверки: # nginx: the configuration file /etc/nginx/nginx.conf syntax is ok # nginx: configuration file /etc/nginx/nginx.conf test is successful
Если ошибок не найдено — перезапустите nginx, чтобы конфигурация вступила в силу. Это можно сделать двумя способами — командой restart или reload. Лучше использовать reload: эта команда проверит конфигурацию, дождется окончания обработки всех запросов, и после этого мягко перезагрузит сервер.
Скопировать кодBASH
sudo nginx -s reload
Снова зайдите на сайт, но не указывайте порт.
Работает, вы настроили проксирование запросов через nginx!