手把手带你整得明明白白 Flask/Django+uWSGI+Nginx

Web 项目(例如 Flask 项目、Django 项目)开发完成后定然是要部署到服务器上的,我也曾翻阅很多文章,零零碎碎地将知识点拼凑起来,还踩了不少的坑,最终实现了项目的部署。

这里将部署过程和配置说明作了整理,希望能够帮助到有需要的开发者。

本文围绕 Flask 和 Django 框架与 uWSGI 服务和 Nginx 服务展开,将从服务器的安全组配置到 Python 的安装,从 uWSGI 的安装到启动,再讲解 Flask、Django 与 uWSGI 组合的配置,接着从 Nginx 的安装到 Flask/Django + uWSGI + Nginx 组合的配置,最后将讲解并演示前后端分离项目中前端项目的 Nginx 配置。

基础准备工作

基础准备工作中,我们将完成服务器安全组配置、Python 和 uWSGI 的安装,帮助新手趟过明明启动了却无法访问的坑。

服务器安全组配置

市面上大部分云服务器厂商的服务器都设有安全组,安全组是管理端口开闭的配置组。如果没有打开对应的安全组,那么就算再服务器启动了服务,用户在浏览器也无法访问服务的。

阿里云和华为云的服务器默认都有安全组,腾讯云默认不设安全组,京东云等其它厂商的服务器没接触过。

感谢信:谢谢群友 金鱼(林洁) 为本文实验提供的云服务器!

这里以阿里云服务器为例。

登录阿里云网站后点击右上角的控制台,在控制台中找到对应的服务器。

在服务器列表页的右上角点击更多选项,并从中找到网络和安全组选项,进而选择安全组配置选项。

在安全组列表页点击右侧的配置规则选项。

在规则列表页点击左上角的添加安全组规则按钮,接着在弹出的面板中输入端口范围和授权对象。本文演示中用到的端口为 80、3000、3333 和 5000,所以这里设定的端口为 80 和 3000/5000

授权对象默认填写 0.0.0.0/0,意思是对所有 IP 都开放。如果对安全性比较看重的朋友,可以填写指定 IP。配置完成后的安全组策略如下图所示:

安装 Python 3

配置完安全组后,便可用 SSH 工具连接服务器。SSH 连接工具很多,直接用终端命令行也可以,我选择的是 Terminus。连接到服务器后的操作将用命令进行,首先我们需要查看当前 Python 版本:

$ python --version

Python 2.7.5

根据返回信息得知当前服务器中的 Python 版本为 2.7.5,如果我们的项目基于 Python 3+ 开发,那么就需要安装对应的版本,这里以 Python3.6 为例 。

在安装 Python 3.6 之前,需要先安装编译时用到的依赖:

$ yum -y groupinstall "Development tools"
$ yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel
$ yum install libffi-devel -y

一切妥当后下载对应版本的安装包,例如 Python3.6:

$ wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz

下载完成后解压:

$ tar -xvJf  Python-3.6.0.tar.xz

创建编译安装的目录:

$ mkdir /usr/local/python3

进入刚才解压后得到的文件夹中,然后进行编译:

$ cd Python-3.6.0
$ ./configure --prefix=/usr/local/python3
$ make && make install

编译时间比较长,受服务器配置影响,整体时间约 3~8 分钟,请耐心等待。当终端出现 Successfully installed pip-9.0.1 setuptools-28.8.0 字样时代表编译完成。

为了方便我们在命令行执行 python 和 pip,这里需要为 Python3.6 创建软链接

$ ln -s /usr/local/python3/bin/python3 /usr/local/bin/python3
$ ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip3

命令执行后,当我们输入 python3 时指向的就是我们安装的 Python3.6。通过命令确认软链接创建情况

$ python3 --version
  Python 3.6.0
$ pip3 --version
  pip 9.0.1 from /usr/local/python3/lib/python3.6/site-packages (python 3.6)

安装并检查 uWSGI 服务

完成 Python3.6 的安装后便可以开始 uWSGI 的安装了。按照 uWSGI 官方文档 Installing uWSGI with Python support 部分的指引,我们需要先安装 Python 支持:

$ yum install python-devel

然后便可以通过 pip 命令安装 uWSGI 了:

$ pip3 install uwsgi

命令执行后终端返回信息如下;

Successfully installed uwsgi-2.0.18

其中出现 Successfully 字样代表安装成功,从返回信息得知 uWSGI 的版本号为 2.0.18。要注意的是,当我们在终端运行:

$ uwsgi --version

时会得到如下提示:

-bash: uwsgi: command not found

这是因为系统找不到 uwsgi 命令。同样的,也要为 uWSGI 创建软链接

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

此时再次运行 uwsgi –version 终端返回的就是正确的信息了:

2.0.18

完成 uWSGI 的安装工作后,我们可以通过一个示例来检测 uWSGI 是否能够正常工作。根据 uWSGI 官方文档 The first WSGI application 部分的介绍,在系统任意目录(假设为 /root)中新建一个名为 foobar 的 Python 文件,并写入以下代码:

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]

这时候使用 uWSGI 提供的命令启动 foobar,并设定 HTTP 端口为 3000

uwsgi --http :3000 --wsgi-file foobar.py

命令执行后,我们在浏览器中访问:

http://47.105.187.6:3000/

当浏览器中出现 Hello World 字样时代表 uWSGI 能够正常工作。

来自 www.sfhfpc.com 算法和反爬虫站长韦世东的提示:可以使用 Ctrl + c 组合键关闭 uWSGI 服务。

Flask + uWSGI 组合拳

对于 Flask 项目的部署,uWSGI 官方文档也有给出相应的介绍,详见 Deploying Flask

来自专业爬虫论坛 bbs.nightteam.cn 的提示:本文的 Flask 包括了 Flask 和 Flask restful。

在开始实验之前我们需要安装 Flask

$ pip3 install Flask

然后新建一个名为 sailboat 的 Python 文件,并写入以下代码:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "<span style='color:red'>Sailboat from GitHub</span>"

这段代码表示基于 Flask 创建了一个 Web 服务,设定的路由为 /,当用户访问根路由(即 /)时服务端将文字资源:

<span style='color:red'>Sailboat from GitHub</span>

返回给用户。当然,现在服务还没启动,用户也无法访问到指定的路由。使用 uWSGi 启动 Flask 项目时需要运行一长串命令:

uwsgi --http :3000 --wsgi-file sailboat.py --callable app --processes 4 --threads 2 --stats 127.0.0.1:9191

其中用到的 precesses、threads 和 stats 是可以省略掉的,因为它们只是附加的一些参数,并不会直接影响服务的启动。最后我们在浏览器中看到的是红色的文字:Sailboat from GitHub,即下图所示的界面:

uWSGI 的配置文件

在你敲击完一长串命令并回车后,你会感觉很爽。然而这并没有什么卵用,过长的命令串极大地增加了你敲错命令的风险,它们是成正比的。uWSGI 团队也考虑到了这个问题,于是乎他们为 uWSGI 增加了配置文件的支持。例如命令串:

$ uwsgi --http-socket :9090 --psgi myapp.pl

用配置文件来表示可以写成:

[uwsgi]
http-socket = :9090
psgi = myapp.pl

假设这个 INI 配置文件的名称为 sailboat.ini,那么你启动它的命令为:

$ uwsgi -i sailboat.ini

这就舒服多了!除了 INI 之外,uWSGI 还支持 JSONXMLYAML 等类型的配置文件。你可以根据个人习惯选择不同类型的配置文件,但大部分人使用的都是 INI。

上面启动 Flask 的命令串在 INI 中体现为:

[uwsgi]
http = :3000
wsgi-file = sailboat.py
callable = app
processes = 4
threads = 2
stats = 127.0.0.1:9191

假设 INI 的文件名称为 sailboat,那么启动它的命令为:

$ uwsgi -i sailboat.ini 

为项目指定虚拟环境

有的朋友可能会问,我的服务器上有多个项目,每个项目对应有 Python 虚拟环境,这种情况下我如何为项目指定对应的虚拟环境呢?

uWSGI 团队也考虑到了这个问题,我们只需要在 INI 中增加 virtualenv 配置项即可。假设要为 sailboat 指定路径为 “/usr/local/python3/lib/python3.6/site-packages/envsailboat” 的Python 虚拟环境,那么在 INI 中增加这项即可:

[uwsgi]
+ virtualenv = /usr/local/python3/lib/python3.6/site-packages/envsailboat
http = :3000
……

来自《Python3 反爬虫原理与绕过实战》作者韦世东的提示:其中的 “+” 号代表新增配置行,“……” 号代表省略其它配置。

以上就是使用 uWSGI 启动 Flask 的介绍,更多知识请翻阅 uWSGI 官方文档。

Django + uWSGI 组合拳

对于 Django 项目的部署,uWSGI 官方文档也有给出相应的介绍,详见 Deploying Django

提示:本文的 Flask 包括了 Django 和 Django rest framework。

在开始实验之前我们需要安装 Django

$ pip3 install django

与 uWSGI 一样,Django 安装完成后也不能直接在终端使用,否则会得到错误提示:

-bash: django-admin: command not found

同样的,我们为 django-admin 创建软链接。如果不知道 django-admin 目录具体路径,可以用 Linux 中的 find 命令进行查找:

$ find / -name "django-admin"
/usr/local/python3/bin/django-admin

得到具体路径后再创建软链接:

$ ln -s /usr/local/python3/bin/django-admin /usr/bin/django-admin

接着就可以使用 django-admin 来创建一个 Django 项目了。例如创建一个名为 sfhfpc 的项目:

$ django-admin startproject sfhfpc

这时候我们就可以进入 sfhfpc 目录下启动它项目了:

$ cd sfhfpc
$ python3 manage.py runserver 0.0.0.0:5000

这里要注意的是,如果安装的 Django 版本为 3.0,而操作系统是 CentOS 则会引发异常:

django.core.exceptions.ImproperlyConfigured: SQLite 3.8.3 or later is required (found 3.7.17).

这是因为 Django 3.0 支持的 SQLite 最低版本为 3.8.3,而操作系统自带的 SQLite 版本为 3.7.17。解决这个异常的选择是升级 SQLite 版本或者降低 Django 版本。在实际应用中还需根据具体需求选择,这里我选择的是降低 Django 版本:

$ pip3 uninstall django
$ pip3 install django==2.1.8

而后删除掉之前创建的 sfhfpc 项目,且在 Django 版本为 2.1.8 的基础上再次创建 sfhfpc 项目:

$ cd /root
$ rm -rf /root/sfhfpc
$ django-admin startproject sfhfpc

此时进入项目目录,通过 runserver 命令启动它:

$ cd sfhfpc
$ python3 manage.py runserver 0.0.0.0:5000

在浏览器访问:

http://47.105.187.6:5000/

会得到如下显示:

这是因为我们并没有按照 Django 的要求设置 HOSTS,同时说明 Django 能够正常相应用户的请求。此时进入 “/root/sfhfpc/sfhfpc” 中编辑名为 settings 的Python 文件,改动文件中关于 ALLOWED 的配置:

- ALLOWED_HOSTS = []
+ ALLOWED_HOSTS = ["*"]

提示:“-” 号代表删除行,“+” 号代表新增行

而后回到 “/root/sfhfpc” 目录中,再次执行 runserver 命令便可正常启动 Django,此时页面显示内容如下:

确保 Django 能够正常运行后,我们再学习如何用 uWSGI 启动 Django。

来自夜幕团队全员的温馨提示:记得用 Ctrl + c 组合键停止刚才启动的 Django 项目哦。

根据 uWSGI 官方文档 Deploying Django 部分的指引,我们很快就能编写出对应的命令串:

uwsgi --http :5000 --chdir /root/sfhfpc/ --wsgi-file sfhfpc/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

对应的 INI 配置如下:

[uwsgi]
http = :5000
chdir = /root/sfhfpc/
wsgi-file = sfhfpc/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:9191

假设该 INI 配置文件名称为 sfhfpc.ini,那么它的路径为:

/root/sfhfpc/sfhfpc.ini

我们使用与 Flask 案例中通过 INI 启动 uWSGI 相同的命令:

$ uwsgi -i sfhfpc.ini

便可启动 Django 项目,命令执行后终端输出内容如下:

[uWSGI] getting INI configuration from sfhfpc.ini
*** Starting uWSGI 2.0.18 (64bit) on [Sat Dec 14 12:41:59 2019] ***
compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-39) on 14 December 2019 03:25:29
os: Linux-3.10.0-1062.1.2.el7.x86_64 #1 SMP Mon Sep 30 14:19:46 UTC 2019
nodename: iZm5ehqonkrh3mzrarekw2Z
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /root/sfhfpc
detected binary path: /usr/local/python3/bin/uwsgi
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
chdir() to /root/sfhfpc/
your processes number limit is 7271
your memory page size is 4096 bytes
detected max file descriptor number: 65535
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :5000 fd 4
uwsgi socket 0 bound to TCP address 127.0.0.1:40032 (port auto-assigned) fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
Python version: 3.6.0 (default, Dec 14 2019, 11:20:23)  [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Python main interpreter initialized at 0xdef330
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
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 416880 bytes (407 KB) for 8 cores
*** Operational MODE: preforking+threaded ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0xdef330 pid: 17724 (default app)
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
spawned uWSGI master process (pid: 17724)
spawned uWSGI worker 1 (pid: 17726, cores: 2)
spawned uWSGI worker 2 (pid: 17727, cores: 2)
spawned uWSGI worker 3 (pid: 17728, cores: 2)
spawned uWSGI worker 4 (pid: 17729, cores: 2)
*** Stats server enabled on 127.0.0.1:9191 fd: 18 ***
spawned uWSGI http 1 (pid: 17730)

其中的 spawned uWSGI http 字样代表 uWSGI 成功启动。至于 WARNING: you are running uWSGI as root,实验中大可不必理会,但工作中必须遵守 uWSGI 的约定:不使用 root 用户运行 uWSGI。

提示:关于 Python 虚拟环境的设置请参考 uWSGI 文档,此处不再赘述。

此时浏览器中页面显示如下:

浏览器呈现结果说明我们通过 uWSGI 启动了 Django 服务。

Nginx 的安装和启动

nginx 是一个高性能的 HTTP 和反向代理服务,也是一个 IMAP/POP3/SMTP 服务,其优点是内存 占用少、并发能力强、稳定性高。

nginx 是跨平台的,它可以在大多数类 UNIX 系统上运行,同时也 支持 Windows 系统。

—— 引用自《Python3 反爬虫原理与绕过实战》

Nginx 的安装可参考 Nginx 官方文档的 Installing Nginx 部分。这里以 CentOS 为例,演示 Nginx 的安装。按照文档指引,点击下图红色框中的链接:

跳转到新页面后,根据自己的操作系统选择安装介绍,例如 CentOS

点击链接后会定位到对应的内容:

总共有 4 步:安装工具、创建 repo、开启配置、安装 Nginx,照做便是

首先安装 yum-utils:

$ sudo yum install yum-utils

然后创建 repo 文件:

$ vi /etc/yum.repos.d/nginx.repo

并将以下内容写入到 nginx.repo 中:

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

接着开启配置:

$ sudo yum-config-manager --enable nginx-mainline

最后执行 Nginx 的安装命令:

$ sudo yum install nginx

命令执行后终端返回内容如下:

Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : 1:nginx-1.17.6-1.el7.ngx.x86_64                                                                                 1/1 
----------------------------------------------------------------------

Thanks for using nginx!

Please find the official documentation for nginx here:
* http://nginx.org/en/docs/

Please subscribe to nginx-announce mailing list to get
the most important news about nginx:
* http://nginx.org/en/support.html

Commercial subscriptions for nginx are available on:
* http://nginx.com/products/

----------------------------------------------------------------------
  Verifying  : 1:nginx-1.17.6-1.el7.ngx.x86_64                                                                                 1/1 

Installed:
  nginx.x86_64 1:1.17.6-1.el7.ngx                                                                                                  

Complete!

内容中出现 Thanks for using nginx 字样代表 Nginx 安装成功。

提示:安装过程中有可能出现类似 Is this ok [y/N] 的选项,输入 y 并回车即可。

Nginx 安装成功后并不会自行启动,启动它的命令如下:

$ systemctl start nginx

此时浏览器显示界面如下:

要注意的是,Nginx 默认监听 80 端口,所以在浏览器输入 ip 地址后呈现的便是 Nginx 的欢迎页。

Flask/Django + uWSGI + Nginx 组合拳

这真是几套神奇的组合, 为什么这么说呢?

  • 首先,Flask 和 Django 自带服务,不需要 uWSGI 和 Nginx 也能启动。
  • 其次,uWSGI 可以与 Flask 和 Django 组合,不需要 Nginx 也能访问。
  • 最后,Flask/Django + uWSGI + Nginx 实际上是 Nginx 和 uWSGI 的关联,至于是 Flask 还是 Django ,Nginx 表示:我无所谓!

那为什么要使用 Nginx,直接用 Flask/Django 自带的服务不行吗?

说到底还是 Nginx 的处理能力太强了,Flask/Django 自带服务的能力太菜,uWSGI 给 Flask/Django 上了一层保险,但远不及 Nginx,所以就出现了 Flask/Django + uWSGI + Nginx 这种搭配。

Flask + Nginx 组合拳

Nginx 会根据配置文件呈现内容,它的配置文件目录为 “/etc/nginx/conf.d”,默认配置文件名为 default。default.conf 文件内容如下:

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ .php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ .php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /.ht {
    #    deny  all;
    #}
}

我们不必改动它的默认配置,为了方便管理,我们可以为每个项目都编写一份配置文件,例如 Flask 项目 porters 的配置文件命名为 porters.conf,同样存放在 “/etc/nginx/conf.d” 中。

来自 NightTeam 全员的提示:conf 文件的命令与具体的 Web 项目无关,可以随意命令。

首先,我们来看看 Flask 与 Nginx 的组合,假设 porters.py 包含如下代码:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return f"<p>Hello!Porters.vip</p>"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=3333)

现在使用直接运行的方式启动这个 Flask 服务:

$ python3 porters.py

页面呈现内容如下:

这代表 Flask 服务正常启动且外部可访问。新建名为 porters 的 Nginx 配置文件,并写入以下配置:

server {
    listen 3000;
    server_name 47.105.187.6;
    charset     utf-8;

    location / {
        proxy_pass  http://localhost:3333;
    }
}

配置的主要作用是让 Nginx 监听 3000 端口,并将请求转发到 http://localhost:3333。也就是说当用户在浏览器访问 http://localhost:3000 时,这个请求被转到服务器上端口号为 3333 的服务,也就是我们启动的 Flask 服务上。页面呈现内容如下:

这正是刚才启动的 Flask 服务。此时访问 http://localhost:3333,得到同样的显示

Flask + uWSGI + Nginx 组合拳

这里我们使用 INI 配置文件的方式启动 Flask 服务,porters 的 INI 配置如下:

[uwsgi]
socket = 127.0.0.1:3333
wsgi-file = porters.py
callable = app
processes = 4
threads = 2
stats = 127.0.0.1:9191

保存后执行启动命令:

$ uwsgi -i porters.ini

这时候访问 http://47.105.187.6:3000 将得到错误提示:

这是由于 Nginx 反向代理的类型为 HTTP 所致,如果代理的是 uWSGI 服务,需要新增对应配置。porters.conf 完整配置如下:

upstream uwsgis {
    server 127.0.0.1:3333;
}

server {
    listen 3000;
    server_name 47.105.187.6; 
    charset     utf-8;
    location / {
        uwsgi_pass  uwsgis;
        include  uwsgi_params;
    }
}

配置中引入了 uWSGi 的支持并配置了 uWSGI 对应的服务和端口。保存配置后执行 Nginx 配置重载命令:

$ nginx -s reload

此时页面呈现如下:

而访问 http://47.105.187.6:3333 时却显示无法访问。

以上就是 Flask + uWSGI + Nginx 的演示和介绍。

Django +uWSGI +Nginx 组合拳

上面演示的过程中,无论 Web 服务是 Flask 还是 Django 都不会影响 uWSGI 和 Nginx 的关系,所以只要按照 uWSGI 配置启动 Web 服务后,Django + uWSGI + Nginx 的配置方法与 Flask + uWSGI + Nginx 的配置方法是一样的。

前后端分离项目的 Nginx 配置

前后端分离是近年来较为常用的前端、后端分开开发的组合方式,这样能够有效提高双端开发效率。很多朋友不知道前端项目开发完毕、打包后得到的静态项目如何部署到服务器上。

首先,Vue、React 或 Angular 项目开发完毕后通常会用类似 yarn buildnpm build 这样的命令将前端项目打包成静态文件——html、css、js 和图片等,假设你已经将项目打包好了,现在你计算机中的 build 目录下的文件就是你的 React 项目打包后得到的静态文件。

首先,你需要将项目上传到服务器中,例如 “/root/static”。如果你计算机的操作系统是类 Unix 系,那么可以用 scp 命令将项目上传到服务器,具体命令如下:

$ scp -r build root@47.105.187.6:/root/static

提示:命令执行后,上传前会要求你输入服务器登录密码,输入后回车即可。

待文件全部上传后,你便可以在 Nginx 的配置文件中配置静态文件的路径了。打开刚才使用的 porters.conf,在 server 级配置下新增部分配置:

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

这部分配置的作用是将 “/root/static” 目录下的静态资源与路由 “/docs” 进行绑定,当用户在浏览器中访问 http://www.xxx.com/docs 时看到的是 “/root/static” 目录中的 index.html 页面。

我的计算机中并没有 Vue 或者 React 系的项目,一些静态文件:

api_data.js     api_project.json    img         main.js
api_data.json       css         index.html      utils
api_project.js      fonts           locales         vendor

这些静态文件虽不是 React/Vue 项目打包而生成,但却与它们打包而生成的静态文件无异,此处不必多想,照做便是。

将 build 目录上传到 47.105.187.6 后按照上面的指引到 Nginx 配置文件中增加部分配置。保存后执行 Nginx 的配置重载命令:

$ nginx -s reload

用浏览器访问,此时页面呈现如下:

显示的是 403,这显然和配置没什么关系,是权限问题。打开 Nginx 的错误日志,看看究竟是什么原因:

$ cat /var/log/nginx/error.log 

命令执行后终端便会显示 Nginx 错误日志中的内容,最下面的一句为:

"/root/static/build" failed (13: Permission denied), client: xx.xx.xx.xxx, server: 47.105.187.6, request: "GET /build HTTP/1.1", host: "47.105.187.6:3000"

其中的 Permission denied 说明 Nginx 没有权限读取 build 目录中的文件。再看看 Nginx 拥有的权限:

$ cat /etc/nginx/nginx.conf 

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

返回的配置中的第 1 行中表明此时 Nginx 的权限是 nginx,它是无法访问 root 用户下的文件的。这里我们将 user nginx 改为 user root 即可。

提示:实验并未考虑安全性等问题,具体工作中选择修改文件权限还是 Nginx user 请向公司运维或部门经理确认。

保存修改后执行 Nginx 配置重载命令:

$ nginx -s reload

再次访问 http://47.105.187.6:3000/build,此时页面呈现如下

页面内容正确显示,说明部署成功。

以上就是前后端分离项目中前端 Nginx 配置的演示和介绍。

扩展知识: Django 静态文件的处理

有些时候,后端开发过程中会产生一些前端文件,例如 Django rest freamwok 开发时开启文档生成功能后便会产生部分静态文件,部署时就会产生静态文件无法正确显示的问题。

在 settings.py 文件中有个 STATIC_URL = ‘/static/’,在它下面新增一行:

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

保存文件,然后在 Python 环境下执行命令:

$ python manage.py collectstatic

这样 Django 就会收集静态文件,放到指定目录内,也就是( Django 项目目录下的 static 内)。

除此之外,还需要在 Nginx 配置中设置静态文件路径:

location /static  {
    alias  /root/sfhfpc/sfhfpc/static;  # 指向 Django 的 static 目录
}

这样处理后,才能确保 Django rest framework docs 的样式能够正确显示。

参考文章

夜幕韦世东 — 《不轻松,服务器部署nginx+uwsgi+djangorestfremework+react

忧臣解读 — 《Centos7安装Python3.7

版权声明

作者:夜幕韦世东

团队:NightTeam

链接:http://www.sfhfpc.com

来源:算法和反爬虫

著作权归作者所有,非商业转载请注明出处,禁止商业转载。

转载前请联系作者韦世东|禁止商业转载:算法和反爬虫 » 手把手带你整得明明白白 Flask/Django+uWSGI+Nginx

赞 (0) 打赏

说说你的看法 0

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏