项目部署 nginx + uwsgi + flask/django 踩坑

记录一下在腾讯云上部署项目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环境

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

# 运行安装程序
$ bash Anaconda3-5.2.0-Linux-x86_64.sh  # 一路yes完事
# 使用sudo conda会安装在/root目录下
# 不使用sudo conda就会安装在/home目录下

# 更新环境变量
$ source ~/.bashrc
# source .zshrc

# 新建conda环境
$ conda create --name django1.11.8 python=3.6

# 激活虚拟环境
$ 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/下创建了启动脚本nginx
  5. nginx默认端口号为80
# 开启nginx服务
$ sudo /etc/init.d/nginx start

# 停止nginx服务
$ sudo /etc/init.d/nginx stop

# 重启nginx服务
# 每次修改配置文件都需要重启nginx
$ sudo /etc/init.d/nginx restart
2. 配置uwsgi
  • 安装
# 安装
# 在conda环境使用pip安装uwsgi会出现莫名的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过程中发生了一些错误, 最后发现是缺少一些so文件
以下解决方法参考于 (https://blog.csdn.net/qq_26105397/article/details/79928222)

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


# 随后使用ldd查看可执行模块的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这三个so库, 将anaconda下的so库链接到相应的系统/lib目录下(32位系统/lib, 64位系统则是相应的/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项目测试
  • 先写一个简单的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, 单独使用uwsgi启动flask
# 无需配置ini, 直接使用shell 参数启动uwsgi服务
$ uwsgi --socket 0.0.0.0:5000 --protocol http -w tmp:app

可以看到使用外部浏览器访问也可以成功显示hello world, 并且再flask中会自动识别html标签

  • 接下来配置nginx,首先修改nginx的配置文件
# 修改nginx的配置文件 /etc/nginx/sites-available (sites-enabled)/default
# 再server节点下添加新的location项, 指向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服务

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

使用配置文件ini代替传参

# file: mysitetest/uwsgi.ini
[uwsgi]
# 使用uwsgi接收请求
socket = 0.0.0.0:5000
# web应用的入口模块名称
module = run:app
# 程序内启用的application变量名
callable = app
vacuum = true
# 项目启动文件的目录
# django中对应wsgi.py的路径
# flask中是app文件对应的路径
wsgi-file = /home/ubuntu/run.py
# 是否开启主进程监控子进程
master = true
# 项目当前的工作目录
chdir = /home/ubuntu
# log文件的位置
logto = tmp.log
# uwsgi对应启动时的进程pid号, 结束服务时需要使用
pidfile = uwsgi.pid
# 设置内存使用上限, 参照自己服务器内存使用情况
buffer-size = 32768
# uwsgi开启的进程数, 同样参照自己服务器情况
# 如果开启master, 会开启三个进程, 其中一个进程只负责调度子进程
processes = 2
# 每个进程的线程数
threads = 2

开启服务

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

这里nginx默认监听端口是80, 接到请求后会重定向到5000端口

4. django项目测试
  • 创建新的django项目
$ django-admin startproject mysitetest

# django项目结构
$ cd mysitetest
$ tree .
django项目结构
  • 新建uwsgi配置文件uwsgi.ini
$ nano uwsgi.ini
[uwsgi]
socket = 0.0.0.0:8000
processes = 3 # 进程数, 自定
threads = 2 # 线程数, 自定
pidfile = uwsgi.pid
daemonize = uwsgi.log
chdir = /home/ubuntu/mysite_test/mysitetest # 当前工作目录
wsgi-file = mysitetest/wsgi.py # django的wsgi.py的相对路径
master = true # 开启父进程

# 查看目录结构
$ 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;
        }
}
  • 开启服务
$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini
成功运行
# 查看当前后台运行的uwsgi进程
$ ps aux | grep "uwsgi"
uwsgi后台进程

我们可以看到有四个进程在后台运行, 因为我们在配置文件中开启了父进程master=true, 父进程负责调度子进程

# 查看目录结构
$ tree .
项目运行后的目录结构

首先项目目录中新增了pycache文件夹, 这是py文件运行后, python解释器保存的字节码, 而另外的uwsgi.piduwsgi.log就是我们在配置文件中设置的pidfiledaemonize, 分别保存uwsgi后台运行的进程pid号以及uwsgi运行的log日志

$ cat uwsgi.pid
11435

这个pid文件中保存着父进程的pid号, 当我们想要停止uwsgi服务时, 只需要使用uwsgi --stop uwsgi.pid 这样系统就会杀死父进程, 由于父进程负责调度另外的进程, 其他进程也会结束

$ 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运行输出的日志, 我们可以看到当前系统的版本, python版本以及uwsig版本等等

6. 配置nginx静态文件路径
  • 配置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配置文件中新增静态文件的地址
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"), )

但是在测试时发现静态文件访问报403, 去查了一下发现需要将nginx的user改为root

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

# 重启nginx服务
$ sudo /etc/init.d/nginx restart
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271