Модуль 22

Nginx + Django

Ось готовий урок, створений у стилі CS50: енергійний, зрозумілий, з акцентом на "чому" і "як", українською мовою.


🎓 Урок: Nginx + Django. Як вийти в "великий світ"

Привіт! Радий бачити вас на цьому уроці. Сьогодні ми перетворимо ваш "домашній" проєкт на Django на справжній "бойовий" сервіс, готовий приймати тисячі користувачів.


1. 🔥 Вступ: проблема та мотивація

Уявіть ситуацію. Ви написали крутий стартап на Django. На вашому ноутбуці все літає. Ви запускаєте команду python manage.py runserver, відправляєте посилання другу — все працює. Ви щасливі.

Але тут ви вирішуєте запустити цей проєкт у реальний світ. На сайт заходить 100 людей одночасно. І що відбувається? Сайт "лягає". Картинки не вантажаться, сторінки відкриваються вічність, а сервер починає диміти (метафорично, звісно).

Чому так сталося? Бо runserver у Django — це як мікрохвильовка. Вона чудова, щоб швидко розігріти собі обід (розробити код), але ви не зможете нагодувати весілля на 200 осіб, використовуючи лише одну мікрохвильовку. Вам потрібна професійна кухня.

У світі веб-серверів цією "професійною кухнею" є зв’язка Nginx + Gunicorn.

Питання до вас: Як ви думаєте, чи варто змушувати геніального шеф-кухаря (Django/Python) самому носити тарілки клієнтам і мити посуд? Звісно, ні. Його робота — готувати логіку. А доставкою і "посудом" (статичними файлами) має займатися хтось інший.

Сьогодні ми наймемо цього "іншого".


2. 🧠 Теоретична база (без сухої академічності)

Давайте розберемо архітектуру. Нам потрібно зрозуміти три компоненти.

🏛 1. Django (The Brain)

Це ваш код на Python. Він геніальний, але повільний у простих речах. Він знає, як дістати дані з бази, але дуже погано вміє віддавати картинки чи CSS-файли.

🦄 2. Gunicorn (The Translator)

Веб-світ розмовляє мовою HTTP. Django розмовляє мовою Python. Вони не розуміють одне одного напряму. Gunicorn — це WSGI-сервер (Web Server Gateway Interface). Уявіть його як перекладача. Він бере HTTP-запит з інтернету, перетворює його на виклик Python-функції для Django, чекає відповідь і перекладає її назад у HTTP.

🚦 3. Nginx (The Traffic Controller)

Це наш герой сьогодні. Nginx (читається "Енджин-екс") — це реверс-проксі.

Аналогія з рестораном: * Django — це Шеф-кухар на кухні (готує складні страви). * Gunicorn — це офіціант (передає замовлення від залу до кухні). * Nginx — це хостес (адміністратор) на вході.

Що робить Nginx (Хостес)? 1. Зустрічає гостей (клієнтів з інтернету). 2. Якщо гість хоче просто води (картинку, CSS, JS) — Nginx дає це миттєво сам, не турбуючи Шефа (Django). Це важливо! 3. Якщо гість хоче складну страву (сторінку з даними з БД) — Nginx направляє його до офіціанта (Gunicorn), який біжить до Шефа. 4. Захищає кухню від хуліганів (DDoS-атаки, зайві запити).

💡 Запам'ятайте головне: Nginx стоїть "на передовій". Він приймає удар першим. Django працює лише тоді, коли це дійсно потрібно.


3. 🧪 Приклади (від простого до реального)

Давайте налаштуємо це крок за кроком.

Етап 0: Підготовка

У вас є Django-проєкт. Ви звикли робити так:

python manage.py runserver

Забудьте про це на продакшені. Це небезпечно і повільно.

Етап 1: Встановлюємо Gunicorn

Спочатку замінимо runserver на Gunicorn.

pip install gunicorn
# Запуск (уявімо, що ваш проект називається myproject)
gunicorn myproject.wsgi:application --bind 0.0.0.0:8000

Тепер ваш сайт працює швидше і стабільніше. Але... Стоп. Де всі стилі? Сайт виглядає як "голий" HTML 90-х років.

Чому? Бо Gunicorn не вміє віддавати статичні файли (CSS, зображення). Це не його робота.

Етап 2: Підключаємо Nginx (Магія починається)

Нам потрібно сказати Nginx: "Друже, все, що починається на /static/, віддавай сам із папки, а решту — передавай на Gunicorn".

Створимо конфіг файл для сайту (/etc/nginx/sites-available/myproject):

server {
    listen 80;
    server_name mydomain.com;  # Або ваша IP-адреса

    # 1. Запит на Favicon (іконку) - ігноруй помилки, не пиши в лог
    location = /favicon.ico { access_log off; log_not_found off; }

    # 2. Робота зі статикою (CSS, JS, Images)
    # Коли хтось просить /static/..., Nginx лізе в папку на диску
    location /static/ {
        alias /home/user/myproject/static/;
    }

    # 3. Все інше - відправляємо на Gunicorn
    location / {
        include proxy_params;
        proxy_pass http://127.0.0.1:8000; # Тут слухає Gunicorn
    }
}

Що тут відбулося? Ми розділили потоки. Легкі завдання (файли) Nginx робить сам, важкі (логіка) — віддає далі.


4. 🛠 Практична частина

Час забруднити руки кодом! Виконайте ці завдання:

🔹 Завдання 1: "Збери статику"

Перш ніж Nginx зможе щось віддати, файли мають бути в одній купі. 1. У settings.py переконайтеся, що є STATIC_ROOT = os.path.join(BASE_DIR, 'static'). 2. Виконайте команду: python manage.py collectstatic. 3. Перевірте, чи з'явилася папка static у корені проєкту.

🔹 Завдання 2: "Запуск Gunicorn"

Запустіть Gunicorn, щоб він слухав тільки локально (назовні його не має бути видно):

gunicorn --workers 3 myproject.wsgi:application --bind 127.0.0.1:8000

(Чому 3 воркери? Формула: (2 x к-сть ядер CPU) + 1. Це оптимально для паралельної роботи).

🔹 Завдання 3: "Налаштування Nginx"

  1. Встановіть Nginx (sudo apt install nginx).
  2. Створіть конфіг (як у прикладі вище).
  3. Зробіть лінк: sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled.
  4. Перевірте конфіг на помилки: sudo nginx -t (Якщо побачите "successful" — ви молодець!).
  5. Перезапустіть Nginx: sudo systemctl restart nginx.

🔹 Завдання із зірочкою (Mini-case):

Уявіть, що ваш сайт почав спамити якийсь бот з IP 123.123.123.123. Завдання: Додайте в конфіг Nginx правило, щоб заблокувати доступ саме цьому IP. (Підказка: гугліть nginx deny ip).


5. 💡 Мислення як у розробника

Як відрізнити новачка від профі в цій темі?

❌ Новачок: * Запускає runserver на AWS і дивується, чому його зламали. * Намагається змусити Django віддавати відео-файли через Python (це вбиває CPU). * Забуває робити collectstatic після зміни CSS і думає, що браузер "кешує".

✅ Профі (Developer Mindset): * Делегування: Профі знає: Python — дорогий ресурс. Nginx (C++) — дешевий. Все, що можна віддати Nginx (кешування, стиснення Gzip, SSL, статика), віддається йому. * Безпека: Профі ніколи не відкриває порт 8000 назовні. Тільки порт 80 (HTTP) або 443 (HTTPS), які контролює Nginx. * Логи: Якщо щось не працює, профі не вгадує. Він йде в /var/log/nginx/error.log і читає, що сталося.

Порада: Якщо ви бачите помилку "502 Bad Gateway" — це означає, що Nginx працює, але Gunicorn (офіціант) впав або спить. Nginx стукає у двері, а йому ніхто не відчиняє.


6. 🧩 Підсумок

Отже, що ми сьогодні зробили? 1. Зрозуміли, що Django — це кухар, а не офіціант. 2. Познайомилися з Gunicorn — перекладачем між Web і Python. 3. Налаштували Nginx — потужний щит і розподільник трафіку.

Тепер ваш додаток готовий до навантажень. Він працює швидко, безпечно і виглядає правильно.

Що далі? Зараз ваш сайт працює по HTTP (небезпечно, як листівка без конверта). На наступному занятті ми прикрутимо SSL-сертифікат (HTTPS) за допомогою Let's Encrypt, щоб у браузері з'явився той самий зелений замочок 🔒.

А поки — спробуйте "покласти" свій локальний Nginx навантаженням. Спойлер: у вас навряд чи вийде. 😉

Успіхів у коді!