1. 程式人生 > >從零開始在 Ubuntu 下部署 Nginx uWSGI Django 伺服器

從零開始在 Ubuntu 下部署 Nginx uWSGI Django 伺服器

環境:Ubuntu 16.04

1 準備工作

2 安裝並配置虛擬環境(本機)

2.1 更新軟體源

sudo apt-get update
sudo apt-get upgrade
  • update是更新軟體列表
  • upgrade是對比本地軟體版本和線上最新軟體版本,然後升級

2.2 安裝虛擬環境

sudo pip2 install virtualenv
  • virtualenv是虛擬環境安裝包,建立虛擬環境可以更好地控制包的版本,包的版本不會因為2.1中的升級操作而升級,保證了專案的穩定性
  • 不同虛擬環境之間的執行環境相互獨立,互不干擾
sudo pip2 install virtualenvwrapper
  • virtualenvwrappervirtualenv的擴充套件管理包,可以將所有的虛擬環境整合在一個目錄下
  • 使用前需要先進行以下配置

    1. 建立虛擬環境管理目錄
mkdir ~/.virtualenvs
  1. 開啟.bashrc
sudo vi ~/.bashrc 
  1. .bashrc的末尾增加以下內容
export WORKON_HOME=$HOME/.virtualenvs  # 所有虛擬環境儲存的目錄
source /usr/local/bin/virtualenvwrapper.sh
  1. 啟用配置檔案
source ~/.bashrc

2.3 建立虛擬環境

mkvirtualenv django_blog
  • 建立虛擬環境需要聯網
  • 建立完虛擬環境之後會自動進入虛擬環境,可以通過命令列字首(下圖紅框)判斷是否在虛擬環境內
  • 虛擬環境常用命令
# 建立虛擬環境
mkvirtualenv <name>

# 列出所有虛擬環境
workon TAB*2

# 進入虛擬環境
workon <name>

# 退出虛擬環境
deactivate

# 刪除虛擬環境
rmvirtualenv <name>

2.4 安裝django包

pip install django==1.8.2
  • 包後面加==用來選擇包的版本

3 建立一個django演示專案(本機)

3.1 建立專案

django-admin startproject project_test
  • 專案建立在home目錄或其子目錄,以免許可權問題帶來的不便

3.2 建立應用

  • 進入專案目錄並檢視專案結構
cd project_test/
tree
  • 專案目前結構如下

    1. 建立應用
python manage.py startapp app_test
  • 建立應用後項目結構如下

3.3 修改專案配置

3.3.1 修改環境變數

  • 開啟IDE(此處使用的是Pycharm)
  • 選擇File/Settings,進入Project Interpreter,選擇虛擬環境內的python版本
  • 如果選項內沒有,就點選右側的齒輪,選擇Add Local,
    選擇所在虛擬環境下的python版本,如/home/python/.virtualenvs/django_blog/bin/python2.7

3.3.2 建立模板資料夾、靜態檔案資料夾和應用urls

  • 在專案根目錄分別建立statictemplates資料夾
  • static資料夾下建立jscssimg三個資料夾,以後用來存放靜態檔案
  • templates資料夾下建立app_test(應用名)資料夾,以後用來存放模板檔案
  • 在應用資料夾下建立urls.py檔案,以後用來存放應用的urls對映表
  • 建立完成之後的目錄結構如下:

3.3.3 修改settings

  • 開啟/project_test下的settings.py
  • 新增應用__在INSTALLED_APPS中將我們剛建立的應用加到最後面
  • 修改模板路徑__在TEMPLATES裡的DIRS修改為'DIRS': [BASE_DIR, 'templates'],
  • 修改靜態檔案路徑__在最後新增
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

3.4 建立頁面

3.4.1 修改專案urls

  • 開啟/project_test下的urls.py,在urlpatterns內新增一行,意思是隻要不是匹配到admin,都轉到app_test應用
url(r'^', include('app_test.urls')),
  • 開啟/app_test下的urls.py,新增以下內容:
#coding=utf-8
from django.conf.urls import  url
from . import views  # 從當前資料夾內引入views

urlpatterns = [
    url(r'^$', views.index),  # 匹配到根目錄,就執行views檔案內的index函式
]
  • 開啟/project_test下的views.py,新增剛才urls.py內提到的index函式
#coding=utf-8
from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, 'app_test/index.html')
    # 對請求值不做任何處理,直接跳轉到模板目錄下app_test資料夾下的index.html頁面
  • 將一張圖片放在/static/img資料夾內
  • templates/app_test資料夾下,建立模板檔案index.html,內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
    <h1>下面有一張圖片</h1>
    ![](/static/img/test.jpg)  // 尋找static(settings裡面的STATIC_URL)資料夾下img資料夾裡的test.jpg圖片
</body>
</html>

3.5 開啟頁面

  • 在專案根目錄資料夾下,在終端內(確保已進入虛擬環境)
python manage.py runserver
  • 終端顯示如下(紅色字型暫不用管,因為我們並沒有建立models):

  • 開啟紅框內顯示的IP地址(127.0.0.1:8000)

  • 瀏覽器成功顯示建立的頁面

4 將專案上傳至伺服器(本機 & 伺服器)

4.1 匯出虛擬環境內的包(本機)

pip freeze > plist.txt
  • 此操作將虛擬環境內所有的包都儲存在了list.txt裡面

4.2 將專案資料夾整體上傳至伺服器

  • 傳輸檔案可以用samba,ftp,scp等等,此處使用的是scp
scp -r <YOUR_LOCAL_PROJECT_DIR> <SERVER_USERNAME>@<SERVER_IP>:<YOUR_SERVER_PROJECT_DIR>

4.3 在伺服器上安裝虛擬環境(伺服器)

  • 在伺服器上重複2.1~2.3的步驟,安裝虛擬環境
  • 進入虛擬環境,進入專案目錄,根據本地計算機提供的包列表安裝所需要的包
pip install -r plist.txt

5 安裝uWSGI(伺服器)

  • 安裝Python開發版本(因為安裝uWSGI過程中需要編譯)
sudo apt-get install python-dev
  • 安裝gcc(因為安裝uWSGI過程中需要C編譯器)
sudo apt-get install gcc
  • 安裝uWSGI
pip install uwsgi
  • 使用uwsgi --version命令檢視版本號,確認已正確安裝

6 配置Django(伺服器)

  • 配置專案settings,修改以下一項
ALLOWED_HOSTS = ['*', ]
  • 在專案根目錄資料夾下,在終端內(確保已進入虛擬環境)
python manage.py runserver 0:8000
  • 在本地計算機瀏覽器中輸入以下地址以測試Django在伺服器上是否正常執行
<YOUR SERVER IP>:8000

2017.06.08更新
* 如果不能正常顯示頁面,一般為以下兩個原因:

1.請檢查防火牆狀態,保證8000埠是能夠被訪問的,程式碼如下( 更多防火牆設定可以參考我這篇文章http://t.cn/RSuX8Qj

# 檢查防火牆狀態
sudo ufw status

# 可以臨時關閉防火牆
sudo ufw disable

# 或者保持防火牆開啟,允許8000埠連線
sudo ufw allow 8000

2.請檢查伺服器安全組規則,如阿里雲伺服器,可以在進入管理控制檯後,按以下步驟設定( 如要了解更多伺服器安全組規則設定,請參見阿里雲官方文件http://t.cn/RST7Sgz

3.重啟服務,再次在本地計算機瀏覽器中檢視

  • 確定伺服器正常後,開啟settings,修改以下一項
DEBUG = False

7 配置uWSGI(伺服器)

7.1 打通uWSGI和Python

  • 在專案根目錄建立test.py檔案,內容如下
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return ["Hello World"]  # python2
    # return [b"Hello World"]  # python3
  • 執行uWSGI(表示使用http協議,並使用8000埠,載入指定檔案test.py)
uwsgi --http :8000 --wsgi-file test.py
  • 開啟瀏覽器,輸入
127.0.0.1:8000
  • 若顯示’Hello World’則表示執行正常,說明以下三個環節是相通的
web client <-> uWSGI <-> Python

7.2 打通uWSGI和Django

  • 在專案根目錄建立檔案my_uwsgi.ini,並寫入以下內容
[uwsgi]
# 使用nginx連線時使用
# socket = 0:8001

# 直接做web伺服器使用
http = 0:8080

# 專案目錄
chdir = /home/python/Desktop/project_test

# 專案中wsgi.py檔案的目錄
wsgi-file = /home/python/Desktop/project_test/project_test/wsgi.py

# 主程序
master = true

# 多程序&多執行緒
processes = 6
threads = 2

# .sock檔案目錄需與Nginx檔案內的配置相同
# socket = /home/python/Desktop/project_test/my_sock.sock
# chmod-socket = 666

# 以守護程序的方式啟動
vacuum = true


# 儲存pid程序
pidfile=uwsgi.pid

# 儲存log日誌
daemonize=uwsgi.log
  • 啟動uWSGI服務
uwsgi --ini my_uwsgi.ini
  • 終端顯示以下內容即代表開啟成功
[uWSGI] getting INI configuration from my_uwsgi.ini
  • 開啟瀏覽器,位址列輸入以下地址
<YOUR_SERVER_IP>:8080
  • 可以看到,文字正常顯示,圖片無法顯示,這是正常現象

  • 以上步驟說明以下三個環節是相通的

web client <-> uWSGI <-> Django
  • 停止uWSGI服務
uwsgi --stop uwsgi.pid

8 配置Nginx(伺服器)

8.1 安裝Nginx

  • 安裝Nginx
sudo apt-get install nginx
  • Nginx安裝成功後,系統會自動開啟 Nginx 服務,預設使用80埠,開啟瀏覽器並輸入你伺服器的IP地址,就可以看到 nginx 的測試頁面
Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.
  • 說明以下兩個環節是相通的
web client <-> the web server(Nginx)

8.2 配置Nginx

  • /etc/nginx/目錄下的uwsgi_params複製到專案資料夾,對此檔案不做任何改動
cp /etc/nginx/uwsgi_params .
  • 在專案根目錄建立檔案my_nginx.conf,並寫入以下內容
upstream django {
    server    127.0.0.1:8001;
    # server      unix://home/python/Desktop/project_test/my_sock.sock;
}

server {
    listen      8000;  # 埠號
    server_name 127.0.0.1;  # 伺服器 ip 或是域名
    charset     utf-8;  # 字符集

    # 最大上傳限制
    # client_max_body_size 75M;

    location /media  {
        alias /home/python/Desktop/project_test/media_common;  # 媒體檔案所在資料夾
    }

    location /static {
        alias /home/python/Desktop/project_test/static_common;  # 靜態檔案所在資料夾
    }


    # 將所有非媒體請求轉到Django伺服器上
    location / {
        uwsgi_pass      django;  # 最上方已定義
        # 將所有引數都轉到uwsgi下
        include         /home/python/Desktop/project_test/uwsgi_params; # uwsgi_params的路徑
    }
}
  • 這個配置檔案表示將靜態檔案和媒體檔案由Nginx處理,而其它的請求轉入uWSGI處理

  • 與Nginx配置目錄建立軟連結

sudo ln -s /home/python/Desktop/project_test/my_nginx.conf /etc/nginx/sites-enabled/
  • 建立靜態檔案與媒體檔案存放目錄
sudo mkdir static_common
sudo mkdir media_common
  • 修改專案settings,在最後面新增
STATIC_ROOT = os.path.join(BASE_DIR, 'static_common')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_common')
  • 進入專案根目錄,執行靜態檔案遷移命令
python manage.py collectstatic
  • 提示輸入選項時選yes即可

  • 重啟Nginx服務

sudo /etc/init.d/nginx restart

9 Nginx & uWSGI & Django(伺服器)

9.1 測試Nginx

  • 在瀏覽器內輸入<YOUR_SERVER_IP>:8000/static/admin/css/base.css,檢查是否能正常顯示這個css檔案

  • 將一張測試圖片test.jpg放入media_common資料夾中,在瀏覽器中輸入<YOUR_SERVER_IP>:8000/media/test.jpg,如果出現403則將圖片的許可權改為666,成功顯示圖片

9.2 測試uWSGI

  • 回到專案根目錄,輸入以下命令
uwsgi --socket :8001 --wsgi-file test.py
  • 開啟瀏覽器,位址列輸入<YOUR_SERVBER_IP>,看是否能正常顯示’Hello World’

9.3 用UNIX socket取代TCP port

  • 修改my_nginx.conf最終版如下:
upstream django {
    # server    127.0.0.1:8001;
    server      unix:///home/python/Desktop/project_test/my_sock.sock;
}

server {
    listen      8000;  # 埠號
    server_name songmingyao.com;  # 伺服器 ip 或是域名
    charset     utf-8;  # 字符集

    # 最大上傳限制
    # client_max_body_size 75M;

    location /media  {
        alias /home/python/Desktop/project_test/media_common;  # 媒體檔案所在資料夾
    }

    location /static {
        alias /home/python/Desktop/project_test/static_common;  # 靜態檔案所在資料夾
    }


    # 將所有非媒體請求轉到Django伺服器上
    location / {
        uwsgi_pass      django;  # 最上方已定義
        # 將所有引數都轉到uwsgi下
        include         /home/python/Desktop/project_test/uwsgi_params; # uwsgi_params的路徑
    }
}
  • 修改my_uwsgi.ini最終版如下
[uwsgi]
# 使用nginx連線時使用
# socket = 0:8001

# 直接做web伺服器使用
# http = 0:8080

# 專案目錄
chdir = /home/python/Desktop/project_test

# 專案中wsgi.py檔案的目錄
wsgi-file = /home/python/Desktop/project_test/project_test/wsgi.py

# 主程序
master = true

# 多程序&多執行緒
processes = 6
threads = 2

# .sock檔案目錄需與Nginx檔案內的配置相同
socket = /home/python/Desktop/project_test/my_sock.sock
chmod-socket = 666

# 以守護程序的方式啟動
vacuum = true

# 儲存pid程序
pidfile=uwsgi.pid

# 儲存log日誌
daemonize=uwsgi.log
  • 重啟Nginx和uWSGI
sudo /etc/init.d/nginx restart

uwsgi --stop uwsgi.pid
uwsgi --ini my_uwsgi.ini
  • 開啟瀏覽器,位址列輸入網址<YOUR_SERVER_IP>:8000,檢視圖片和文字是否顯示正常

  • 此時以下環節已全部打通

  • *
web client <-> web server(nginx) <-> the socket <-> uwsgi <-> Django

9.4 伺服器開機自啟

  • 修改/etc/rc.local,新增以下內容到exit 0之前
/usr/local/bin/uwsgi --ini /home/python/Desktop/project_test/my_uwsgi.ini