איך לשרת אפליקציות Flask עם Gunicorn ו-Nginx על Ubuntu 22.04

A previous version of this tutorial was written by Kathleen Juell.

הקדמה

במדריך זה, תבנו אפליקציה ב-Python באמצעות הפריימוורק Flask על Ubuntu 22.04. רוב המדריך יתמקד בכיצד להגדיר את שרת היישום Gunicorn וכיצד להשיג את האפליקציה ולהגדיר את Nginx לפעול כפרוקסי הפוך מקדמי.

נדרשים מראש

לפני התחלת המדריך, עליכם להיות ברשותכם:

  • שרת עם Ubuntu 22.04 מותקן ומשתמש לא מקורי עם הרשאות sudo. ניתן לעקוב אחר המדריך שלנו להגדרת השרת הראשונית להכוונה.

  • Nginx מותקן, עוקבים אחר השלבים 1 ו-2 של איך להתקין את Nginx על Ubuntu 22.04.

  • שם דומיין מוגדר להפנות אל השרת שלך. ניתן לרכוש דומיין בNamecheap או לקבל אחד בחינם בFreenom. ניתן ללמוד כיצד להפנות דומיינים אל DigitalOcean על ידי מעקב אחר תיעוד רלוונטי על דומיינים ו-DNS. וודא שאתה יוצר את הרשומות DNS הבאות:

    • רשומת A עם your_domain מפנה אל כתובת ה-IP הציבורית של השרת שלך.
    • רשומת A עם www.your_domain מפנה אל כתובת ה-IP הציבורית של השרת שלך.
  • ידע על תקן ה-WSGI, שבו ישתמש השרת Gunicorn כדי לתקשר עם אפליקציית ה-Flask שלך. דיון זה מכסה את WSGI בפרטיות יותר.

שלב 1 — התקנת הרכיבים ממאגרי המידע של Ubuntu

השלב הראשון יהיה להתקין את כל הרכיבים הנדרשים ממאגרי המידע של Ubuntu. זה כולל pip, מנהל החבילות של פייתון, שינהל את רכיבי הפייתון. תקבל גם את קבצי הפיתוח של פייתון הנדרשים לבניית חלק מרכיבי Gunicorn.

ראשית, עדכן את אינדקס החבילות המקומי והתקן את החבילות שיאפשרו לך לבנות את סביבת הפייתון שלך. אלו יכלול את python3-pip, יחד עם מספר נוספים של חבילות וכלי פיתוח הנדרשים לסביבת תכנות עמידה:

  1. sudo apt update
  2. sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

עם החבילות הללו במקום, השלב הבא הוא ליצור סביבה וירטואלית עבור הפרוייקט שלך.

שלב 2 — יצירת סביבת פייתון וירטואלית

באופן הבא, תגדיר סביבת וירטואלית כדי לבדל את אפליקציית ה-Flask מקבצי הפייתון האחרים במערכת שלך.

התחל על ידי התקנת החבילה python3-venv, שתתקין את המודול venv:

  1. sudo apt install python3-venv

הבא, צור ספריית הורה עבור פרוייקט Flask שלך. נעבור אל הספרייה עם פקודת cd לאחר שתיצור אותה:

  1. mkdir ~/myproject
  2. cd ~/myproject

צור סביבת וירטואלית כדי לאחסן את דרישות ה-Python של פרויקט Flask שלך על ידי הקלדה:

  1. python3 -m venv myprojectenv

זה יתקין עותק מקומי של Python ו-pip לתוך ספרייה בשם myprojectenv בתוך ספריית הפרויקט שלך.

לפני התקנת אפליקציות בתוך הסביבה הווירטואלית, עליך להפעיל אותה. עשה זאת על ידי הקלדה:

  1. source myprojectenv/bin/activate

ההוראות ישתנו כדי לציין שאתה פועל כעת בתוך הסביבה הווירטואלית. זה ייראה משהו כזה: (myprojectenv)user@host:~/myproject$.

שלב 3 — התקנת אפליקציית Flask

עכשיו שאתה בתוך הסביבה הווירטואלית שלך, תוכל להתקין את Flask ו-Gunicorn ולהתחיל לעבוד על עיצוב האפליקציה שלך.

ראשית, התקן את wheel עם ההתקנה המקומית של pip כדי לוודא שהחבילות שלך יתקינו גם אם ארכיוני wheel חסרים:

  1. pip install wheel

הערה

ללא קששר לגרסה של Python שאתה משתמש בה, כאשר הסביבה הווירטואלית מופעלת, עליך להשתמש בפקודת pip (ולא ב-pip3).

באשר לכך, התקן את Flask ו-Gunicorn:

  1. pip install gunicorn flask

יצירת אפליקציית דוגמה

כעת שיש לך Flask זמין, תוכל ליצור אפליקציה פשוטה. Flask הוא מסגרת מיקרו. הוא לא כולל כלים רבים שמסגרות עם יכולות מורחבות יותר עשויות לכלול, וקיים בעיקר כמודול שתוכל לייבא לפרויקטים שלך כדי לעזור לך לאתחל אפליקציית רשת.

על אף שהאפליקציה שלך עשויה להיות מורכבת יותר, ניצור את אפליקציית Flask שלנו בקובץ יחיד, שמקורא myproject.py:

  1. nano ~/myproject/myproject.py

קוד האפליקציה ישהה בקובץ זה. זה יייבא את Flask ויצור מופע של אובייקט Flask. תוכל להשתמש בזה כדי להגדיר את הפונקציות שצריך להפעיל כאשר מבוצעת בקשה לנתיב מסוים:

~/myproject/myproject.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

בגדול זה מגדיר איזה תוכן להציג כאשר מוגשת בקשה לדומיין הראשי. שמור וסגור את הקובץ כאשר תסיים.

אם עקבת אחר המדריך להגדרה ראשונית של השרת, עליך להפעיל חומת אש UFW. כדי לבדוק את האפליקציה, עליך לאפשר גישה לפורט 5000:

  1. sudo ufw allow 5000

עכשיו תוכל לבדוק את אפליקציית Flask שלך על ידי הקלדת:

  1. python myproject.py

תראה פלט דומה לזה,, כולל אזהרה מועילה שמזכירה לך שלא להשתמש בהגדרת השרת הזו בייצור:

Output
* Serving Flask app "myproject" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: off * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

בקר בכתובת ה-IP של השרת שלך והוסף אחריה :5000 בדפדפן האינטרנט שלך:

http://your_server_ip:5000

אמור לראות משהו דומה לזה:

כאשר תסיים, לחץ על CTRL-C בחלון הטרמינל שלך כדי לעצור את שרת הפיתוח של Flask.

יצירת נקודת הכניסה WSGI

השלב הבא הוא ליצור קובץ שישמש כנקודת הכניסה של היישום שלך. זה יגיד לשרת Gunicorn כיצד להתקשר עם היישום.

קרא לקובץ wsgi.py:

  1. nano ~/myproject/wsgi.py

בקובץ זה, יבא את מופע ה-Flask מהיישום שלנו ואז יפעיל אותו:

~/myproject/wsgi.py
from myproject import app

if __name__ == "__main__":
    app.run()

שמור וסגור את הקובץ כאשר אתה מסיים.

שלב 4 — הגדרת Gunicorn

היישום שלך כתוב עם נקודת כניסה שהוקצתה. אתה יכול כעת להמשיך להגדיר את Gunicorn.

לפני שתמשיך, ודא ש-Gunicorn יכול לשרת את היישום כראוי.

ניתן לעשות זאת על ידי העברת שם נקודת הכניסה של היישום. זה מורכב משם המודול (מבלי לכלול את הרחבת .py), פלוס שם הפונקציה הקריאה בתוך היישום. במקרה זה, זהו wsgi:app.

ציין גם את הממשק והפורט לקשירה באמצעות הארגומנט 0.0.0.0:5000 כך שהיישום יופעל על ממשק זמין לציבור:

  1. cd ~/myproject
  2. gunicorn --bind 0.0.0.0:5000 wsgi:app

תראה פלט כמו בדוגמה הבאה:

Output
[2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4 [2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419) [2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync [2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421

בקר בכתובת ה-IP של השרת שלך עם :5000 מחובר בסוף בדפדפן האינטרנט שלך שוב:

http://your_server_ip:5000

אתה צריך לראות את הפלט של היישום שלך:

כאשר אתה מאשר שהוא פועל כראוי, לחץ על CTRL-C בחלון הטרמינל שלך.

כאשר אתה מסיים להשתמש בסביבת הסביבה הווירטואלית, אתה יכול לנטרל אותה:

  1. deactivate

כל הפקודות של Python ישתמשו כעת בסביבת ה-Python של המערכת שוב.

הבא, צור את קובץ היחידת שירות systemd. יצירת קובץ היחידה של systemd תאפשר למערכת האיניציאליזציה של Ubuntu להתחיל את Gunicorn באופן אוטומטי ולשרת את היישום Flask בכל פעם שהשרת מתמיד:

צור קובץ יחידה שמסתיים ב־.service בתוך התיקייה /etc/systemd/system כדי להתחיל:

  1. sudo nano /etc/systemd/system/myproject.service

בפנים, תתחיל עם הקטע [Unit], שמשמש לציון מטא-נתונים ותלויות. הוסף תיאור של השירות שלך כאן ואמור למערכת האיניציאליזציה להתחיל רק את זה לאחר שהיעד של הרשת הושג:

/etc/systemd/system/myproject.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

לאחר מכן, הוסף קטע [Service]. זה יציין את המשתמש והקבוצה שבה ברצונך שהתהליך ירוץ תחתיהם. נן בבעלות החשבון הרגיל שלך על התהליך מאחר שהוא בבעלות כל הקבצים הרלוונטיים. כמו כן, תן לקבוצה להיות בבעלות של הקבוצה www-data כך ש-Nginx יוכל לתקשר בקלות עם תהליכי Gunicorn. זכור להחליף את שם המשתמש כאן עם השם שלך:

/etc/systemd/system/myproject.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data

אחר כך, יש למפות את תיקיית העבודה ולהגדיר את המשתנה הסביבתי PATH כך שמערכת האיניציאציה תדע שהפקודות הניתנות לעיבוד ממוקמות בתוך הסביבה הווירטואלית שלנו. יש לציין גם את הפקודה להפעלת השירות. הפקודה תבצע את הפעולות הבאות:

  • התחל 3 תהליכי עובד (אף על פי שכדאי להתאים את זה כפי הצורך)
  • צור וקשר לקובץ סוקט של Unix, myproject.sock, בתוך תיקיית הפרויקט שלנו. נקבע ערך של umask של 007 כך שהקובץ הסוקט ייווצר עם גישה לבעלים ולקבוצה, ויגביל גישה לאחרים
  • ציין את שם קובץ נקודת הכניסה WSGI, יחד עם הפונקציה הפיתוחית בקובץ זה (wsgi:app)

סיסטם ה-Systemd מחייב שתציינו את הנתיב המלא לקובץ הביצוע Gunicorn, שמותקן בתוך הסביבה הווירטואלית שלך.

זכור להחליף את שם המשתמש ואת נתיבי הפרויקט עם המידע שלך:

/etc/systemd/system/myproject.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

לבסוף, הוסף מקטע [Install]. זה יודיע ל-systm הקבצים לקשר את השירות הזה אם תאפשרו את התחלתו בהפעלה. תרצה שהשירות יתחיל כאשר המערכת הרגילה של המשתמשים הרבים מופעלת ופועלת:

/etc/systemd/system/myproject.service
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

עם זאת, קובץ השירות שלך ל-systmd הוא מוכן. שמור וסגור אותו כעת.

כעת ניתן להפעיל את שירות ה-Gunicorn שיצרת ולאפשר לו להתחיל באופן אוטומטי בעת הפעלת המחשב:

  1. sudo systemctl start myproject
  2. sudo systemctl enable myproject

בוא נבדוק את המצב:

  1. sudo systemctl status myproject

תראה פלט כמו זה:

Output
● myproject.service - Gunicorn instance to serve myproject Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2022-05-10 19:40:41 UTC; 9s ago Main PID: 17300 (gunicorn) Tasks: 4 (limit: 2327) Memory: 56.0M CPU: 514ms CGroup: /system.slice/myproject.service ├─17300 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app ├─17301 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app ├─17302 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app └─17303 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app May 10 19:40:41 r systemd[1]: Started Gunicorn instance to serve myproject. . . .

אם תראה שגיאות, הקפיד לפתור אותן לפני שתמשיך עם המדריך.

שלב 5 — הגדרת Nginx להעביר בקשות פרוקסי

שרת האפליקציות שלך Gunicorn כעת צריך לעמוד ולרוץ, ממתין לבקשות על קובץ הסוקט בתיקיית הפרויקט. עכשיו תוכל להגדיר את Nginx כך שיעביר בקשות אינטרנט לקובץ הסוקט הזה על ידי הוספה של קוד נוסף לקובץ ההגדרה שלו.

התחל ביצירת קובץ הגדרת שרת חדש בתיקיית sites-available של Nginx. קרא לו myproject כדי לשמור על קו ההדרכה:

  1. sudo nano /etc/nginx/sites-available/myproject

פתח קובץ בלוק שרת והגדר ל-Nginx להאזין בפורט המשתנה 80. גם הגדר להשתמש בבלוק זה לבקשות לשם הדומיין של השרת שלנו:

/etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name your_domain www.your_domain;
}

בשלב הבא, הוסף בלוק מיקום שתואם לכל בקשה. בתוך בלוק זה, תכלול את קובץ ה-proxy_params שמגדיר פרמטרים פרוקסי כלליים שצריך להגדיר. תעביר אז את הבקשות לסוקט שהגדרת באמצעות ההוראה proxy_pass:

/etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name your_domain www.your_domain;

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
    }
}

שמור וסגור את הקובץ כאשר תסיים.

כדי לאפשר את ההגדרת בלוק השרת של Nginx שיצרת עכשיו, קישור את הקובץ לתיקיית sites-enabled:

  1. sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

עם הקובץ בתיקייה ההיא, תוכל לבדוק אם יש שגיאות תחביר:

  1. sudo nginx -t

אם זה חוזר ללא ציון של כל בעיות, הפעל מחדש את תהליך ה-Nginx כדי לקרוא את ההגדרה החדשה:

  1. sudo systemctl restart nginx

סוף סוף, כוונן את הגדרות הגישה שוב. אין צורך יותר בגישה דרך פורט 5000, כך שתוכל להסיר את הכלל הזה. לאחר מכן, תוכל לאפשר גישה מלאה לשרת ה-Nginx:

  1. sudo ufw delete allow 5000
  2. sudo ufw allow 'Nginx Full'

עכשיו תוכל לגשת לשם הדומיין של השרת בדפדפן האינטרנט שלך:

http://your_domain

אתה צריך לראות את תוצאות היישום שלך:

הערה: תקבל שגיאת שער HTTP 502 אם Nginx לא יכול לגשת לקובץ הקובע של gunicorn. כללית זו כיוונית משום שספריית הבית של המשתמש לא מאפשרת למשתמשים אחרים לגשת לקבצים בתוכה.

אם שמו של הקובץ הוא /home/sammy/myproject/myproject.sock, הבטיח ש־/home/sammy מקבלת לפחות הרשאות של 0755. תוכל להשתמש בכלי כמו chmod כדי לשנות את ההרשאות כמו כך:

  1. sudo chmod 755 /home/sammy

אז רענן את העמוד כדי לראות אם שגיאת ה־HTTP 502 נעלמה.

אם תתקל בשגיאות, נסה לבדוק את הנקודות הבאות:

  • sudo less /var/log/nginx/error.log: בדוק את יומני השגיאות של Nginx.
  • sudo less /var/log/nginx/access.log: בדוק את יומני הגישה של Nginx.
  • sudo journalctl -u nginx: בדוק את יומני התהליך של Nginx.
  • sudo journalctl -u myproject: בדוק את יומני התהליך של Gunicorn של היישום שלך.

שלב 6 — מאבטח את היישום

כדי להבטיח כי תעבורה אל השרת שלך תישאר מאובטחת, נשיג תעודת SSL עבור הדומיין שלך. ישנם מספר דרכים לעשות זאת, כולל קבלת תעודה חינמית מ־Let’s Encrypt, יצירת תעודה סלפי, או רכישה מספק אחר והגדרת Nginx להשתמש בה על ידי מעקב אחר צעדים 2 עד 6 של איך ליצור תעודת SSL סלפי עבור Nginx ב־Ubuntu 22.04. נשתמש באפשרות הראשונה (Let’s Encrypt) למען המהירות.

התקן את חבילת ה־Nginx של Certbot באמצעות apt:

  1. sudo apt install python3-certbot-nginx

‏Certbot מספק מגוון של דרכים לקבלת תעודות SSL דרך תוספות. התוסף של Nginx ידאג לבצע שינויים בתצורה של Nginx ולטעון מחדש את התצורה כאשר נדרש. כדי להשתמש בתוסף זה, יש להקליד את הפקודה הבאה:

  1. sudo certbot --nginx -d your_domain -d www.your_domain

פקודה זו מפעילה את certbot עם תוסף --nginx, באמצעות -d לציון שמות לתעודה שנרצה שתהיה תקפה.

אם זה הפעם הראשונה שאתה מריץ certbot, יתבקש ממך להזין כתובת דוא"ל ולהסכים לתנאי השירות. לאחר כך, certbot יתקשר עם שרת Let’s Encrypt, ולאחר מכן יריץ את האתגר כדי לאמת שאתה שולט בדומיין שבו אתה מבקש תעודה.

אם זה מוצלח, certbot ישאל איך תרצה להגדיר את ההגדרות של HTTPS שלך:

Output
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access. ------------------------------------------------------------------------------- 1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, or if you're confident your site works on HTTPS. You can undo this change by editing your web server's configuration. ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

בחר את הבחירה שלך ואז לחץ ENTER. ההגדרה תתעדכן, ו-Nginx יטען מחדש כדי לאסוף את ההגדרות החדשות. certbot יסיים עם הודעה שתספר לך שהתהליך היה מוצלח ואיפה מאוחסנות התעודות שלך:

Output
IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/your_domain/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/your_domain/privkey.pem Your cert will expire on 2020-08-18. To obtain a new or tweaked version of this certificate in the future, simply run certbot again with the "certonly" option. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le

אם עקבת אחר הוראות ההתקנה של Nginx בתקנות הנדרשות, לא תצטרך יותר את אישור פרופיל ה-HTTP הרציני:

  1. sudo ufw delete allow 'Nginx HTTP'

כדי לאמת את ההגדרה, נווט שוב אל דומיינך, באמצעות https://:

https://your_domain

תראה שוב את תוצאות היישום שלך, יחד עם אינדיקטור האבטחה של הדפדפן שלך, שצריך לציין כי האתר מאובטח.

מסקנה

במדריך זה, יצרת ואיבטחת אפליקציה פשוטה ב־Flask בתוך סביבת פיתוח פייתון וירטואלית. יצרת נקודת כניסה WSGI כך שכל שרת אפליקציות התומך ב־WSGI יכול לשרת אותה, ואז הגדרת את שרת האפליקציות Gunicorn לספק את הפונקציה הזו. לאחר מכן, יצרת קובץ שירות systemd כדי להפעיל את שרת האפליקציות באופן אוטומטי בעת ההפעלה. יצרת גם בלוק שרת Nginx המעביר תעבורת לקוח רשת אל שרת האפליקציות, מעביר בקשות חיצוניות, ואיבטחת תעבורה לשרת שלך עם Let’s Encrypt.

Flask הוא מסגרת פשוטה מאוד, אך גמישה ביותר המיועדת לספק לאפליקציות שלך פונקציונליות מבלי להיות יותר מדי מגבילה בנוגע למבנה ולעיצוב. תוכל להשתמש במערך הכללי המתואר במדריך זה כדי לשרת את אפליקציות Flask שתפתח.

Source:
https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-ubuntu-22-04