دیپلوی پروژه Django با استفاده از Nginx، Systemd و Gunicorn بر روی سرور Ubuntu

هدف از نوشتن این مطلب در حال اجرا نگه‌داشتن پروژه بر روی سرور به صورت بهینه است به شکلی که اگر ترمینال سیستم خود را می‌بندید یا سرور خود را restart می‌کنید پروژه شما همچنان قابل اجرا باشد.

سرویس systemd در واقع یک پکیج مدیریت سرویس می‌باشد که در ابتدای بوت شدن سیستم‌عامل اجرا شده و توانایی کنترل و مدیریت پروسه‌ها را دارا می‌باشد.

سرویس Gunicorn ساخته شده تا با web server های زیادی در تعامل باشد و این توانایی را دارد تا از طریق رابط WSGI وظیفه ارتباط بین web server و web application ها را بر عهده بگیرد. پس Gunicorn پروژه شما را در دل خود جای می‌دهد و آن را مدیریت می‌کند. و ما برای اداره کردن Gunicorn از systemd یا ابزارهای دیگر استفاده می‌کنیم.

یکی از ابزار‌های مشهور برای مدیریت Gunicorn سرویس supervisor است.

برای داشتن یک دید بهتر به تصویر زیر نگاهی بیاندازیم:

فرض بر این است که پروژه شما کاملا قابل اجرا از طریق Nginx می باشد و بدون مشکل کار می‌کند اگر تا به اینجای کار با مشکل مواجه هستید کافی‌است پست «دیپلوی پروژه جنگو روی سرور ابوتنو لینوکس با استفاده از انجین‌ایکس» با دقت مشاهده و اجرا کنید تا برای اجرای دستورات این مرحله آماده شوید.


ابتدا env پروژه خود را به حالت activate در بیاوردید(من از نام rezaenv استفاده می‌کنم).

دستور زیر را برای نصب Gunicorn در ترمینال وارد کنید:

pip install gunicorn

یا

pip3 install gunicorn

دستور gunicorn --version را استفاده کنید تا ورژن نصب شده را ببینید.

حالا وارد آدرس rezaenv/bin شوید و دستور ll را وارد کنید تا فایل gunicorn ایجاد شده را ببینید:

اگر Gunicorn را زمانی نصب کنید که در حالت env activate نیستید، این فایل ایجاد نمی‌شود.
فایل‌بندی پروژه وب اپلیکیشن جنگو
فایل‌بندی پروژه وب اپلیکیشن جنگو




حال وارد آدرس rezaproject/reza شده و فایل settings.py را با دستور

 sudo nano settings.py 

ویرایش می‌کنیم:

اگر IP سرور ما در حال حاضر 185.239.107.157 باشد:

ALLOWED_HOSTS = [&quot185.239.107.157&quot, &quotlocalhost&quot, &quot127.0.0.1&quot]
دقت کنید localhost حتما باید در بین آدرس‌های وارد شده باشد.

برای تست کردن Gunicorn ابتدا به آدرس rezaproject بروید و از دستور زیر استفاده کنید:

gunicorn --bind 0.0.0.0:8000 reza.wsgi

پس می‌توانید آدرس سایت را وارد کرده و تست کنید.

حالا deactivate کنید و از محیط env خارج شوید.

حالا قصد داریم تا از طریق systemd سرویس Gunicorn را تنظیم و مدیریت کنیم. این کار بوسیله یک Socket انجام می‌شود که سرعت بالایی نسبت به حالت network آن دارد. یعنی nginx که یک request از طریق یک client دریافت کرده از طریق یک سوکت با gunicorn صحبت می‌کند و gunicorn نیز با Django app ما.

پس به آدرس زیر می‌رویم:

cd /etc/systemd/system/

با دستور touch دو فایل gunicorn.socket و gunicorn.service را ایجاد می‌کنیم.

touch gunicorn.socket
touch gunicorn.service

ابتدا socket را با sudo nano gunicorn.socket کانفیگ می‌کنیم طبق دستور زیر:

/etc/systemd/system/gunicorn.socket

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

با ctl + x آن را save می‌کنیم و خارج می‌شویم.

و سپس sudo nano gunicorn.service:

/etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/rezaproject
ExecStart=/home/ubuntu/rezaenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          reza.wsgi:application

[Install]
WantedBy=multi-user.target

ذخیره کرده و خارج شوید.

دقت کنید User=ubuntu باید دقیقا همان کاربری باشد که شما با آن وارد سرور شدید.

دستور زیر را وارد کنید تا gunicorn بتواند به محتوای پروژه شما دسترسی داشته باشد:

sudo chown -R ubuntu:www-data ~/rezaproject

حال برای راه‌اندازی gunicorn به روش زیر عمل می‌کنیم(ترتیب اجرا بسیار مهم می‌باشد):

sudo systemctl daemon-reload
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

و برای تست سوکت آن :

sudo systemctl status gunicorn.socket
برای اطمینان این مورد را نیز تست کنید: sudo systemctl status gunicorn

در صورتی که gunicorn.service هنوز ران نشده است دستور زیر را وارد کنید و دوباره status هار را چک کنید:

sudo systemctl enable gunicorn.service

حال که کار ما با Gunicorn تمام شده به سراغ تغییرات Nginx می‌رویم، پس به آدرس و فایل زیر می‌رویم:

sudo nano /etc/nginx/nginx.conf

و تغییرات را به شکل زیر اعمال می‌کنیم:

events {

}

http {
    server {
        server_name 185.239.107.157;
        listen 9003;
        location / {
            include proxy_params;
            proxy_pass http://unix:/run/gunicorn.sock;
        }
    }
}

ذخیره کنید و خارج شوید.

توجه کنید server_name آدرس ip سرور، یا نام دامین سرور شما می‌باشد ‌و listen پورتی است که شما مایل هستید تا به همراه آدرس توسط request ها call شود.

دستور sudo nginx -t را وارد کنید تا از syntax فایل nginx.conf مطمئن شوید:

و سپس nginx را restart کنید:

sudo systemctl restart nginx

حال می‌توانید پروژه خود را روی آدرسی شبیه به http://185.239.107.157:9003 مشاهده کنید.

مطمئن باشید با خارج شدن از ترمینال مک یا لینوکس خود یا reboot و reset شدن سرور، پروژه شما دوباره run خواهد شد و این اتفاق با همکاری تمامی این عناصر خواهد بود.

پایان.