Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试

参照追梦人物老师的教程部署django博客应用,本贴记录了本人的真实部署过程,以及部署过程中遇到的无数问题和相应的解决方法。本贴为学习记录贴,非教程贴,进一步的权威信息参见原博主。
操作supervisor参加supervisor; 操作nginx参加nginx。

  • 购买服务器

通过优惠购买或者试用获得一台阿里云服务器,购买成功后首先是重置密码。
然后下载并安装xshell,打开并远程连接到服务器上。

  • 创建新用户

一般应用不会部署到root用户下,不安全。因此新建用户

[root@xxx ~]# adduser wwb

配置用户密码

[root@xxx ~]# adduser wwb

将新用户添加到超级权限组

[root@xxx ~]# usermod -aG wheel wwb

将用户wwb添加到wheel用户组下,wheel用户组表示管理组。

切换到新用户

# su - wwb

安装wget,便于下载软件

sudo yum install -y wget
  • 下载安装python

进入python官网,右键获取源码链接。
在这里插入图片描述

https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz

进入wwb的用户目录下,新建src目录并进入,下载python源码到服务器

mkdir ~/src
cd ~/src
wget https://www.python.org/ftp/python/3.6.9/Python-3.6.9.tgz

安装可能的依赖:

sudo yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel

解压文件,并进入目录

tar -zxvf Python-3.6.9.tgz
cd Python-3.6.9

编写配置文件

./configure --prefix=/usr/local/python3

编译


make

安装

make install

在/usr/bin目录创建python3和pip3的软连接

ln -s /usr/local/python3/bin/python3.6 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
默认的文件目录用途

/usr/local/ ------ 用户的软件安装目录
/usr.bin/ ------ 用户的软件运行目录

环境变量与/usr/bin的关系

echo $PATH可以查看所有的环境变量:

echo $PATH在这里插入图片描述

可以看到/usr/bin以及/usr/local/sbin、/usr/sbin等特殊目录默认在环境变量中,因此当安装一个新的应用时可以选择将其软连接到/usr/bin等现有环境变量下,或者将安装目录添加到环境变量中。

永久添加环境变量
vim /etc/profile

添加代码:

PATH=$PATH:xx要添加的目录xx

执行永久生效:

source /etc/profile
  • 安装pipenv

pipenv是一个虚拟环境工具,需要本地建立项目时就使用pipenv虚拟环境,项目才能在服务器中使用pipenv快速建立相同的虚拟环境安装所需的依赖

pip3 install pipenv --user

遇到的问题:
本地创建django项目时不是用的pipenv,导致服务器部署时没有Pipfile文件,无法自动安装所需依赖。

解决:
重新使用pipenv创建虚拟环境,并在环境中新建项目。然后将业务代码复制到新项目中,得到一个使用pipenv工具新建的项目。

安装指定版本的pipenv(太新的版本会出错):
pip install pipenv==2020.5.28

创建虚拟环境:
pipenv --python python3.6
pipenv install Django
pipenv install Markdown

新建项目:
pipenv run django-admin startproject blogproject
更多信息参见追梦人物老师博客。

  • 部署前的准备工作

为了将本地项目部署到云服务器上,需要对本地项目做一些调整

首先需要调整settings.py文件的 ALLOWED_HOSTS的设置
ALLOWED_HOSTS = ['127.0.0.1', 'localhost ',  '139.196.xxx.xxx']

将服务器的公网IP或者域名添加到ALLOWED_HOSTS中,只有ALLOWED_HOSTS中配置的域名才允许访问django项目。

设置静态文件目录
  • 项目部署到线上服务器需要使用nginx进行服务代理,它最大的优势在于能够高效地处理项目中的静态文件。
  • 为了能让 Nginx 高效响应关于静态文件的请求,后续我们会把项目中的全部静态文件收集到一个统一的目录下(使用的是manage.py这个项目管理工具)。
  • STATIC_ROOT 就是部署项目时,项目中所有的静态文静聚合的目录。而STATIC_URL 则是STATIC_ROOT 在浏览器访问时所映射的地址。更详细的解释推荐参考另一位博主的说明。
  • 因此需要在settings.py文件中配置STATIC_URL 和STATIC_ROOT 的值:
 STATIC_URL = '/static/'
 STATIC_ROOT = os.path.join(BASE_DIR, 'static')

os.path.join(BASE_DIR, ‘static’)等于 /setting文件所在目录/static

git上传和拉取代码

使用github保存代码,方便本地和云服务器上传或拉取。windows参见这里和这里。linux参见这里。

  • windows系统git上传代码

首先要求github已经建立了一个仓库,并保证仓库至少有一个readme文件。

本地新建文件夹,克隆仓库

git clone https://github.com/xxx.git

配置签名和邮箱

git config --global user.name "my name"
git config --global user.email "my email"

生成本地密钥对

ssh-keygen -t rsa -C "[email protected]"

Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第1张图片
从保存目录中,找到id_rsa.pub文件,复制内容。

登录GitHub,点开右上角头像,下拉选择Settings;

选择"SSH and GPG KEYS",点击右上角的"New SSH key";

然后Title里面随便填,再把刚才id_rsa.pub里面的内容复制到Title下面的Key内容框里面,最后点击"Add SSH key",这样就完成了SSH Key的加密。

关联到GitHub

git remote add origin GitHub仓库地址

添加

git add filename

提交

git commit -m "信息"

上传

git push -u origin 

拉取

git pull

提交其他文件:

.gitREADME.md文件复制到另外的文件夹下,即可上传该文件夹下的内容。

  • linux系统git上传代码
生成token

linux需要使用token令牌进行登录,所以首先需要生成token

登录github后,右上角下拉框点“Setting”(倒数第二个)

在出现的页面中选择Developer settings

再点击personal access tokens 即可进行个人token的设置。

点击create new token进入具体的设置页面。
Note:不重要
Expiration:token有效的时间
Select scopes:token的作用:repo可以上传到仓库,delete-repo可以删除仓库,其他的根据自己需求选择,选好后create就可生成token。以后向git上push代码时将token复制到需要输入密码的地方即可。
注意:生成token后复制一下,不然页面刷新就看不到了。

生成本地密钥
ssh-keygen -t rsa -C "邮箱"

Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第2张图片
同Windows一样,复制公钥到github中。

克隆github仓库,得到本地仓库
git clone https://github.com/xxx.git
配置签名和邮箱
git config --global user.email "邮箱"
git config --global user.name "用户名"
测试是否链接成功
ssh -v git@github.com
ssh -T git@github.com

添加

git add filename

提交

git commit -m "信息"

上传

git push -u origin 

当需要输入账号密码时:

账号为注册邮箱
密码为token

拉取项目代码到云服务器

切换到普通用户,新建~etc/apps目录,拉取项目代码

su wwb
mkdir -p ~/apps
cd ~/apps
git clone <仓库地址>

进入项目中,根据pipfile文件安装项目依赖

cd ~/apps/myDjango
pipenv install --deploy --ignore-pipfile # Pipenv 从 Pipfile.lock 文件中安装项目依赖
  • 安装postgresql数据库:

项目中使用的数据库是postgresql数据库,首先将其安装到服务器上。

进入postgresql官网,选择合适的linux版本,复制安装代码即可。

# 安装rpm源
sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

yum -qy module disable postgresql
# 安装数据库服务器
sudo yum install -y postgresql11-server
# 初始化数据库
sudo /usr/pgsql-11/bin/postgresql-11-setup initdb

sudo systemctl enable postgresql-11
# 启动数据库服务器
sudo systemctl start postgresql-11
在postgresql中创建项目用到的数据库blog
1.进入数据库  
su - postgres ,psql -p5432
2.创建数据库  
create database dbname;
3.列出数据库(验证是否成功) 
\l
4.选择数据库  
\c dbname
5.创建表  
create table tablename(....);
6.验证表是否创建成功  
\d
7.查看表信息   
\d tablename 
8.向表插入数据
insert into ()
9.更新表数据
update tablename
10.删除表 
drop table tablename;

Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第3张图片
linux下postgres的基本数据库的更多操作命令参见这里。

执行数据迁移
pipenv run python manage.py makemigrations
# 执行数据迁移
pipenv run python manage.py migrate

执行迁移时报错
配置好数据库后,启动项目时报错:org.postgresql.util.PSQLException: FATAL: Ident authentication failed for user "ptms"
原因 :
postgresql的一个配置文件pg_hba.conf中没有信任该服务器ip导致报错。
解决:
找到相应配置文件

find / -name pg_hba.conf

修改配置:
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第4张图片
重启数据库服务:

systemctl restart postgresql-11.service
  • 启动服务器

# 切换到项目根目录
cd /home/wwb/apps/myDjango/blogproject/
# 使用runserver启动服务器 
pipenv run python manage.py runserver 0.0.0.0:8000

通过浏览器访问 ip:8000,访问成功。

  • 使用 Gunicorn进行生产环境的服务部署

runserver 开启的开发服务器仅用于开发测试,不建议用于生产环境。所以我们使用流行的 Gunicorn 来启动可以用于线上环境的服务器。
首先切换到普通用户

su wwb

进入项目根目录,安装 Gunicorn

cd ~/etc/apps/myDjango/blogproject/
pipenv install gunicorn

启动Gunicorn服务器

# wsgi文件在blogproject目录之下,因此执行命令要在blogproject目录中
pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 0.0.0.0:8000

启动成功后,通过浏览器访问。

可能遇到的问题

开启gunicorn 服务时显示连接失败
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第5张图片
原因:
连接的端口(8000)被占用;
解决:
查找占用进程,并关闭占用进程,然后重新开启。

lsof -i:8000
在这里插入图片描述

kill -9 19878

pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000
在这里插入图片描述

  • 启动 Nginx 服务器进行服务代理

一句话说明使用nginx的原因,可以粗浅地理解为用 django 去获取静态文件是很耗时的,但 Nginx 可以很高效地处理。

更细致地解释,参见追梦人物老师的博客:

Nginx (engine x) 是一个高性能的 HTTP 和反向代理 web 服务器,它的功能非常多,这里我们主要用它来处理静态文件以及将非静态文件的请求反向代理给 Gunicorn
当我们访问一个博客文章详情页面时,服务器会接收到下面两种请求:

  • 显示文章的详情信息,这些信息通常保存在数据库里,因此需要调用数据库获取数据。
  • 图片、css、js 等存在服务器某个文件夹下的静态文件。

对于前一种请求,博客文章的数据需要借助 django 从数据库中获取,Nginx 处理不了,它就会把这个请求转发给运行在 Gunicorn 服务中的 django 应用,让 django 去处理。而对于后一种静态文件的请求,只需要去这些静态文件所在的文件夹获取,Nginx 就会代为处理,不再麻烦 django。
---------------https://www.zmrenwu.com/courses/hellodjango-blog-tutorial/materials/74/

Nginx 的安装和启用
# 切换到普通用户
su wwb
# 安装 Nginx:
sudo yum install epel-release -y
sudo yum install nginx -y
# 启动Nginx服务:
sudo systemctl start nginx

在浏览器输入 ip(不输入端口则默认为 80 端口,Nginx 默认在 80 端口监听请求),看到 Nginx 的欢迎界面说明 Nginx 启动成功了。

可能遇到的问题

nginx启动成功后输入ip,无法访问默认的主页(80端口)。
原因:
云服务器未对外开启80端口,参考这里。
解决:
到服务器管理界面开启相应的端口。
在这里插入图片描述

配置nginx的服务信息

位于 /etc/nginx/nginx.conf 的nginx.conf文件是nginx服务器的配置信息,包括 Nginx 进程运行时的用户和组(分别为第一个和第二个参数)以及代理的虚拟服务的配置情况等。

/etc/nginx/nginx.conf

# 进程运行的用户和组,这里粗暴地设为root用户和组
user root root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

......

http {
    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;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    
    # 其他服务器的配置文件的存放地址
    include /etc/nginx/conf.d/*.conf;
	
	# 一个默认的服务器配置
    server {
        listen       80 default_server;   # 监听的端口
        listen       [::]:80 default_server;
        server_name  _;                   # 服务域名/ip
        root         /usr/share/nginx/html;

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

        location / {                  # 访问路径
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
    
  ......
  

配置项目的代理服务信息

# 切换到普通用户
su wwb
# 进入/etc/nginx/conf.d目录
cd /etc/nginx/conf.d
# 新建myBlog.conf配置文件
vim myBlog.conf

具体的配置信息:

server {
    charset utf-8;
    listen 80;
    server_name 139.196.xxx.xx;

    location /static {
        alias /home/wwb/apps/myDjango/blogproject/static;
    }

    location / {
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8000;
    }
}

监听80端口(访问ip时的默认端口),server_name为公网ip或域名,访问静态文件路径static_url时,nginx自动到static_root指定的路径下获取文件。访问其他路径时,将请求转发给本机的8000端口,那里运行的是Gunicorn 服务中的 django程序。

重启 nginx 使得配置生效

sudo systemctl restart nginx 
关闭 DEBUG 模式,收集静态文件

开发环境下,django 为了调试方便,会将 settings.py 文件中的 DEBUG 选项配置为 True,这样如果程序运行出错,调试信息将一览无余,这在开发时很方便,但部署到线上就会带来巨大安全隐患,所以我们把 DEBUG 选项设置为 False,关闭调试模式。

在本地将 settings.py 中的 DEBUG 设置为:

DEBUG=False

运行命令收集静态文件到之前配置的 STATIC_ROOT 目录下:

pipenv run python manage.py collectstatic

再次启动服务 Gunicorn

pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000

此时,当我们访问ip(域名)139.196.xxx.xx时,请求到达默认端口80,进入nginx服务器。当请求类型为静态文件时,nginx会快速地去static_root文件夹下获取资源,当请求非静态资源时,服务会转给运行于8000端口的django程序(运行于Gunicorn 服务中)。

  • 使用Supervisor守护Gunicorn 进程

当前的Gunicorn服务是我们手工启动的,一旦我们退出 shell,服务器就关闭了,博客无法访问。就算在后台启动 Gunicorn,万一哪天服务器崩溃重启了又得重新登录服务器去启动,非常麻烦。为此使用 Supervisor 来管理 Gunicorn 进程,这样当服务器重新启动或者 Gunicorn 进程意外崩溃后,Supervisor 会帮我们自动重启 Gunicorn
-------- https://www.zmrenwu.com/courses/hellodjango-blog-tutorial/materials/74/

先按 Ctrl + z 停止刚才启动的 Gunicorn 服务进程。

首先安装 Supervisor。注意这里使用的是系统自带的 pip2,因为截至本教程书写时 Supervisor 还不支持 Python3,不过这并不影响使用。
切换到普通用户

su wwb

安装supervisor

 pip install supervisor

在用户目录建立Supervisor相关的文件的目录结构

~/etc
├── supervisor
│ ├── conf.d
│ └── var
│ ├── log
└── supervisord.conf

其中 supervisord.conf 是 Supervior 的配置文件,通过echo_supervisord_conf方式创建,它会包含存放在conf.d 下的配置。
supervisor目录手动创建,其中var 目录下用于存放一些经常变动的文件,例如 socket 文件,pid 文件,log 下则存放日志文件。

进入 ~/etc 目录下生成 Supervisor 的配置文件:

cd ~/etc
echo_supervisord_conf > supervisord.conf

对supervisord.conf配置文件的调整

# [unix_http_server] 版块,设置file的值。
# 即让 socket 文件生成在 ~/etc/supervisor/var/ 目录下。注意 supervisor 不支持将 ~ 展开为用户 home 目录,所以要用绝对路径指定。
[unix_http_server]
file=/home/wwb/etc/supervisor/var/supervisor.sock   ; the path to the socket file


# [supervisord] 板块下的 logfile 和 pidfile 文件的路径,还有 user 改为系统用户,这样 supervisor 启动的进程将以系统用户运行,避免可能的权限问题:

[supervisord]
logfile=/home/wwb/etc/supervisor/var/log/supervisord.log ; main log file; default $CWD/supervisord.log
pidfile=/home/wwb/etc/supervisor/var/supervisord.pid ; supervisord pidfile; default supervisord.pid
user=root            ; setuid to this UNIX account at startup; recommended if root

# [supervisorctl] 板块,配置serverurl的值
[supervisorctl]
serverurl=unix:////home/wwb/etc/supervisor/var/supervisor.sock ; use a unix:// URL  for a unix socket

# [include] 版块,将 /home/wwb/etc/supervisor/conf.d/ 目录下所有以 .ini 结尾的文件内容包含到配置中来,这样便于配置的模块化管理,和之前 Nginx 配置文件的处理方式是类似的。注意取消行首的`;`注释。
[include]
files = /home/wwb/etc/supervisor/conf.d/*.ini
autorestart=True
将项目应用配置到supervisor中

进入 /home/wwb/etc/supervisor/conf.d目录,新建项目应用的配置文件 blog.ini

su wwb
cd /home/wwb/etc/supervisor/conf.d
vim blog.ini

应用的配置详情 blog.ini

# 程序名,后续开启关闭进程都使用程序名指代当前应用
[program:myDj]
# 程序需要执行的指令
command=pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000
# 执行指令时到达的路径
directory=/home/wwb/apps/myDjango/blogproject
# 是否自动启动,遭遇意外自动重启
autostart=true
autorestart=unexpected
# 开启当前应用的用户角色
user=root
# 应用的相关日志
stdout_logfile=/home/wwb/etc/supervisor/var/log/myDjango-stdout.log
stderr_logfile=/home/wwb/etc/supervisor/var/log/myDjango-stderr.log

启动 Supervisor

# -c 指定 Supervisr 启动时的配置文件。
supervisord -c ~/etc/supervisord.conf

进入 supervisorctl 进程管理控制台

supervisorctl -c ~/etc/supervisord.conf

执行 update 命令更新配置文件并启动应用

在这里插入图片描述

浏览器输入域名/IP,可以看到服务已经正常启动:

Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第6张图片

  • 使用 CDN 加快 Bootstrap 和 jQuery 的加载速度

使用 CDN 来加快本地文件Bootstrap 和 jQuery的加载速度。具体来说,替换 base.html 的几个静态文件的加载标签:

base.html

- <link rel="stylesheet" href="{% static 'blog/css/bootstrap.min.css' %}">
- <script src="{% static 'blog/js/jquery-2.1.3.min.js' %}"></script>
- <script src="{% static 'blog/js/bootstrap.min.js' %}"></script>
+ <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
+ <script src="https://cdn.bootcss.com/jquery/2.1.3/jquery.min.js"></script>
+ <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

替换后重启应用,提高访问速度

supervisorctl -c ~/etc/supervisord.conf restart myDj 

配置过程中遇到的一些问题和错误

问题:pipenv install安装速度太慢

制作Pipfile后,修改文件中source块下的url字段,设定为国内的pypi源即可。推荐的是清华的pypi源,具体设定如下:
bash;'>[source]
url=“https://pypi.tuna.tsinghua.edu.cn/simple”
verify_ssl=true。
name=“pypi”

报错:incorrect padding

Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第7张图片
原因:
django版本过低

解决:
在项目根目录执行命令,安装合适版本

pipenv install django==3.2.1

导包报错: attempted relative import beyond top-level package

原因:
python导包有相对导入层数限制

解决:
将多个子包的父包设为资源包。
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第8张图片

上传本地项目/文件到github:
首先克隆远程仓库

git clone https://github.com/xxxx.git

将得到的readme文件和.git文件复制到目标文件下。
然后提交文件就到了目标仓库了。

问题:在服务器上安装pipenv安装项目依赖出错:

$ pipenv install --deploy --ignore-pipfile
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第9张图片
原因:
pipenv版本问题,版本过高。

解决:
将pipenv(2022.4.20)换到低版本pipenv(2020.5.28)即可

pip install pipenv==2020.5.28

报错:安装项目依赖时,psycopg2找不到匹配版本或无法安装在这里插入图片描述

原因:
Linux找不到pipfile依赖中对应的psycopg2版本

解决:
删除pipfile配置文件中关于psycopg2的环境依赖信息,手动安装psycopg2库。
安装binary版本:

pipenv install psycopg2-binary

报错:启动服务时找不到django

原因:在root用户下安装的虚拟环境,切换到其他用户后不可用。
解决:切回到正确的用户

报错:服务器部署完成无法访问

原因:服务器没有开发对应的端口
解决:
服务器 -->安全组 -->安全组规则,添加需要的端口。
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第10张图片

报错:服务器在django项目中不被允许

解决:在setting的ALLOW POST中添加对应的ip。

报错:admin后台添加文章时报错

/ ProgrammingError / relation "blog_post“处的计数不存在第1行: SELECT COUNT(*) AS "__count”FROM "blog_post“WHERE "blog_po”
原因:
部署后没有执行完整的迁移
解决:
makemigrations + migrate

报错:点击文章详情页时报错Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第11张图片

原因:
linux系统下表示路径用/,而\表示转义!!!!!
解决:
将相应的路径系统统一改为 /

报错:nginx启动成功后,无法访问默认主页(80端口)

原因:未对外开启80端口,参考这里
解决:到服务器管理界面开启即可。
在这里插入图片描述

问题:如何查询linux用户信息

whoami 查看当前登录用户
cat /etc/passwd 查看所有⽤户信息
cat /etc/group 查看所有组信息
groups ⽤户名查看当前⽤户所在组,以及组内其它成员的信息

问题静态文件的相关处置

参考这里
STATIC_ROOT
STATIC_ROOT 是在部署静态文件(pyhton manage.py collectstatic)时,所有的静态文静聚合的目录。
STATIC_ROOT要写成绝对地址,在这里,比如我的项目mysite是/home/mysite/,那么STATIC_ROOT 为 /home/mysite/collect_static/
当部署项目时,django会把所有的static文件都复制到STATIC_ROOT文件夹下。

STATIC_URL
在浏览器上,利用前缀 STATIC_URL的具体内容,来映射STATIC_ROOT,
HTTP://192.168.1.2:8000/static 相当于 本地地址的STATIC_ROOT。

STATICFILES_DIRS
应用中,有时候需要在所有的app文件外面,建立一个公共的文件夹, 因为有些静态文件不是某个app独有的,那么就可以把它放到一个公共文件夹里面,方便管理(注意,建立一个公共的静态文件的文件夹只是一种易于管理的做法,但是不是必须的,app是可以跨app应用静态文件的,因为最后所有的静态文件都会在STATIC_ROOT里面存在)
那现在的问题是如何让django知道你把一些静态文件放到app以外的公共文件夹中呢,那就需要配置STATICFILES_DIRS了

STATICFILES_DIRS = (
os.path.join(BASE_DIR, ‘common_static’),
)

STATICFILES_DIRS告诉django,首先到STATICFILES_DIRS里面寻找静态文件,其次再到各个app的static文件夹里面找(注意, django查找静态文件是惰性查找,查找到第一个,就停止查找了)

报错:开启gunicorn 服务时显示连接失败

Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第12张图片
原因:
对应的端口(8000)被占用;
解决:
查找占用进程,并关闭占用进程,然后重新开启。

lsof -i:8000

在这里插入图片描述

kill -9 19878

pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000

在这里插入图片描述

nginx域名配置问题

对于nginx虚拟服务器的配置文件,其中server_name使用ip时,不用接端口

server {
charset utf-8;
listen 80;
server_name 139.196.xx.xxx;
location /static {
alias /home/yangxg/apps/HelloDjango-blog-tutorial/static;
}
location / {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8000;
}
}

问题:使用nginx代理服务后,pc端可以访问,手机端访问不了。

未知,待解决。

理解:启用nginx代理服务后,服务器实际上运行了两个服务:nginx服务外围代理(80端口),Gunicorn内层代理,处理非静态文件请求。

理解:echo_supervisord_conf > supervisord.conf

查看supervisord的配置信息并将文件写入到supervisord.conf中。

~ 等效于 用户的home目录

一个小坑:配置文件中,行前加;,表示对该行的注释

;[include]

linux环境变量PATH

  1. 需要明⽩以下2点:
    1、Linux的环境变量是保存在变量PATH中,可通过Linux shell命令 echo $PATH 查看环境变量。
    2、Linux环境变量值环境变量值之间是通过冒号:进⾏隔开的。

  2. 暂时的添加环境变量PATH:
    可通过export命令,如
    export PATH=$PATH:/usr/locar/myfile/bin,将/usr/locar/myfile/bin⽬录临时添加到环境变量中。

  3. 当前⽤户永久添加环境变量:
    vim ~/.bashrc
    ⽂件末尾添加:
    export PATH=$PATH: /usr/local/nginx/sbin/
    source ~/.bashrc

  4. 为所有⽤户永久添加某⼀环境变量:
    vim /etc/profile
    ⽂件末尾添加:
    PATH=$PATH:/usr/local/python3/bin
    执行永久生效:
    source /etc/profile

  5. etc/environment 下⾯添加,
    打开 /etc/environment ,在最后添加变量,然后运⾏下⾯2条命令。

sudo vi /etc/environment
source /etc/environment

测试supervisorctl 是否成功启动gunicorn 应用

访问gunicorn 服务:
获取网络资源— wget http://127.0.0.1:8000
展示网络资源— curl http://127.0.0.1:8000

出错:supervisorctl 启动成功却无法浏览器访问

原因:
supervisorctl 中的应用,域名配置出错,将应用域名写成-b 127.0.0.0:8000
解决:
正确域名为-b 127.0.0.1:8000

报错:supervisor报错couldn’t setuid to 0 Can’t drop privilege as nonroot user

原因:
启动supervisor的用户配置文件的用户program中的用户不是同一个用户导致

启动supervisor的是root用户
在这里插入图片描述>
supervisord.conf中的user是wwb
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第13张图片

解决:
将各处用户进行统一

supervisord日志报错:permition refuse

原因:
gunicorn应用要求的权限用户是root,而在supervisord中配置的gunicorn的启用用户是wwb
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第14张图片

supervisord-nginx-gunicorn联调

  • 首先启动gunicorn,判断gunicorn能否正常运行

进入目录:
/home/wwb/apps/myDjango/blogproject
执行:
pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000
在命令行访问,观察能否正常访问:
wget http://127.0.0.1:8000curl http://127.0.0.1:8000

  • 然后启动nginx,判断nginx是否正常运行,与gunicorn 能否正常通信

执行命令:
systemctl start nginx

判断nginx运行状态:
systemctl status nginx.service
Django学习之旅(十二)Nginx+Gunicorn+Supervisor部署Django博客应用以及各种排坑尝试_第15张图片

浏览器访问ip/域名,判断nginx+gunicorn是否正常运行

  • 关闭gunicorn,杀死相关进程,然后启动supervisord

gunicorn 运行页面执行 ctrl+z,关闭服务。
然后执行 lsof -i:8000,查找8000端口的进程。
执行 kill -9 pid关闭占用端口的进程。
启动supervisord服务:
supervisord -c /home/wwb/etc/supervisord.conf
进入控制台:
supervisorctl -c /home/wwb/etc/supervisord.conf
通过supervisorctl 启动gunicorn服务:
start myDj
查看supervisord日志,确认是否正常运行:
进入日志目录: cd /home/wwb/etc/supervisor/var/log
查看登录日志: cat myDjango-stderr.log
正常启动了相关服务:
在这里插入图片描述
命令行检验gunicorn服务:
curl http://127.0.0.1:8000
浏览器访问成功。

你可能感兴趣的:(django,nginx,gunicorn)