服务器部署记录

零、写在前面

距大一下部署过django项目已经过去了一年多了,所以在这次软工部署项目的过程中完全是从头学起。那段经历对于现在的我唯一作用就是让我不可能去半途放弃部署,因为曾经在知识储备非常匮乏的情况下都能够成功部署(虽然当时借助了乃子哥许多帮助),现在没有道理比过去还差劲。嗯,经过这次部署,对于每个步骤的理解实际上是更加深刻了,当时完全是借着教程懵懵懂懂地部署上去,连nginx和uwsgi的基本功能都没有弄明白。趁着刚部署完项目,脑子还比较清醒,记录一下部署的过程,免得浪费了这几天的付出。部署服务器的问题会出在各种意向不到的地方,所以这篇博客也可以积累一下解决问题的经验

  • 参考教程:知乎

  • 本次部署所使用的环境如下,某些版本不同可能造成部分步骤存在差异

    1. 云服务器:华为云
    2. 操作系统:Centos8.2 64bit
    3. Django版本:Django3.2.23
  • 注意:我们租赁的云服务器需要具有公网IP,否则无法通过SSH连接,只能使用内网穿透,这部分就不在此讨论了

一、部署过程

首先可以大致把我们的部署给过程分为两部分:1.准备python的环境和各种工具 2.部署本地项目到服务器上

1.1 环境准备

在此之前,我们需要使用SSH连接访问我们的服务器,方便上传各种资源。这里推荐使用FinalShell或者XShell,因为在上传文件的时候可以可视化上传,否则需要使用SFTP等文件传输工具来上传文件,连接参数参考下图

1.1.1 安装Python
  • 连接成功之后,在系统中自动更新所有已安装软件包到最新版本,-y表示不需要用户确认操作

    1
    yum update -y
  • 安装软件管理包和可能使用的依赖

    1
    2
    yum -y groupinstall "Development tools"
    yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel
  • 下载Pyhton3压缩包到/usr/local目录

    1
    2
    cd /usr/local
    wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz
  • 解压该压缩包

    1
    tar -zxvf Python-3.6.6.tgz
  • 编译安装到自己指定路径-/usr/local/python3

    1
    ./configure --prefix=/usr/local/python3
  • 安装Python3

    1
    2
    make
    make install
  • 安装完成之后,建立软链接,添加变量,之后我们可以在终端中直接使用python3命令,类似于windows配置环境变量

    1
    ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3
  • 同理,这里建立pip3的软链接

    1
    ln -s /usr/local/python3/bin/pip3.6 /usr/bin/pip3
  • 查看是否成功安装Python

    1
    2
    python3 -V
    pip3 -V

1.1.2 安装virtualenv

安装virtualenv是为了方便不同的项目管理,因为不同的项目需要不同的依赖,如果都装在同一个环境里面的话会造成冗余以及会互相影响,不太优雅

  • 直接使用pip3安装

    1
    pip3 install virtualenv
  • 同理建立软链接

    1
    ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv
1.1.3 使用virtualenv创建环境
  • 创建并切换到虚拟环境集中管理的目录,这个任选你喜欢的目录即可,这里选择的是:/data/env

    1
    2
    mkdir -p /data/env
    cd /data/env
  • 为你的虚拟环境起一个名字,这里使用:djangoenv--python=指明该虚拟环境复制自父环境

    1
    virtualenv --python=/usr/bin/python3 djangoenv
  • 进入并启动虚拟环境

    1
    2
    cd djangoenv/bin
    source activate
  • 当路径前面出现djangoenv时,表示进入成功

1.1.4 安装django和uwsgi
  • 使用pip3安装django和uwsgi,注意这里需要安装两次uwsgi:一次在虚拟环境中,一次在系统环境中

    1
    2
    pip3 install django
    pip3 install uwsgi
  • 同样建立软链接

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

1.2 着手部署

1.2.1 前端文件部署

由于这次是前后端分离的项目,所以一开始打算先部署前端到服务器上查看一下效果

  • 安装nginx网页web服务器,并启动nginx服务

    1
    2
    yum install nginx
    nginx
  • 查看端口占用,可以看到nginx默认访问端口80已经开启

    1
    netstat -ntlp
  • 创建文件夹存放我们的前端文件

    1
    2
    mkdir -p /home/shine/web
    cd /home/shine/web
  • 打包我们的前端文件到该文件夹中,这里我上传的是frontend.zip压缩包,故需要解压缩

    1
    unzip frontend.zip
  • 可以看到我们的网页文件成功上传到服务器了

由于已经安装了nginx服务器,所以直接在浏览器访问自己服务器的公网IP已经可以看到网页了,不过此时是nginx的默认页面,我们需要进行修改,让其显示我们的网页页面

  • 找到nginx的配置文件:/etc/nginx/nginx.conf

    1
    2
    cd /etc/nginx
    vim nginx.conf
  • 在修改文件之前,最好复制一份源文件防止自己修改出错

    1
    cp nginx.conf nginx.conf.bak
  • root的值改为自己网页文件的路径,index是要首先展示的网页文件,listen是要监听的端口号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    server {
    listen 8080;
    listen [::]:8080;
    server_name xx.xx.xx.xx; #填写你自己服务器的IP
    root /home/shine/web/frontend;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
    index page_a.html;
    }
    }
  • 文件配置完成之后,先检查nginx语法是否无误,检查完成后重启nginx服务器。之后便可以成功在浏览器访问上传的网页文件了

    1
    2
    nginx -t
    systemctl restart nginx
1.2.2 后端文件部署
  • 在本地项目中导出所有的环境依赖包

    1
    pip list --format=freeze > requirements.txt
  • 创建并进入自己的后端文件夹,打开虚拟环境,安装依赖

    1
    2
    3
    4
    5
    mkdir -p /home/shine/web/backend
    cd /data/env/djangoenv/bin
    source activate
    cd /home/shine/web/backend
    pip3 install -r req.txt
  • 如果项目中含有静态文件的话,还需要收集静态文件

    1
    2
    3
    # 这是在settings.py中配置的
    STATIC_ROOT = os.path.join(BASE_DIR, 'static') # 指定样式收集目录
    python3 manage.py collectstatic
  • 检查是否可以正常运行django项目,如果可以则进入下一步,否则检查上述步骤

    1
    python3 manage.py runserver

  • 配置uwsgi文件,重点!!!,每个名词具体解释如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [uwsgi]
    # django项目目录
    chdir=/home/shine/web/backend/software
    # 端口号,用来和nginx进行内部通信,并不是外部端口
    socket=127.0.0.1:8888
    # module文件,django项目自带的wsgi文件
    module=software.wsgi
    # 最多允许的进程数量
    processes=4
    # 让uwsgi在后台运行,同时把日志文件记录在uwsgi.log中
    daemonize=uwsgi.log
    # 所需虚拟环境的路径
    home=/data/env/djangoenv
  • 进行nginx和uwsgi通信的配置,需要注意的内容如下所示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    server {
    listen 80;
    server_name 127.0.0.1:80; #改为自己的域名,没域名修改为127.0.0.1:80
    charset utf-8;
    location / {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:8888; #端口要和uwsgi里配置的一样
    uwsgi_param UWSGI_SCRIPT software.wsgi; #wsgi.py所在的目录名+.wsgi
    uwsgi_param UWSGI_CHDIR /home/shine/web/backend/software; #项目路径
    }
    location /static/ {
    alias /home/shine/web/backend/software/static/; #静态资源路径
    }
    }
  • 配置好nginx和uwsgi之后,查看是否有语法配置错误,检查完重启nginx服务和uwsgi服务

    1
    2
    3
    4
    nginx -t
    systemctl restart nginx
    killall -9 uwsgi
    uwsgi --ini /home/shine/web/backend/software/uwsgi.ini
  • 如果上述没有任何报错的话,就可以通过浏览器访问你的Django项目啦~

二、问题分析

2.1 问题1

  • 描述:在安装uwsgi的时候,弹出报错:ERROR: Command errored out with exit status 1

  • 解决:貌似安装一下python3-devel就可以解决

    1
    yum install python3-devel

2.2 问题2

  • 描述:nginx配置语法无误,并且路径正确但弹出报错:[error] open() “/run/nginx.pid” failed (2: No such file or directory)
  • 解决:最开始我的网页文件存放在root文件夹下面,访问这个文件夹路径需要授予root权限,否则就会报错

2.3 问题3

  • 描述:pip freeze导出的依赖文件含有(@ file:///)
  • 解决:改用命令:pip list --format=freeze > requirements.txt

2.4 问题4

  • 描述:django后端返回504网络超时error

  • 解决:uwsgi默认连接时间为60s,超时就会返回错误,所以需要在nginx.conf设置超时时间

    1
    2
    3
    uwsgi_send_timeout 600;
    uwsgi_connect_timeout 600;
    uwsgi_read_timeout 600;

2.5 问题5

  • 描述:在nginx的服务器中配置6666端口无法访问
  • 解决:某些端口浏览器认为不安全,会拒绝访问,例如:6666、6000等等端口

三、命令记录

  • 查看端口运行情况

    1
    netstat -ntlp
  • 重启nginx服务

    1
    systemctl restart nginx
  • 查看uwsgi进程

    1
    ps -ef|grep uwsgi
  • 杀死uwsgi进程

    1
    killall -9 uwsgi
  • 启动uwsgi进程

    1
    uwsgi --ini uwsgi.ini