Skip to content
VDS · المواقع وخوادم الويب

تطبيق Python: gunicorn وsystemd

تشغيل Django أو Flask أو FastAPI على VDS: البيئة الافتراضية، وgunicorn مع socket، وخدمة systemd، واختيار عدد العمال حسب مستواك.

آخر تحديث 23 أغسطس 2026

خادم التطوير المدمج (manage.py runserver، flask run) غير مصمم لأحمال الإنتاج. على VPS، تقوم بتثبيت gunicorn أو uvicorn، ويقوم خادم ويب بتقديمهما خارجيًا.

البيئة

لا تثبّت حزم المشروع في Python النظام أبدًا — فتحديث النظام سيعطّل التطبيق.

apt install -y python3 python3-venv python3-pip
useradd -r -m -d /srv/app -s /usr/sbin/nologin appuser

sudo -u appuser python3 -m venv /srv/app/venv
sudo -u appuser /srv/app/venv/bin/pip install -r /srv/app/requirements.txt
sudo -u appuser /srv/app/venv/bin/pip install gunicorn

بالنسبة إلى FastAPI، ثبّت بالإضافة إلى ذلك uvicorn[standard] — إذ يشغّله gunicorn كفئة عامل.

الخدمة

/etc/systemd/system/myapp.service:

[Unit]
Description=Python app
After=network-online.target postgresql.service

[Service]
User=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/srv/app/venv/bin/gunicorn \
  --workers 3 \
  --bind unix:/run/myapp/gunicorn.sock \
  --access-logfile - \
  myproject.wsgi:application
RuntimeDirectory=myapp
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

بالنسبة إلى FastAPI، استبدل سطر التشغيل بـ --worker-class uvicorn.workers.UvicornWorker app.main:app.

systemctl daemon-reload
systemctl enable --now myapp
journalctl -u myapp -f

ينشئ RuntimeDirectory=myapp المسار /run/myapp بالصلاحيات المطلوبة عند كل تشغيل — وإلا فلا يوجد مكان لوضع المقبس فيه.

عدد العمال

الصيغة المعتادة هي 2 × cores + 1، لكنها تصطدم بحدود الذاكرة: إذ يستهلك كل عامل Django ما بين 80 و200 ميغابايت.

المستوىالأنويةالعمال
VDS-112
VDS-223
VDS-345
VDS-469

إذا كان التطبيق يقضي وقتًا طويلًا في انتظار الشبكة وقاعدة البيانات، فأضف --threads 2 بدلًا من زيادة عدد العمليات.

خادم الويب

location / {
    proxy_pass http://unix:/run/myapp/gunicorn.sock;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

location /static/ { alias /srv/app/static/; }

قدّم ملفات Django الثابتة مباشرة عبر Nginx بعد جمعها: collectstatic. فتمريرها عبر Python يضيف حملًا غير ضروري.

الأخطاء الشائعة

العَرَضالسبب
502 وconnect() to unix:... failed (13)لا يملك Nginx صلاحيات على المقبس — اضبط --umask 007 ومجموعة مشتركة
ModuleNotFoundErrorالتشغيل بـ Python النظام بدلًا من venv
DisallowedHost في Djangoلم يُضف النطاق إلى ALLOWED_HOSTS
يُقتل العمال بسبب المهلةطلب طويل — زد --timeout، وانقل الأعمال الثقيلة إلى قائمة انتظار
توقف كل شيء بعد إصدار جديدنسيت systemctl restart myapp — فالكود في الذاكرة لا يحدّث نفسه

احفظ الأسرار في EnvironmentFile بصلاحيات 600، لا في settings.py. فملف الإعدادات سينتهي به المطاف في المستودع عاجلًا أو آجلًا.