Модуль 39

Деплой FastAPI (Linux, Nginx, Gunicorn)

Ось готовий урок, створений за твоїм майстер-промптом.


🎓 Урок: Деплой FastAPI (Linux, Nginx, Gunicorn)

Привіт, друзі! 👋 Це CS50 (умовно 😉), і сьогодні ми виходимо з вашої затишної кімнати у відкритий космос Інтернету.


1. 🔥 Вступ: Коли localhost більше недостатньо

Уявіть ситуацію. Ви написали геніальний API на FastAPI. На вашому ноутбуці все літає: ви пишете uvicorn main:app --reload, відкриваєте браузер, і магія працює. Ви показуєте це другу на своєму екрані — він у захваті.

Але тут друг каже: «Круто! Скинь посилання, я зайду з телефону, поки їду додому».

І тут... тиша. Ви розумієте, що адреса http://127.0.0.1:8000 працює тільки всередині вашого комп’ютера. Як тільки ви закриєте кришку ноутбука — сервер помре.

Питання до вас: Чи можна просто залишити ноутбук увімкненим назавжди і дати другу вашу домашню IP-адресу? Технічно — так. Але чи це безпечно? Чи витримає ноутбук 1000 друзів одночасно? А якщо вимкнуть світло?

Саме тому нам потрібен Деплой. Нам потрібен професійний сервер, який працює 24/7, захищений і швидкий.

Аналогія з рестораном: 🍝 * Локальна розробка — це коли ви готуєте вечерю на власній кухні для сім'ї. Все просто, по-домашньому. * Продакшн (Production) — це відкриття справжнього ресторану. Вам потрібен адміністратор на вході (Nginx), шеф-кухар, який керує процесами (Gunicorn), і кухарі, які швидко готують їжу (Uvicorn/FastAPI).

Сьогодні ми побудуємо цей ресторан.


2. 🧠 Теоретична база: Хто є хто?

Давайте розберемо наш «персонал», не заглиблюючись у нудні визначення, а зрозуміємо суть.

1. Linux (Ubuntu) 🐧

Це будівля вашого ресторану. Фундамент. Більшість серверів у світі працюють на Linux. Вам не обов'язково бути гуру Linux, але базові команди знати треба, щоб «вмикати світло» і «відкривати двері».

2. Gunicorn та Uvicorn ⚡️

Тут часто плутаються. * FastAPI — це рецепт. * Uvicorn — це кухар, який вміє готувати асинхронно (дуже швидко). Але він "одинак". Якщо він впаде, кухня зупиниться. * Gunicorn — це суворий менеджер (Process Manager). Він наймає кількох кухарів (кілька процесів Uvicorn). Якщо один кухар «зависне» або впаде, Gunicorn миттєво замінить його новим. Він відповідає за стабільність.

Запам’ятайте: У продакшені ми запускаємо Gunicorn, який всередині себе керує Uvicorn workers.

3. Systemd ⚙️

Це «привид» опери. Системна служба Linux. Навіщо? Якщо сервер перезавантажиться (наприклад, оновлення), Systemd автоматично запустить Gunicorn. Вам не треба заходити і писати команди вручну. Він робить ваш сайт безсмертним (поки працює сервер).

4. Nginx 🚦

Це Реверс-проксі (Reverse Proxy). Це ваш хостес або охоронець на вході. Він стоїть перед Gunicorn і приймає всі запити від клієнтів. Чому не пускати людей одразу до Gunicorn? * Безпека: Nginx краще тримає удар від хакерів. * Швидкість: Він миттєво віддає картинки та файли (static files), не турбуючи Python. * SSL: Саме Nginx перетворює http на безпечний https із замочком 🔒.


3. 🧪 Приклади: Будуємо крок за кроком

Припустимо, у вас вже є орендований VPS (віртуальний сервер) на Ubuntu і ви підключилися до нього через термінал.

Крок 1. Найпростіший додаток

Створимо папку і файл. (Я очікую, що ви знаєте Python, тому код мінімальний).

# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Привіт, це мій перший деплой!"}

Якщо ви зараз запустите uvicorn main:app, це буде "домашня кухня". Йдемо далі.

Крок 2. Налаштування Gunicorn + Systemd (Робимо "Безсмертя")

Ми створимо спеціальний файл-інструкцію для Linux, щоб він знав, як запускати ваш сайт.

Файл: /etc/systemd/system/myapi.service

[Unit]
Description=Gunicorn instance to serve FastAPI
After=network.target

[Service]
User=root
WorkingDirectory=/root/my-project
# Ось тут магія: Gunicorn запускає Uvicorn воркери
ExecStart=/usr/local/bin/gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000

[Install]
WantedBy=multi-user.target

Що тут відбувається? * -w 4: Ми найняли 4 "кухарів" (воркерів). * -k uvicorn...: Ми сказали Gunicorn'у використовувати саме Uvicorn, бо FastAPI асинхронний. * bind: Слухаємо порт 8000.

Тепер ми кажемо Linux: "Запам'ятай і запусти!"

sudo systemctl start myapi
sudo systemctl enable myapi

Питання до вас: Якщо я зараз перезавантажу сервер командою reboot, чи підніметься сайт сам? Відповідь: Так! Завдяки команді enable.

Крок 3. Налаштування Nginx (Відкриваємо парадні двері)

Зараз сайт доступний на порту 8000. Це некрасиво. Ми хочемо просто заходити по IP або домену (порт 80 стандартний).

Створюємо конфіг /etc/nginx/sites-available/myapi:

server {
    listen 80;
    server_name 203.0.113.1; # Тут буде ваша IP або домен

    location / {
        proxy_pass http://127.0.0.1:8000; # Перенаправляємо на Gunicorn
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Логіка проста: 1. Користувач стукає у порт 80 (Nginx). 2. Nginx бачить це і "перекидає" (proxy_pass) запит на порт 8000, де сидить наш Gunicorn. 3. Користувач навіть не знає, що там є порт 8000.

Залишилось зробити "символічне посилання" (увімкнути сайт) і перезапустити Nginx:

sudo ln -s /etc/nginx/sites-available/myapi /etc/nginx/sites-enabled
sudo systemctl restart nginx

🎉 Вуаля! Введіть IP адресу в браузер. Ви побачите {"message": "Привіт..."}.


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

Час бруднити руки. Виконайте ці завдання на вашому тестовому сервері (або віртуальній машині).

  1. 🔹 Повторення: Пройдіть весь шлях вище. Добийтеся, щоб по IP-адресі відкривався JSON-відповідь.
  2. 🔹 Зміна умов: Змініть кількість воркерів у Gunicorn з 4 на 1. Перезапустіть службу (systemctl restart myapi). Чи змінилося щось візуально? (Спойлер: ні, але під капотом змінилося навантаження, яке сервер може витримати).
  3. 🔹 Виправлення помилки (Симуляція):
    • Зупиніть Gunicorn (systemctl stop myapi).
    • Зайдіть на сайт. Ви побачите помилку 502 Bad Gateway.
    • Завдання: Поясніть своїми словами, чому саме Nginx віддав цю помилку? Хто "винен"?
  4. 🔹 А що, якщо...
    • Змініть порт у Gunicorn на 8001, але НЕ міняйте конфіг Nginx.
    • Що буде? Як це виправити? (Синхронізуйте порти).
  5. 🔹 Міні-кейс: Додайте в main.py новий ендпоінт /health, який повертає {"status": "ok"}. Оновіть код на сервері і змусьте Gunicorn побачити зміни без повного перезавантаження сервера. (Підказка: достатньо рестарту сервісу).

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

Як відрізнити новачка від профі при деплої?

❌ Помилка новачка:

Запускають uvicorn main:app --host 0.0.0.0 --port 80 прямо в консолі, використовуючи screen або tmux, і йдуть спати. Чому це погано? Процес впаде — сайт впаде. Сервер перезавантажиться — сайт не встане. Немає логів, немає масштабування. Це "милиця".

✅ Як думає інженер:

  1. "Все має бути автоматизовано". Я не хочу запускати нічого руками після рестарту. Тому Systemd.
  2. "Розділяй і володарюй". Python має займатися кодом, а Nginx — статикою і SSL. Не змушуйте Python віддавати картинки — він це робить повільно.
  3. "Де мої логи?". Якщо щось зламалося, профі не тицяє навмання. Він пише: journalctl -u myapi -f (читає логи сервісу в реальному часі) або дивиться /var/log/nginx/error.log.

Порада: Завжди перевіряйте конфіг Nginx перед перезапуском командою sudo nginx -t. Це вбереже вас від падіння всього сервера через одну пропущену крапку з комою.


6. 🧩 Підсумок

Отже, що ми сьогодні зробили? Ми перетворили домашню заготовку на професійний сервіс.

  • Тепер ви знаєте, що Gunicorn — це менеджер процесів.
  • Ви знаєте, що Nginx — це захисник і проксі.
  • Ви вмієте налаштовувати Systemd, щоб ваш код працював вічно (ну, майже).

Ваш API тепер живе в Інтернеті. Але... Чи помітили ви, як багато ручної роботи? Редагування файлів, налаштування шляхів... А якщо треба перенести це на інший сервер? Знову все руками?

На наступному занятті ми дізнаємося, як запакувати весь цей "ресторан" у контейнер, який можна розгорнути де завгодно однією командою.

🚀 Далі буде: Docker та Docker Compose.

А поки — успішного деплою! Не забудьте sudo systemctl restart... 😉