Flask kichik va tushunarli freymvork bo'lgani uchun ko'pchilik o'zining birinchi veb-ilovasini aynan unda yozadi. Lokal kompyuterda fayl oxiridagi app.run(debug=True) qatori ilovani bir zumda ishga tushiradi va kod o'zgarganda avtomatik yangilaydi. Lekin bu ichki server ishlab chiqarish uchun mo'ljallanmagan, debug rejimi esa internetda ochiq qolsa, jiddiy xavfsizlik teshigiga aylanadi. Ushbu maqolada Flask ilovasini oddiy hostingga yoki VPS'ga to'g'ri joylash uchun nimalarni o'zgartirish kerakligini ko'rib chiqamiz.
app.run() serverda nega ishlatilmaydi
app.run() Werkzeug kutubxonasining ishlab chiqish serverini ochadi. U bitta mashinada sinash uchun qulay, ammo ko'p so'rovli yuklamani, jarayon qulashidan keyin tiklanishni va xavfsizlik nuqtai nazaridan qattiq sinovlarni hisobga olmagan. Eng katta xavf esa debug=True bilan bog'liq: bu rejimda xato sahifasida interaktiv konsol paydo bo'ladi va undan serverda istalgan Python kodini bajarish mumkin. Garchi konsol PIN kod bilan himoyalangan bo'lsa ham, uni internetga ochiq qoldirish qat'iyan tavsiya etilmaydi. Shuning uchun serverda ilova har doim alohida WSGI server orqali ishga tushadi, debug esa o'chiriladi.
Amaliy misol sifatida Farg'onadagi to'yxonaning misol.uz saytini olaylik. Saytda zallar rasmi, narxlar sahifasi va sana tanlab bron qilish formasi bor, ma'lumotlar esa kichik SQLite bazasida saqlanadi. Dasturchi ilovani Flask'da bir hafta ichida yozdi, endi uni hech narsani buzmasdan internetga chiqarish kerak.
Ilovani kirish nuqtasi bilan tartibga solish
Serverdagi har qanday WSGI server ilovani qaysi fayldan va qaysi nom bilan olishni bilishi kerak. Buning eng toza yo'li ilova fabrikasi va alohida wsgi.py faylidir. Ilova kodi app paketida, kirish nuqtasi esa loyiha ildizida turadi:
# app/__init__.py
import os
from flask import Flask
def create_app():
app = Flask(__name__, instance_relative_config=True)
app.config["SECRET_KEY"] = os.environ["FLASK_SECRET_KEY"]
app.config["DATABASE"] = os.path.join(app.instance_path, "booking.sqlite")
os.makedirs(app.instance_path, exist_ok=True)
from . import views
app.register_blueprint(views.bp)
return app
# wsgi.py
from app import create_app
app = create_app()
SECRET_KEY sessiya va formalarni imzolash uchun ishlatiladi, shuning uchun u uzun, tasodifiy va kod omboridan tashqarida bo'lishi kerak. Uni python -c "import secrets; print(secrets.token_hex(32))" buyrug'i bilan yaratib olish mumkin. SQLite fayli esa instance papkasida saqlanadi, chunki static ichiga qo'yilgan baza brauzer orqali yuklab olinishi mumkin bo'lib qoladi.
Oddiy hostingda Passenger orqali ishga tushirish
Ba'zi hosting panellari Python ilovalarni Phusion Passenger yordamida ishga tushiradi. Bunday muhitda Passenger loyiha ildizida passenger_wsgi.py faylini qidiradi va undagi application nomli obyektni ilova sifatida oladi. Fayl juda qisqa bo'ladi:
# passenger_wsgi.py
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
from app import create_app
application = create_app()
Bog'liqliklar odatda shu loyiha uchun yaratilgan virtual muhitga o'rnatiladi, ilova esa o'sha muhitdagi Python bilan ishlaydi. Kodni yangilagandan keyin Passenger'ga ilovani qayta yuklash kerakligini bildirish uchun loyiha ichida tmp/restart.txt faylini yaratish yoki uning vaqtini yangilash kifoya:
mkdir -p tmp
touch tmp/restart.txt
Har bir hosting tarifi Python'ni qo'llab-quvvatlamaydi va qo'llab-quvvatlaganlarida ham sozlash usuli farq qilishi mumkin. Tarifingizda Python ilovalarni ishga tushirish imkoniyati bor-yo'qligini va qaysi versiyalar mavjudligini sayt.uz kabinetidan yoki texnik yordam orqali aniqlab oling. Agar faqat PHP qo'llab-quvvatlanadigan tarifda bo'lsangiz, Flask uchun VPS to'g'riroq tanlov bo'ladi.
VPS'da Gunicorn va Nginx bilan ishga tushirish
VPS'da sizda to'liq nazorat bor va sozlama boshqa Python freymvorklari bilan deyarli bir xil. Virtual muhitga Gunicorn o'rnatiladi, ilova esa wsgi.py dagi app obyekti orqali ishga tushiriladi:
python3 -m venv venv
venv/bin/pip install -r requirements.txt gunicorn
venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app
Bu buyruqni systemd xizmati qilib yozasiz, shunda u server qayta yuklanganda o'zi ko'tariladi va xato bilan to'xtasa qayta ishga tushadi. Oldida esa Nginx turadi: u HTTPS'ni boshqaradi, /static/ fayllarini diskdan beradi va qolgan so'rovlarni proxy_pass http://127.0.0.1:8000; orqali Gunicorn'ga uzatadi.
Proksi ortida to'g'ri manzil va protokolni ko'rish
Ilova Nginx yoki boshqa proksi ortida ishlaganda Flask har bir so'rovni 127.0.0.1 dan oddiy HTTP orqali kelgan deb ko'radi. Natijada url_for(..., _external=True) noto'g'ri http:// havolalar yasaydi, loglarda esa barcha mijozlar bir xil IP bilan ko'rinadi. Buni Werkzeug'ning ProxyFix qatlami tuzatadi, u proksi yuborgan sarlavhalarni o'qiydi:
from werkzeug.middleware.proxy_fix import ProxyFix
app = create_app()
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
Raqamlar ilova oldida nechta proksi turganini bildiradi. Ularni haqiqiy holatdan katta qo'ymang, aks holda mijoz soxta sarlavha yuborib, o'z IP manzilini yashirishi mumkin. Shuningdek, HTTPS ishlagach sessiya cookie'larini faqat xavfsiz ulanishda yuboriladigan qilib qo'ying: SESSION_COOKIE_SECURE = True.
Joylashdan keyingi tekshiruv ro'yxati
Sayt ochilgandan so'ng bir necha narsani tekshirib chiqing. Ataylab mavjud bo'lmagan sahifani oching va xato sahifasida kod parchalari yoki konsol ko'rinmasligiga ishonch hosil qiling. Bron formasini yuborib ko'ring: agar SQLite fayliga yozish huquqi bo'lmasa, attempt to write a readonly database xatosi chiqadi va uni papka ruxsatlarini to'g'rilash bilan hal qilasiz. Rasmlar va CSS yuklanayotganini, HTTP manzil avtomatik HTTPS'ga yo'naltirilayotganini ham ko'zdan kechiring. To'yxona misolida bu tekshiruvlar bir necha daqiqa oladi, lekin mavsum boshida bronlar yo'qolib qolishining oldini oladi.