Nginx+uwsgi+Django部署

Nginx+uwsgi+Django 入门部署

环境配置

如果下文没有特殊说明, 以 python3 为基础来配置

安装pip

ubuntu:

1
2
3
4
5
6
7
8
9
# pip2
sudo apt-get install python-pip
# 检查是否安装成功
pip -V

# pip3
sudo apt-get install python3-pip
# 检查是否安装成功
pip3 -V

CentOS:

1
2
3
4
5
# pip2
sudo yum -y install epel-release
sudo yum -y install python-pip
# 检查是否安装成功
pip -V

CentOS 安装 python3 后在 python3/bin/ 下有 pip3, 所以问题变成如何安装 python3, 参考这里

安装nginx

Ubuntu:

1
2
sudo apt-get install nginx
sudo /etc/init.d/nginx start # start nginx

CentOS:

1
2
3
4
sudo yum install epel-release # 已安装此源则可以跳过
sudo yum install nginx
# 启动nginx服务
sudo systemctl start nginx.service

这时候浏览器访问 http://127.0.0.1/ 应该可以看到 nginx 的欢迎界面(下图是 CentOS 的)

停止nginx服务

建议如果要测试下面的 Djangouwsgi 或者是 uwsgi+Django 的话, 先把 nginx 服务 关闭, 不然可能会出现一些错误

Ubuntu:

1
sudo /etc/init.d/nginx stop    # stop nginx

CentOS:

1
2
3
4
5
# 停止nginx服务
sudo systemctl stop nginx.service

# 重启nginx服务
sudo systemctl restart nginx.service

安装uwsgi

1
pip3 install uwsgi

做基本测试, 在任意一个目录下, 创建一个名为 test.py 的文件:

1
2
3
4
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]

shell 运行下面的命令:

1
2
3
# --http :8001: 使用http协议, 运行在8001端口;
# --wsgi-file test.py: 加载指定的文件,test.py
uwsgi --http :8001 --wsgi-file test.py

然后浏览器访问 http://127.0.0.1:8001 查看效果

安装Django

1
pip3 install Django

用uwsgi运行Django服务器

先确保你的Django服务器可以正常运行, 这里不多阐述, 可以按照官网的教程创建一个简单的项目来测试

先进入项目 manage.py 所在目录, 然后执行下面的命令:

1
2
# --module mysite.wsgi: 加载指定的wsgi模块
uwsgi --http :8001 --module mysite.wsgi

然后浏览器访问 http://127.0.0.1:8001 (路径根据你的项目设计而定)查看效果

配置nginx+uwsgi+Django(Ubuntu下)

下文中, manage.py 所在目录均写为 dir_M/, 请读者自行更改为自己的目录

部署静态文件

进入 dir_M/ 目录, 创建两个新目录 media static, 来存放相应的静态文件

然后打开 dir_M/project_name/settings.py 文件, 在末尾添加一行:

1
STATIC_ROOT = os.path.join(BASE_DIR, "static/")

然后回到 dir_M/, 运行下面的命令:

1
python manage.py collectstatic

这一步就完成了

设置站点nginx配置文件

先将 uwsgi_params (通常在 /etc/nginx/ 这个目录里有) 拷贝到 dir_M/

1
cp /etc/nginx/uwsgi_params dir_M/

dir_M 下创建一个名为 s_nginx.conf 文件, 写入以下内容(这里直接用 file socket 的方式配置, 如果想用 web port socket 的方式的话, 可以看 参考1):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# s_nginx.conf

# the upstream component nginx needs to connect to
# 告知nginx连接的是django
upstream django {
server unix:///home/pachirisu/Desktop/uwsgi/Server/Server/Server.sock; # 用 file socket 性能更好
# server 127.0.0.1:8001; # 用 web port socket 性能一般
}

# configuration of the server
# 服务器配置
server {
# 监听端口
listen 8765;
# 域名, 若没有可以随便写一个
server_name www.alice.com;
charset utf-8;

# 允许最大的请求大小
client_max_body_size 75M;

# 下面两个是Django的静态文件, 可以交由nginx处理
# 要先创建好对应文件夹
location /media {
alias /home/pachirisu/Desktop/uwsgi/Server/Server/media;
}

location /static {
alias /home/pachirisu/Desktop/uwsgi/Server/Server/static;
}

# Finally, send all non-media requests to the Django server.
# 非静态请求会交给Django来处理
location / {
uwsgi_pass django;
# 刚刚复制的 uwsgi_params 文件
include /home/pachirisu/Desktop/uwsgi/Server/Server/uwsgi_params;
}
}

这个配置文件告诉nginx提供来自文件系统的媒体和静态文件, 以及处理那些需要Django干预的请求. 对于一个大型部署, 让一台服务器处理静态/媒体文件, 让另一台处理Django应用, 被认为是一种很好的做法, 但是现在, 这样就好了

将这个文件链接到 /etc/nginx/sites-enabled,这样nginx就可以看到它了:

1
sudo ln -s dir_M/s_nginx.conf /etc/nginx/sites-enabled/

简单测试静态文件部署

添加一个文件(在这里是图片 3.jpg, 文本也可以)到 dir_M/media 中, 然后重启 nginx

1
sudo /etc/init.d/nginx restart

可以尝试用 url 来访问你刚刚放置的文件, 我这里是访问 http://127.0.0.1:8765/media/3.jpg, 效果如下:

让nginx与uwsgi通信

将上文我们用来测试uwsgi的文件拷贝到 dir_M/

1
2
3
4
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]

shell 中运行:

1
2
3
4
# --socket 表示用 uwsgi 协议, 这里是 unix socket, 也就是上面我们配置nginx的file socket
# --wsgi-file 加载指定的文件
# --chmod-socket 给予权限, 没有这个可能会造成通信失败(可选664)
uwsgi --socket project_name.sock --wsgi-file test.py --chmod-socket=666

重启 nginx

这时候访问 http://127.0.0.1:8765, 应该就可以看到 Hello World 了

如果出错

可以检查一下 nginx 的错误日志 /var/log/nginx/error.log

让nginx与uwsgi+Django通信

和上文的 uwsgi+Django 类似, 只要把 uwsgi 运行参数改一下就好了, 当然还是在 dir_M/ 目录:

1
2
# --module 加载模块
uwsgi --socket project_name.sock --module project_name.wsgi --chmod-socket=666

记得重启 nginx

配置uwsgi.ini文件 让uwsgi启动更方便

我们可以将用在uWSGI上的相同的选项放到一个文件中,然后告诉 uWSGI 使用该文件运行。这使得管理配置更容易。

同样在 dir_M 目录, 创建一个名为 s_uwsgi.ini 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# s_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
# 这里是是 dir_M 目录
chdir = /home/pachirisu/Desktop/uwsgi/Server/Server

# Django's wsgi file
# 这里填写你的 project_name.wsgi
module = Server.wsgi

# 虚拟环境 笔者这里没有用到 所以注释了 没发现有什么问题
# the virtualenv (full path)
# home = /path/to/virtualenv

# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10

# the socket (use the full path to be safe
# sock文件所在的目录, 一般是 dir_M/project_name.sock
socket = /home/pachirisu/Desktop/uwsgi/Server/Server/Server.sock

# ... with appropriate permissions - may be needed
# 权限 可选664
chmod-socket = 666

# 虚拟环境相关的吧 没有用到
# clear environment on exit
# vacuum = true

# 后台运行
daemonize = /root/log/s_uwsgi_run.log

然后就可以通过这个 ini 文件来运行 uwsgi:

1
uwsgi --ini s_uwsgi.ini

重启 nginx !

整体过程

  1. 通过 ini 文件启动 uwsgi + Django
  2. 启动 nginx 服务
  3. 访问你的网站
  4. OK!

到这里入门级的部署就完成了, 进阶的等之后笔者学习了再分享一下吧!

配置nginx+uwsgi+Django(CentOS下)

下文中, manage.py 所在目录均写为 dir_M/, 请读者自行更改为自己的目录

部署静态文件

进入 dir_M/ 目录, 创建两个新目录 media static, 来存放相应的静态文件

然后打开 dir_M/project_name/settings.py 文件, 在末尾添加一行:

1
STATIC_ROOT = os.path.join(BASE_DIR, "static/")

然后回到 dir_M/, 运行下面的命令:

1
python manage.py collectstatic

这一步就完成了

设置站点nginx配置文件

先将 uwsgi_params (通常在 /etc/nginx/ 这个目录里有) 拷贝到 dir_M/

1
cp /etc/nginx/uwsgi_params dir_M/

与 Ubuntu 不同

打开 /etc/nginx/ 目录下的 nginx.conf, 把这里面的 Server 默认配置注释了(不注释不知道会怎么样, 笔者这里注释了, 后来运行是正常的)

dir_M 下创建一个名为 s_nginx.conf 文件, 写入以下内容(这里直接用 file socket 的方式配置, 如果想用 web port socket 的方式的话, 可以看 参考1):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# s_nginx.conf

# the upstream component nginx needs to connect to
# 告知nginx连接的是django
upstream django {
server unix:///root/Server/Server/Server.sock; # 用 file socket 性能更好
# server 127.0.0.1:8001; # 用 web port socket 性能一般
}

# configuration of the server
# 服务器配置
server {
# 监听端口
listen 8765;
# 域名, 若没有可以随便写一个
server_name www.alice.com;
charset utf-8;

# 允许最大的请求大小
client_max_body_size 75M;

# 下面两个是Django的静态文件, 可以交由nginx处理
# 要先创建好对应文件夹
location /media {
alias /root/Server/Server/media;
}

location /static {
alias /root/Server/Server/static;
}

# Finally, send all non-media requests to the Django server.
# 非静态请求会交给Django来处理
location / {
uwsgi_pass django;
# 刚刚复制的 uwsgi_params 文件
include /root/Server/Server/uwsgi_params;
}
}
这个配置文件告诉nginx提供来自文件系统的媒体和静态文件,以及处理那些需要Django干预的请求。对于一个大型部署,让一台服务器处理静态/媒体文件,让另一台处理Django应用,被认为是一种很好的做法,但是现在,这样就好了。

将这个文件链接到 /etc/nginx/sites-enabled(没有这个文件夹? 参考 遇到的坑2),这样 nginx 就可以看到它了:

1
sudo ln -s dir_M/s_nginx.conf /etc/nginx/sites-enabled/

简单测试静态文件部署

在这里没有测试过, 不过预计和 Ubuntu 的差不多

让nginx与uwsgi+Django通信

和上文的 uwsgi+Django 类似, 只要把 uwsgi 运行参数改一下就好了, 当然还是在 dir_M/ 目录:

1
2
# --module 加载模块
uwsgi --socket project_name.sock --module project_name.wsgi --chmod-socket=666

记得重启 nginx

如果出错

可以检查一下 nginx 的错误日志 /var/log/nginx/error.log

配置uwsgi.ini文件 让uwsgi启动更方便

我们可以将用在uWSGI上的相同的选项放到一个文件中,然后告诉 uwsgi 使用该文件运行。 这使得管理配置更容易。

同样在 dir_M 目录, 创建三个文件 s_uwsgi.ini uwsgi.pid uwsgi.status

打开 s_uwsgi.ini 文件, 写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# s_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
# 这里是是 dir_M 目录
chdir = /home/pachirisu/Desktop/uwsgi/Server/Server

# Django's wsgi file
# 这里填写你的 project_name.wsgi
module = Server.wsgi

# 虚拟环境 笔者这里没有用到 所以注释了 没发现有什么问题
# the virtualenv (full path)
# home = /path/to/virtualenv

# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10

# the socket (use the full path to be safe
# sock文件所在的目录, 一般是 dir_M/project_name.sock
socket = /home/pachirisu/Desktop/uwsgi/Server/Server/Server.sock

# ... with appropriate permissions - may be needed
# 权限 可选664
chmod-socket = 666

# 虚拟环境相关的吧 没有用到
# clear environment on exit
# vacuum = true

# 后台运行
daemonize = /root/log/s_uwsgi_run.log

# 查看状态
stats=%(chdir)/uwsgi.status
# 用来重启和停止uwsgi服务
pidfile=%(chdir)/uwsgi.pid

然后就可以通过这个 ini 文件来运行 uwsgi:

1
uwsgi --ini s_uwsgi.ini

刚刚那两个文件有下面的功能:

1
2
3
4
5
6
7
8
9
# 停止
uwsgi --stop uwsgi.pid
# 重启
uwsgi --reload uwsgi.pid
# 查看进程pid
cat uwsgi.pid
# 查看进程状态
uwsgi --connect-and-read uwsgi/uwsgi.status
#

重启 nginx !

最后就是这样:

整体过程

  1. 通过 ini 文件启动 uwsgi + Django
  2. 启动 nginx 服务
  3. 访问你的网站
  4. OK!

到这里入门级的部署就完成了, 进阶的等之后笔者学习了再分享一下吧!

遇到的坑

1.

之前服务器是用来搭建 wordpress 博客的, 后来重装了系统, 不过 wordpress 还残留??
所以测试 nginx 的时候, 因为80端口早被 wordpressapache 服务器占用了, 启动不了, 所以要把 apache 服务停了, 执行下面的命令:

(ps: 当然如果你想让nginx监听其他端口比如8002也是可以的, 只要改一下配置, 不过这里是刚入门部署的时候, 就按普通的方式来)

1
2
3
4
5
6
7
8
# 查看占用80端口的进程
lsof -i:80
# 查看 httpd.service 服务状态
systemctl status httpd.service
# 停止服务
systemctl stop httpd.service
# 取消开机启动服务
systemctl disable httpd.service

到这里80端口就不会被占用了, 可以继续配置 nginx

2.

CentOS 下并没有 sites-enabled/ 这个目录, 于是要先编辑 /etc/nginx/nginx.conf, 在 http block 中添加 include /etc/nginx/sites-enabled/*; 如图:

然后自己新建一个 sites-enabled/, 重启 nginx 服务(sudo systemctl restart nginx.service)就可以了

3.

先用 pip3 install uwsgi, 发现 command not found

然后就 pip install uwsgi(这个是pip2), 结果Django出了一堆问题

后来找到解决方法了, 添加软连接, 用 python3uwsgi:

1
ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi3

4.

即使给了666的权限, 在 CentOSnginx 服务的时候也会提示权限不足(在 error.log 看到), 看了一下原因也在里面, 就是运行的用户不同, 到 nginx.conf 更改运行用户为 root 就可以了, 不过里面建议用普通用户运行….

参考

使用uWSGI和nginx来设置Django和你的web服务器
Django 部署(Nginx)
Django Nginx+uwsgi 安装配置