項(xiàng)目部署 nginx + uwsgi + flask/django 踩坑

記錄一下在騰訊云上部署項(xiàng)目nginx + uwsgi + python-flask/django

軟件版本

  • python 3.6
  • flask lastest
  • django 1.11.8
  • uwsgi 2.0.18
  • nginx lastest
  • anaconda 3.5.2.0

登錄云之后先更新軟件

$ sudo apt update
$ sudo apt upgrade

配置conda環(huán)境

# 安裝conda
$ curl -O https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh

# 運(yùn)行安裝程序
$ bash Anaconda3-5.2.0-Linux-x86_64.sh  # 一路yes完事
# 使用sudo conda會(huì)安裝在/root目錄下
# 不使用sudo conda就會(huì)安裝在/home目錄下

# 更新環(huán)境變量
$ source ~/.bashrc
# source .zshrc

# 新建conda環(huán)境
$ conda create --name django1.11.8 python=3.6

# 激活虛擬環(huán)境
$ source activate django1.11.8

安裝軟件

1. 配置nginx
$ sudo apt install nginx
  1. 存放在/etc/nginx下, 配置文件放在/etc/nginx/sites-available(sites-enabled)/default中
  2. 日志放在了/var/log/nginx中
  3. 程序文件在/usr/sbin/nginx
  4. 在/etc/init.d/下創(chuàng)建了啟動(dòng)腳本nginx
  5. nginx默認(rèn)端口號為80
# 開啟nginx服務(wù)
$ sudo /etc/init.d/nginx start

# 停止nginx服務(wù)
$ sudo /etc/init.d/nginx stop

# 重啟nginx服務(wù)
# 每次修改配置文件都需要重啟nginx
$ sudo /etc/init.d/nginx restart
2. 配置uwsgi
  • 安裝
# 安裝
# 在conda環(huán)境使用pip安裝uwsgi會(huì)出現(xiàn)莫名的ModuleImportError
$ conda install uwsgi

# 安裝完畢, 測試安裝是否成功
$ uwsgi --version
# uwsgi: error while loading shared libraries: libicui18n.so.58: cannot open shared object file: No such file or directory

在安裝uwsgi過程中發(fā)生了一些錯(cuò)誤, 最后發(fā)現(xiàn)是缺少一些so文件
以下解決方法參考于 (https://blog.csdn.net/qq_26105397/article/details/79928222)

# 首先查看uwsgi的安裝位置
$ which uwsgi
# /usr/local/bin/uwsgi


# 隨后使用ldd查看可執(zhí)行模塊的dependency
$ ldd /home/ubuntu/anaconda3/bin/uwsgi 
    linux-vdso.so.1 (0x00007ffd043b4000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f03c3470000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f03c30d2000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f03c2ece000)
    libz.so.1 => /home/ubuntu/anaconda3/bin/../lib/libz.so.1 (0x00007f03c2cb7000)
    libpcre.so.1 => /home/ubuntu/anaconda3/bin/../lib/libpcre.so.1 (0x00007f03c2a72000)
    libyaml-0.so.2 => /home/ubuntu/anaconda3/bin/../lib/libyaml-0.so.2 (0x00007f03c2854000)
    libjansson.so.4 => /home/ubuntu/anaconda3/bin/../lib/libjansson.so.4 (0x00007f03c3da3000)
    libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f03c25c7000)
    libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f03c20fc000)
    libxml2.so.2 => /home/ubuntu/anaconda3/bin/../lib/libxml2.so.2 (0x00007f03c1d95000)
    liblzma.so.5 => /home/ubuntu/anaconda3/bin/../lib/liblzma.so.5 (0x00007f03c1b6f000)
    libiconv.so.2 => /home/ubuntu/anaconda3/bin/../lib/libiconv.so.2 (0x00007f03c3cbd000)
    libicui18n.so.58 => not found 
    libicuuc.so.58 => not found
    libicudata.so.58 => not found
    libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f03c1937000)
    libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f03c1734000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f03c152c000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f03c113b000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f03c3b95000)
    libstdc++.so.6 => /home/ubuntu/anaconda3/bin/../lib/././libstdc++.so.6 (0x00007f03bef53000)
    libgcc_s.so.1 => /home/ubuntu/anaconda3/bin/../lib/././libgcc_s.so.1 (0x00007f03bed41000)

缺少libicui18n.so.58, libicuuc.so.58, libicudata.so.58這三個(gè)so庫, 將anaconda下的so庫鏈接到相應(yīng)的系統(tǒng)/lib目錄下(32位系統(tǒng)/lib, 64位系統(tǒng)則是相應(yīng)的/lib64)

$ sudo ldd -s /home/ubuntu/anaconda3/lib/libicui18n.so.58 /lib/libicui18n.so.58
$ sudo ldd -s /home/ubuntu/anaconda3/lib/libicuuc.so.58 /lib/libicuuc.so.58
$ sudo ldd -s /home/ubuntu/anaconda3/lib/libicudata.so.58 /lib/libicudata.so.58
# 測試
$ uwsgi --version
# 2.0.18
3. flask項(xiàng)目測試
  • 先寫一個(gè)簡單的flask的hello_world程序
## tmp.py
from flask import Flask
app = Flask(__name__)

app.route('/')
def hello_world():
    return "<h1>Hello World</h1>"

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
  • 首先不使用nginx, 單獨(dú)使用uwsgi啟動(dòng)flask
# 無需配置ini, 直接使用shell 參數(shù)啟動(dòng)uwsgi服務(wù)
$ uwsgi --socket 0.0.0.0:5000 --protocol http -w tmp:app

可以看到使用外部瀏覽器訪問也可以成功顯示hello world, 并且再flask中會(huì)自動(dòng)識(shí)別html標(biāo)簽

  • 接下來配置nginx教翩,首先修改nginx的配置文件
# 修改nginx的配置文件 /etc/nginx/sites-available (sites-enabled)/default
# 再server節(jié)點(diǎn)下添加新的location項(xiàng), 指向wsgi的IP和端口

server {
    ...
        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                # try_files $uri $uri/ =404;
                uwsgi_pass 0.0.0.0:5000;
                include /etc/nginx/uwsgi_params;
        }

}

重啟nginx服務(wù)

# 更改配置重啟
$ sudo /etc/init.d/nginx restart
[ ok ] Restarting nginx (via systemctl): nginx.service.

使用配置文件ini代替?zhèn)鲄?/p>

# file: mysitetest/uwsgi.ini
[uwsgi]
# 使用uwsgi接收請求
socket = 0.0.0.0:5000
# web應(yīng)用的入口模塊名稱
module = run:app
# 程序內(nèi)啟用的application變量名
callable = app
vacuum = true
# 項(xiàng)目啟動(dòng)文件的目錄
# django中對應(yīng)wsgi.py的路徑
# flask中是app文件對應(yīng)的路徑
wsgi-file = /home/ubuntu/run.py
# 是否開啟主進(jìn)程監(jiān)控子進(jìn)程
master = true
# 項(xiàng)目當(dāng)前的工作目錄
chdir = /home/ubuntu
# log文件的位置
logto = tmp.log
# uwsgi對應(yīng)啟動(dòng)時(shí)的進(jìn)程pid號, 結(jié)束服務(wù)時(shí)需要使用
pidfile = uwsgi.pid
# 設(shè)置內(nèi)存使用上限, 參照自己服務(wù)器內(nèi)存使用情況
buffer-size = 32768
# uwsgi開啟的進(jìn)程數(shù), 同樣參照自己服務(wù)器情況
# 如果開啟master, 會(huì)開啟三個(gè)進(jìn)程, 其中一個(gè)進(jìn)程只負(fù)責(zé)調(diào)度子進(jìn)程
processes = 2
# 每個(gè)進(jìn)程的線程數(shù)
threads = 2

開啟服務(wù)

$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini

這里nginx默認(rèn)監(jiān)聽端口是80, 接到請求后會(huì)重定向到5000端口

4. django項(xiàng)目測試
  • 創(chuàng)建新的django項(xiàng)目
$ django-admin startproject mysitetest

# django項(xiàng)目結(jié)構(gòu)
$ cd mysitetest
$ tree .
django項(xiàng)目結(jié)構(gòu)
  • 新建uwsgi配置文件uwsgi.ini
$ nano uwsgi.ini
[uwsgi]
socket = 0.0.0.0:8000
processes = 3 # 進(jìn)程數(shù), 自定
threads = 2 # 線程數(shù), 自定
pidfile = uwsgi.pid
daemonize = uwsgi.log
chdir = /home/ubuntu/mysite_test/mysitetest # 當(dāng)前工作目錄
wsgi-file = mysitetest/wsgi.py # django的wsgi.py的相對路徑
master = true # 開啟父進(jìn)程

# 查看目錄結(jié)構(gòu)
$ tree .
  • 配置nginx
$ sudo nano /etc/nginx/sites-enabled/default
# 添加下面兩行
server {
        ...
        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                # try_files $uri $uri/ =404;
                uwsgi_pass 0.0.0.0:8000;
                include /etc/nginx/uwsgi_params;
        }
}
  • 開啟服務(wù)
$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini
成功運(yùn)行
# 查看當(dāng)前后臺(tái)運(yùn)行的uwsgi進(jìn)程
$ ps aux | grep "uwsgi"
uwsgi后臺(tái)進(jìn)程

我們可以看到有四個(gè)進(jìn)程在后臺(tái)運(yùn)行, 因?yàn)槲覀冊谂渲梦募虚_啟了父進(jìn)程master=true, 父進(jìn)程負(fù)責(zé)調(diào)度子進(jìn)程

# 查看目錄結(jié)構(gòu)
$ tree .
項(xiàng)目運(yùn)行后的目錄結(jié)構(gòu)

首先項(xiàng)目目錄中新增了pycache文件夾, 這是py文件運(yùn)行后, python解釋器保存的字節(jié)碼, 而另外的uwsgi.piduwsgi.log就是我們在配置文件中設(shè)置的pidfiledaemonize, 分別保存uwsgi后臺(tái)運(yùn)行的進(jìn)程pid號以及uwsgi運(yùn)行的log日志

$ cat uwsgi.pid
11435

這個(gè)pid文件中保存著父進(jìn)程的pid號, 當(dāng)我們想要停止uwsgi服務(wù)時(shí), 只需要使用uwsgi --stop uwsgi.pid 這樣系統(tǒng)就會(huì)殺死父進(jìn)程, 由于父進(jìn)程負(fù)責(zé)調(diào)度另外的進(jìn)程, 其他進(jìn)程也會(huì)結(jié)束

$ cat uwsgi.log
*** Starting uWSGI 2.0.18 (64bit) on [Thu Jan  7 00:07:36 2021] ***
compiled with version: 7.3.0 on 09 February 2019 23:40:56
os: Linux-4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020
nodename: VM-0-17-ubuntu
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/ubuntu/mysite_test/mysitetest
writing pidfile to uwsgi.pid
detected binary path: /home/ubuntu/anaconda3/envs/django1.11.8/bin/uwsgi
chdir() to ~/mysite_test/mysitetest
chdir(): No such file or directory [core/uwsgi.c line 2623]
*** Starting uWSGI 2.0.18 (64bit) on [Thu Jan  7 00:11:26 2021] ***
compiled with version: 7.3.0 on 09 February 2019 23:40:56
os: Linux-4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020
nodename: VM-0-17-ubuntu
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/ubuntu/mysite_test/mysitetest
writing pidfile to uwsgi.pid
detected binary path: /home/ubuntu/anaconda3/envs/django1.11.8/bin/uwsgi
chdir() to /home/ubuntu/mysite_test/mysitetest
your processes number limit is 7075
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 0.0.0.0:8000 fd 3
Python version: 3.6.7 | packaged by conda-forge | (default, Nov 21 2018, 03:09:43)  [GCC 7.3.0]
Python main interpreter initialized at 0x555a259b36d0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 166752 bytes (162 KB) for 2 cores
*** Operational MODE: threaded ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x555a259b36d0 pid: 10878 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 10878)
spawned uWSGI worker 1 (pid: 10891, cores: 2)
[pid: 10891|app: 0|req: 1/1] 111.56.143.81 () {42 vars in 753 bytes} [Wed Jan  6 16:11:32 2021] GET / => generated 1716 bytes in 8 msecs (HTTP/1.1 200) 3 headers in 95 bytes (1 switches on core 0)
SIGINT/SIGQUIT received...killing workers...
worker 1 buried after 1 seconds
goodbye to uWSGI.
*** Starting uWSGI 2.0.18 (64bit) on [Thu Jan  7 00:14:21 2021] ***
compiled with version: 7.3.0 on 09 February 2019 23:40:56
os: Linux-4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020
nodename: VM-0-17-ubuntu
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/ubuntu/mysite_test/mysitetest
writing pidfile to uwsgi.pid
detected binary path: /home/ubuntu/anaconda3/envs/django1.11.8/bin/uwsgi
chdir() to /home/ubuntu/mysite_test/mysitetest
your processes number limit is 7075
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 0.0.0.0:8000 fd 3
Python version: 3.6.7 | packaged by conda-forge | (default, Nov 21 2018, 03:09:43)  [GCC 7.3.0]
Python main interpreter initialized at 0x5635857876d0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 333504 bytes (325 KB) for 6 cores
*** Operational MODE: preforking+threaded ***
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x5635857876d0 pid: 11435 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 11435)
spawned uWSGI worker 1 (pid: 11448, cores: 2)
spawned uWSGI worker 2 (pid: 11449, cores: 2)
spawned uWSGI worker 3 (pid: 11450, cores: 2)

這里保留著uwsgi運(yùn)行輸出的日志, 我們可以看到當(dāng)前系統(tǒng)的版本, python版本以及uwsig版本等等

6. 配置nginx靜態(tài)文件路徑
  • 配置nginx
# file: /etc/nginx/sites-available(sites-enabled)/default
# 新添加location /static 路由配置, 重定向到指定的絕對路徑

server{
    location /static {
        # root static 文件夾所在的絕對路徑
        root /home/path/to/mysite;
    }
}
  • 配置django
# file: /mysitetest/settings.py
# 在django配置文件中新增靜態(tài)文件的地址
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"), )

但是在測試時(shí)發(fā)現(xiàn)靜態(tài)文件訪問報(bào)403, 去查了一下發(fā)現(xiàn)需要將nginx的user改為root

# file: /etc/nginx/nginx.conf
# 更改user為root
# user www-data;
user root;

# 重啟nginx服務(wù)
$ sudo /etc/init.d/nginx restart
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敢朱,一起剝皮案震驚了整個(gè)濱河市露久,隨后出現(xiàn)的幾起案子要尔,更是在濱河造成了極大的恐慌闹击,老刑警劉巖妥畏,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件智润,死亡現(xiàn)場離奇詭異,居然都是意外死亡贤徒,警方通過查閱死者的電腦和手機(jī)芹壕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來接奈,“玉大人踢涌,你說我怎么就攤上這事■瓿茫” “怎么了斯嚎?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵利虫,是天一觀的道長挨厚。 經(jīng)常有香客問我堡僻,道長,這世上最難降的妖魔是什么疫剃? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任钉疫,我火速辦了婚禮,結(jié)果婚禮上巢价,老公的妹妹穿的比我還像新娘牲阁。我一直安慰自己,他們只是感情好壤躲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布城菊。 她就那樣靜靜地躺著,像睡著了一般碉克。 火紅的嫁衣襯著肌膚如雪凌唬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天漏麦,我揣著相機(jī)與錄音客税,去河邊找鬼。 笑死撕贞,一個(gè)胖子當(dāng)著我的面吹牛更耻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捏膨,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼秧均,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了号涯?” 一聲冷哼從身側(cè)響起熬北,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诚隙,沒想到半個(gè)月后讶隐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡久又,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年巫延,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片地消。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炉峰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脉执,到底是詐尸還是另有隱情疼阔,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站婆廊,受9級特大地震影響迅细,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淘邻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一茵典、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宾舅,春花似錦统阿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蔬蕊,卻和暖如春蜻直,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背袁串。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工概而, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人囱修。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓赎瑰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親破镰。 傳聞我的和親對象是個(gè)殘疾皇子餐曼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355