在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程

当一个项目开发差不多的时候,我们需要尽早把项目上线让他人可以通过外网访问。至于有待完善的地方,可以等部署完后一点点地迭代和改进。现在就让我们详细聊一聊项目部署的流程。

一、前言

由于以前从来没有接触到服务器,项目部署运维等方面的知识,因此在第一次项目部署的时候花费了较长的时间。虽然网上目前有很多的教程,但是都基本是零碎的教程,导致第一次项目部署也踩坑不少。因此我准备写一个完善的部署流程,熟悉部署项目额一般操作。

二、项目部署之前的准备

我们将使用比较流行的 Nginx + Gunicorn 的方式将 Django 开发的web部署到自己的服务器,让别人能够通过域名访问你的网站。至于 Nginx、Gunicorn 原理是什么?(我也不太明白。。。),所以写了一个教程熟悉他们的用法和操作流程。
为了部署我们的项目,需要满足以下几个条件:

  • 购买一台可以通过外网访问的服务器。(目前各大云的云服务器是很好的选择)
  • 有一个域名(直接用IP地址也行,但是搜索引擎不会收录这些网站)
  • 一个基本功能开发完备的项目,项目迁移之后可以成功运行
  • 熟悉使用git和github进行代码拉去和推送,从而方便实时更新项目,修复bug
  • 会一些linux操作系统的基本命令(因为一般的项目部署都是基于linux操作系统完成的)

2.1 服务器相关的问题

  • 服务器购买
    各种云提供商购买一款即可,比如腾讯云,阿里云之类的。博主买的是阿里云服务器,配置为1核2G,学生优惠价是 9.9 元/月,而且服务器性能比较高。注意一点的是在选服务器类型的时候选择公共镜像,这样系统比较纯净。操作系统建议选 ubuntu 14.04 64位,这是本教程使用的服务器环境。

这里主要讲一下阿里云购买成功之后的一些操作:

1、买完后打开阿里云管理控制台

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第1张图片

接下来就是远程登录服务器了,你可以下载Xshell or PuTTY,用来连接,或者使用上图的远程连接

注意:修改了云服务器root的密码了,记得要重启一次云服务器。

博主使用的是Xshell 进行远程登录云服务器,使用Xshell 进行远程登录云服务器的教程如下,这里不再仔细讲解了。

  • 使用xshell远程连接linux服务器

使用xshell远程登录成功界面如下:

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第2张图片

2、配置阿里云的访问端口

在阿里云的云服务器控制台,在右侧点击>网络安全组 > 安全组配置>配置规则>快速创建规则:

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第3张图片

有些端口,快速配置无法满足?比如像 django 的 8000,memcached 的 11211,如何再添加一些端口呢,就是 点击 添加安组规则 按钮。
8000/8003的意思是,允许 8000, 8001, 8002, 8003 端口,其实是表示范围,配置过程如下:

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第4张图片

这样就完成了云服务器的相关设置,配置完云服务器的访问端口,还需要设置域名解析。

2.2 域名相关的问题

如果你想长久的运营一个网站,并且希望搜索引擎可以搜索到这个网站,那么你需要给这个网站配置一个域名。域名服务商有很多,博主是在阿里云上买的域名,并且购买了配套的域名解析服务DNS。
阿里云上面的域名购买成功界面:

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第5张图片

点击解析,并且添加解析记录,出现以下界面:

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第6张图片

其中记录值是 你的云服务器的公网 ip ,不包括端口,所以我们django项目的监听端口应该设置为 80。

设置完成之后出现的界面是这样的:

在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的主要流程_第7张图片

这样,域名解析也就设置完成了,下面我们再开始真正的部署工作,是不是感觉很复杂?恩恩,是的。。。,第一次接触这些东西,搞起来趋势挺麻烦的。

!注意:现在在阿里云上购买的域名都需要先进行备案才能够使用,备案流程根据阿里云官网指引完成即可


对于个人域名备案需要用到的东西:

  • 身份证-正反面图、
  • 户口本/临时居住证-正反图
  • 网站备案信息核验单
  • 大概半个月时间才能完成,期间要保持电话畅通

2.3 简单介绍Gunicorn和Nginx 是什么

这两个都是服务器,简单的区别就是Gunicorn是一个WSGI服务器,而Nginx一个是HTTP服务器。

  • gunicorn 可以单独提供服务,但生产环境一般不这样做。

首先静态资源(jscssimg)会占用不少的请求资源,而对于 gunicorn 来讲它本身更应该关注实际业务的请求与处理而不应该把资源浪费在静态资源请求上;此外,单独运行 gunicorn 是没有办法起多个进程多个端口来负载均衡的。

  • nginx 的作用就是弥补资源占用,负载均衡等问题的。

首先作为前端服务器它可以处理一切静态文件请求,此时 gunicorn 作为后端服务器,nginx 将会把动态请求转发给后端服务器,因此我们可以起多个 gunicorn 进程,然后让 nginx 作均衡负载转发请求给多个 gunicorn 进程从而提升服务器处理效率与处理能力。最后,nginx 还可以配置很多安全相关、认证相关等很多处理,可以让你的网站更专注业务的编写,把一些转发规则等其它业务无关的事情交给 nginx 做。

  • HTTP服务器

如果网站是HTML/CSS/JS(不包括node.js这种SSJS)组成的,那么这是一个静态的网站。用户访问这个网站的时候,HTTP请求被浏览器发送,经过DNS等被送到网站的服务器。服务器处理HTTP请求,将浏览器能够处理的响应返回给用户的浏览器。所以这个场景下的服务器一般被称为HTTP服务器,常见的有Apache的httpd和Nginx

  • Application服务器

如果你的网站是动态的,比如是用Django写的。那么客户端上来的请求要能够被Djano的Application处理。WSGI就是这样的一个协议:它是一个Python程序和用户请求之间的接口。WSGI服务器的作用就是接受并分析用户的请求,调用相应的python对象完成对请求的处理,然后返回相应的结果。uWSGI和gunicorn就是目前主流的WSGI服务器

  • 我们为什么需要用到uwsgi或者gunicorn?

uwsgi或者gunicorn作用:需要有东西在服务器上运行你的Python程序,而且Python不是处理所有的请求都很强,那么uwsgi或者gunicorn就是这个东西或者是处理一些请求的。

  • 我们为什么用Nginx+gunicorn?

1、 配置简单(网上的技术博客都是这么说),选uWSGI还是Gunicorn,功能上两者应该区别不大,但是使用简便来说,应该是Gunicorn更胜一筹。

2、 依赖Nginx的代理行为,(Nginx不仅仅是一个Http服务器,它还是一个反向代理服务器)同Nginx进行功能上的分离。由于不需要直接处理用户来的请求(都被Nginx先处理),Gunicorn不需要完成相关的功能,其内部逻辑非常简单:接受从Nginx来的动态请求,处理完之后返回给Nginx,由后者返回给用户。

3、Nginx具有高性能、高并发、静态文件缓存、及以上两点、甚至还可以做到限流与访问控制,所以选择Nginx是很有必要的;

更多服务器基本概念的理解请参考以下文章:

  • uWSGI, Gunicorn, 啥玩意儿?

2.4 在云服务器上面搭建web开发环境

下面我们需要在与服务器上面搭建web开发的环境中,也就是项目运行所需要的一些依赖,并且移植项目到云服务器。
当我们顺利用Xshell登录远程服务器之后,对于一台全新服务器的话,通常我们是以 root 用户登录的。在 root 下部署代码不安全,最好是建一个新用户(如果你已经以非 root 用户登录的话可以跳过这一步)。下面的一些列命令将创建一个拥有超级权限的新用户:

#创建新用户wss
root@iZuf60za0a748jc3c71epvZ:~# useradd -m -s /bin/bash wss
#新创建的用户加入超级权限组
root@iZuf60za0a748jc3c71epvZ:~# usermod -a -G sudo wss
#为新用户设置密码
root@iZuf60za0a748jc3c71epvZ:~# passwd wss
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
#切换到创建的新用户
root@iZuf60za0a748jc3c71epvZ:~# su - wss
#切换成功,@符号前面已经是新用户名而不是 root 了
wss@iZuf60za0a748jc3c71epvZ:~$ 

如果是新服务器的话,最好先更新一下系统,避免因为版本太旧而给后面安装软件带来麻烦。运行下面的两条命令:

wss@iZuf60za0a748jc3c71epvZ:~$ sudo apt-get update
wss@iZuf60za0a748jc3c71epvZ:~$ sudo apt-get upgrade

安装必要的软件了,这里我们需要用到的软件有 Nginx、Pytohn3、Git、pip 和 virtualenv以及Mysql数据库

wss@iZuf60za0a748jc3c71epvZ:~$ sudo apt-get install nginx

wss@iZuf60za0a748jc3c71epvZ:~$ sudo apt-get install git python3 python3-pip

wss@iZuf60za0a748jc3c71epvZ:~$ sudo pip3 install virtualenv

#安装mysql
wss@iZuf60za0a748jc3c71epvZ:~$ sudo apt-get install mysql-server
wss@iZuf60za0a748jc3c71epvZ:~$ apt-get isntall mysql-client

#安装过程中会提示设置密码什么的,注意设置了不要忘了,安装完成之后可以使用如下命令来检查是否安装成功:
wss@iZuf60za0a748jc3c71epvZ:~$ sudo netstat -tap | grep mysql
(No info could be read for "-p": geteuid()=1000 but you should be root.)
tcp        0      0 localhost:mysql         *:*                     LISTEN      

#登陆mysql数据库可以通过如下命令
wss@iZuf60za0a748jc3c71epvZ:~$ mysql -u root -p 
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 5.7.27-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#查看当前的数据库
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| blog               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)


三、项目部署

首先设置服务器的目录结构,然后把自己本地的项目放到服务器上面来,我使用的是 Github 克隆项目,这种从代码库克隆的方式是比较推荐的,因为可以持续的使用 pull 来让服务器上面的项目保持跟代码仓库中同步。Github 的安装、配置和使用这里省略,可以参考博主写的关于git的基本使用文章:

  • Git&Github基础(二)
  • Git&Github基础(三)

3.1、服务器的目录结构设置

为了方便项目的管理,以及服务器的充分使用,我们需要手动设置云服务器的目录结构。我的项目部署目录一般如下:

(env) wss@iZuf60za0a748jc3c71epvZ:~$ tree -L 3
.
├── sites
│   └── shuangblog.com
│       ├── env
│       └── myblog
└── test.txt

由于一台服务器可能部署多个网站,所有网站代码都放在 sites/ 目录下。shuangblog.com.com/ 这个文件夹以网站的域名命名,便于区分。env/ 是 python 虚拟环境目录。myblog/ 是 Django 博客项目。因此先来创建这个目录结构:

#这里 ~ 代表当前用户的 home 目录,即 /home/wss/
wss@iZuf60za0a748jc3c71epvZ:~$ mkdir -p ~/sites/shuangblog.com

#创建虚拟环境,先进入到 shuangblog.com 目录下,然后运行 virtualenv 命令创建虚拟环境
wss@iZuf60za0a748jc3c71epvZ:~$ cd ~/sites/shuangblog.com
wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$  virtualenv --python=python3 env


注意这里使用 --python=python3 来指定克隆 Python3 的环境。因为 ubuntu 系统默认安装了 Python2,如果不特别指定的话 Virtualenv 默认克隆的是 Python2 的环境。
下一步就是项目的克隆,把从本地上传到github上的项目代码拉取到与服务器的指定目录下:


#克隆代码,先进入到 shuangblog.com 目录下
wss@iZuf60za0a748jc3c71epvZ:~$ cd ~/sites/shuangblog.com
wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$  git clone git@github.com:wss1996/myblog.git myblog

运行虚拟环境,查看目录结构可以看到目录成功创建,也就是项目运行的环境基本搭建完成。


wss@iZuf60za0a748jc3c71epvZ:~$ cd ~/sites/shuangblog.com
wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$  source env/bin/activate
(env) wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$ tree -L2
#目录结构如下:
(env) wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$ tree -L 2
.
├── env
│   ├── bin
│   ├── include
│   └── lib
└── myblog
    ├── apps
    ├── blog
    ├── manage.py
    ├── media
    ├── README.md
    ├── requirements.txt
    ├── settings.py
    ├── static
    ├── templates
    └── tendcode.sock

3.2、项目在服务器上的运行

虚拟环境虽然已经创建,项目也已经拉到服务器。但是环境中还没有安装项目的依赖,所以现在要根据项目的依赖文件去安装依赖。这样项目才能够运行。

  • 进入虚拟环境
  • 目录切换到你的项目的依赖文件 requirements.txt 的目录下
  • 安装依赖
wss@iZuf60za0a748jc3c71epvZ:~$ cd ~/sites/shuangblog.com
wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$  source env/bin/activate
(env) wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com$ cd myblog
(env) wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com/myblog$ ls
apps  blog  manage.py  media  README.md  requirements.txt  settings.py  static  templates  tendcode.sock
(env) wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com/myblog$ pip install -r requirements.txt

项目的基本运行条件已经准备好了,下面开始运行项目。

3.2.1、创建相应的数据库

如果项目同样适用的是 MySQL 数据库的话,在项目运行之前需要先创建数据库,比如我的项目中指定了数据库的基本信息,我创建数据库(进入mysql命令行下)的命令如下:

mysql > CREATE DATABASE `blog` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

这句命令的意思是创建一个名称为 myblog 的数据库,并且将数据库的编码设定为 utf8,这个按照自己的项目需求去创建即可。

3.2.3、迁移,项目运行(按照本地运行Django项目的流程进行)

下面的一些步骤在这里不在详细讲解,主要包括:

  • 创建数据迁移
python manage.py makemigrations
python manage.py migrate
  • 创建管理员账号
python manage.py createsuperuser
  • 静态文件收集
python manage.py collectstatic
  • 项目启动
python manage.py runserver 0.0.0.1:8000

3.3、具体部署(配置Gunicorn以及Nginx)

####3.3.1、安装配置Gunicorn

  • 1、在虚拟环境中安装 Gunicorn;
(env) wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com/myblog$ pip install gunicorn
Requirement already satisfied: gunicorn in /home/wss/sites/shuangblog.com/env/lib/python3.5/site-packages (19.9.0)

  • 2、创建项目的 Gunicorn 配置文件(退出虚拟环境):
#配置文件名为gunicorn_tendcode.service
wss@iZuf60za0a748jc3c71epvZ:~/sites/shuangblog.com/myblog$ sudo vim /etc/systemd/system/gunicorn_tendcode.service

  • 3、具体的配置信息如下
wss@iZuf60za0a748jc3c71epvZ:/etc/systemd/system$ vi gunicorn_tendcode.service

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=wss
Group=www-data
WorkingDirectory=/home/wss/sites/shuangblog.com/myblog
ExecStart=/home/wss/sites/shuangblog.com/env/bin/gunicorn --access-logfile - --workers 2 --bind unix:/home/wss/sites/shuangblog.com/myblog/tendcode.sock blog.wsgi:application

[Install]
WantedBy=multi-user.target


User 填写自己当前用户名称
WorkingDirectory 填写项目的地址
ExecStart 中第一个地址是虚拟环境中 gunicorn 的目录,所以只需要改前半部分虚拟环境的地址即可
workers 2 这里是表示2个进程,可以自己改
unix 这里的地址是生成一个 sock 文件的地址,直接写在项目的根目录即可

blog.wsgi 表示的是项目中 wsgi.py 的地址,我的项目中就是在 blog 文件夹下的


  • 4、启动配置文件
~$ sudo systemctl start gunicorn_tendcode
~$ sudo systemctl enable gunicorn_tendcode

查看服务的状态可以使用命令:

~$ sudo systemctl status gunicorn_tendcode

上面的命令启动没有问题可以看看自己的项目的跟目录下面,应该会多一个 tendcod.sock 文件的。

后续如果对 gunicorn 配置文件做了修改,那么应该先使用这个命令之后重启:

~$ sudo systemctl daemon-reload
#再重启
~$ sudo systemctl restart gunicorn_tendcode

####3.3.2、配置Nginx
接下是配置 Nginx 来处理用户请求。
先在服务器的 /etc/nginx/sites-available/ 目录下新建一个配置文件,文件名为mynginx,并且写入配置信息

sudo vi /etc/nginx/sites-available/mynginx
#配置文件如下
server {
    # 端口和域名
    listen 80;
    server_name www.shuangshuangblog.com;

    # 日志
    # static 和 media 的地址
    location /static/ {
        root /home/wss/sites/shuangblog.com/myblog;
    }
    location /media/ {
        root /home/wss/sites/shuangblog.com/myblog;
    }
    # gunicorn 中生成的文件的地址
    location / {
        include proxy_params;
        proxy_pass http://unix:/home/wss/sites/shuangblog.com/myblog/tendcode.sock;
    }
}

① 服务的域名为 demo.zmrenwu.com。
② 所有URL 带有 /static 的请求均由 Nginx 处理,alias 指明了静态文件的存放目录。
③ 其它请求转发给 Gunicorn处理。
我们在 /etc/nginx/sites-available/ 放置了配置文件,接下来需要创建一个符号链接,把这个配置文件加入到启用的网站列表中去,被启用网站的目录在 /etc/nginx/sites-enabled/,你可以理解为从 sites-available/ 目录下发送了一个配置文件的快捷方式到 sites-enabled/ 目录。具体命令如下:

~$ sudo ln -s /etc/nginx/sites-available/mynginx /etc/nginx/sites-enabled

运行完毕之后可以查看一下 Nginx 的运营情况,看看会不会报错:

(env) wss@iZuf60za0a748jc3c71epvZ:/etc/nginx/sites-available$ sudo nginx -t
[sudo] password for wss: 
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

如果上面这句没有报错,那么恭喜你,你的配置文件没有问题,可以继续下一步,如果报错了,需要按照报错的信息去更改配置文件中对应行的代码,好好检查一下吧!
重启一下 Nginx:

~$ sudo systemctl restart nginx

四、后续的维护

之后的项目维护中,如果更改了 gunicorn 的配置文件,那么需要依次执行下面两条语句去重启服务,如果只是修改了 Django 项目的内容,只需要单独执行第二条重启命令即可:

~$ sudo systemctl daemon-reload
~$ sudo systemctl restart gunicorn_tendcode

如果修改了 Nginx 的配置文件,那么需要依次执行下面两条语句去重启服务:

~$ sudo nginx -t
~$ sudo systemctl restart nginx

五、总结

  • 对于Nginx+gunicorn的部署方式,有些命令我还不是很懂,对于相关的配置东西还是很多的,以后如果再用到的话就好好研究一下;
  • 最起码知道了Nginx以及gunicorn是什么,还有他们的分工协作,也能照葫芦画瓢配置部署一些简单的项目;
  • 项目部署维护,高并发多进程啥的有机会还是要多研究研究;

六、参考文章内容链接

  • 在 Linux 服务器上使用 Nginx + Gunicorn 部署 Django 项目的正确姿势
  • 使用 Nginx 和 Gunicorn 部署 Django 博客
  • nginx+uwsgi 和nginx+gunicorn区别、如何部署
  • gunicorn 详解
  • 阿里云ubuntu16.4服务器部署python3.6.2+django1.11.3网站的全过程
  • Ubuntu 安装mysql和简单操作
  • Linux vim编辑器常用命令
  • 初次部署django+gunicorn+nginx

你可能感兴趣的:(linux相关)