2018年2月4日 星期日

[Web] Digital Ocean升級 和 部署到One-click app時修改的 Nginx、Gunicorn 設定。

Digital Ocean 升級

之前的一篇記錄過如何在 Digital Ocean 建立一個雲端主機後,不久的某天早上在查看電郵時,留意到 Digital Ocean 為它的服務升級了。以最低價格每月5美元一個標準主機的Droplet 為例,就有以下更新:從 512MB -> 1GB RAM、 20GB -> 25GB SSD。

但如電郵標題已經講明,這是[Action Required]。這個自製網站的規模不怕暫時離線,也未看到有復原到小容量,或預留那 5GB Disk的需要,所以也沒理由不放心進行 Disk, CPU and RAM 的升級。以 Control Panel 的方式升級也非常容易。



參考:https://www.digitalocean.com/community/tutorials/how-to-resize-your-droplets-on-digitalocean

 

 Nginx、Gunicorn

Deployment 方面糾纏了幾星期終於有成果了。其實最終是趁著系統升級之前,也把心一橫來個砍掉重練,復原到一開始的主機映象。重新來按步就班的試驗,就一天內弄好了。 之前這段日子也有不少得著的,見到很多名詞如: Nginx Gunicorn, wsgi, uWSGI, uwsgi, supervisor, 等等,左試右試的弄混亂過才明白它們的關係。在這個 Ubuntu 16.04 + Django 1.8.7 的 One-Click install Image下要掛上自家的網頁,會需要修改的是Nginx 和 Gunicorn。整個後端架構的關係如下:

後端:
Request <->
<-> Web Server (Nginx/Aphach/etc...) <->
<-> Web Server Gateway Interface(Gunicorn/uWSGI/etc...) <->
<-> Application, or Framwork (Python Django/Python Flask/Node.JS Express/JS Express Ruby on Rail/etc...))

瀏覽器是前端上的用家看到的網頁;
當用家輸入網址後。

Web Server (Nginx) 在後端負責架起伺服器功能,去接受和處理外來訪客的HTTP request,proxy, cache,static files;Gateway (Gunicorn) 作為 Web Server 和 Framework之間的中介接口,管理如何呼叫適當的Python應用程序、Load balancing 等;背後的Application & Framework 當然是Python 的Django 框架下設置的Model、Template、View 和 多個的 Python .py 檔。

開始試驗換成自己的project前,建議先跟預設的教學例子執行一次:
How To Use the Django One-Click Install Image for Ubuntu 16.04

0) Preparation
從 Digital Ocean 的 1-click image 開始,先用 "rsync" 把自己的項目("myAstrooma")上載到用戶的資料夾下:
# 用 rsync 的 SSH 資料同步
rsync -avi --delete -e 'ssh -p 22' (local folder) (username)@(your IP):(remote folder)





更新了以下一些所需的套件,(在此也建議真的日後應該弄個virtualenv,以確保自家主機測試和虛擬主機上服務的環境一致):
$ export LC_ALL=C
$ sudo pip install --upgrade pip
$ sudo pip install django-import-export
$ sudo pip install Pillow

首先應該可以用Django 的runserver 啟動的,防火牆設定中打開測試用的連接埠。
$ sudo ufw app list
$ sudo ufw status
$ sudo ufw enable
$ sudo ufw allow 8000
$ sudo python manage.py collectstatic 
$ sudo python manage.py makemigrations
$ sudo python manage.py migrate
$ python manage.py runserver 0.0.0.0:8000

1) Nginx
修改 /etc/nginx/sites-avail
able/django 這個 Nginx 的設定檔:
$ sudo nano /etc/nginx/sites-available/django

upstream app_server {
    server 127.0.0.1:9000 fail_timeout=0;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    client_max_body_size 4G;
    server_name _;

    keepalive_timeout 5;

    # Your Django project's media files - amend as required
    location /media  {
        alias /home/django/myAstrooma/media;
    }

    # your Django project's static files - amend as required
    location /static {
        alias /home/django/myAstrooma/static;
    }

    # Proxy the static assests for the Django Admin panel
    location /static/admin {
       alias /usr/lib/python2.7/dist-packages/django/contrib/admin/static/admin/;
    }

    location / {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_redirect off;
            proxy_buffering off;
            proxy_pass http://app_server;
    }

    # Customize Django project's assets files - amend as required
    location /assets {
        alias /home/django/myAstrooma/assets;
    }
}


把捷徑(symbolic-link)放到 /etc/nginx/sites-enabled/django,這裡才是 Nginx 卜月十田十行是實際使用的設定:
$ sudo ln -s /etc/nginx/sites-available/django /etc/nginx/sites-enabled/django

測試 Nginx 的 config:
$ sudo nginx -t

這時候如果未啟動網路伺服器 Nginx 的話,在瀏覽器輸入IP或網址應該會出現 "Unable to connect,  can’t establish a connection to the server at ......" 的錯誤訊息。 然後這指令啟動Nginx:
$ systemctl restart nginx


2) Gunicorn
啟動Nginx後,上面連接不到伺服器的訊息會消失,但如果未啟動 Gateway's Gunicorn 的話,主機不懂如何處理這些請求,所以會面對 "502 Bad Gateway,   nginx/1.10.3 (Ubuntu)" 的錯誤訊息。下一步就要修改修改 Gunicorn 的設定檔,分別是:
  • /etc/systemd/system/gunicorn.service :
  • /etc/gunicorn.d/gunicorn.py 
修改 /etc/systemd/system/gunicorn.service 這個 Gunicorn 的設定檔,特別是當中的 WorkingDirectory、name、pythonpath:
$ sudo nano /etc/systemd/system/gunicorn.service

[Unit]
Description=Gunicorn daemon for Django Project
Before=nginx.service
After=network.target

[Service]
WorkingDirectory=/home/django/django_project
ExecStart=/usr/bin/gunicorn --name=django_project --pythonpath=/home/django/django_project --bind unix:/home$
Restart=always
SyslogIdentifier=gunicorn
User=django
Group=django

[Install]
WantedBy=multi-user.target

而 /etc/gunicorn.d/gunicorn.py 是有關 work processor 的 設定,可以沒有改動。
"""gunicorn WSGI server configuration."""
from multiprocessing import cpu_count
from os import environ


def max_workers():
    return cpu_count() * 2 + 1

max_requests = 1000
worker_class = 'gevent'
workers = max_workers()

最後就是更新和啟動 Gunicorn:
$ cd ~/myAstrooma
$ gunicorn --bind 0.0.0.0:8000 myAstrooma.wsgi:application

$ sudo systemctl daemon-reload
$ sudo systemctl restart gunicorn.service


而如果要關掉Server時可以閉上firewall 的 80 port、或者關掉Nginx
$ sudo ufw deny 80

$ sudo systemctl stop nginx
$ sudo systemctl stop gunicorn.service


在最後那天成功部署的過程中,最有用的 D.O. 教學要算這兩篇了:
How To Use the Django One-Click Install Image for Ubuntu 16.04
How To Set Up Django with Postgres, Nginx, and Gunicorn on Ubuntu 16.04


3) Django
Django 中的 setting.py 和 static files 的運用時,也有一些設定應該在正式上線時修改的。原本打算是另外一篇了,但見以上的 "Nginx - Gunicorn - Django" 架構,在這裡留個分部提一提點,就當完整了吧。

沒有留言:

張貼留言