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服务

建议如果要测试下面的 Django、uwsgi 或者是 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端口早被 wordpress 的 apache 服务器占用了, 启动不了, 所以要把 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出了一堆问题

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

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

4.

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

参考

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