浅谈Django+Gunicorn+Nginx部署之路


Posted in Python onSeptember 11, 2019

前言

最近,我已经成功将我的个人网站从 Flask 迁移到 Django 了,最早接触 Django 的时候大概是在 4 年前,我记得那个时候 Django 中的路由配置使用 正则 来进行的,但是我有特别烦这个东西,所以就果断弃坑了。然后今年年初的时候,我用 Flask 写了一个我的个人网站,刚开始的时候功能还是比较简单,看着路由配置和部署规则都很方便,就果断采用了。但是后来我想添加的功能越来越多的时候,我发现我已经越来越难掌控它了,正好最近我稍微看了一下 Django 这几年的变化,最新的 2.2 版本还是很不错的,路由规则和 Flask 已经一致了,所以我就重新入坑了。

目前我的个人网站基本功能已经迁移完毕。但是在部署的时候,我遇到了一些问题,在网上看了一些解决方法,要么太乱,要么太旧,个人觉得都已经不太适用了。所以在这里记录一下我的部署过程。

部署

网上有很多都是用 UWSGI 的方式来部署,但是我个人比较喜欢 Gunicorn,所以以下内容我只是记录了 Django + Gunicorn + Nginx 在 Ubuntu 上的部署方式相关内容。

步骤一

上传网站源码至目标服务器

由于我的源码是用 Github 来托管的,所以我直接执行下述命令来克隆我的网站源码到服务器即可。

git clone https://github.com/your-name/repo-name.git

# 进入项目目录
cd repo-name

# 创建并激活虚拟环境
python3 -m virtualenv venv
source venv/bin/activate

# 安装项目依赖
pip install -r requirements.txt

目前我的网站采用的相关依赖包如下:

autopep8
Django
django-bootstrap4
django-ckeditor
gunicorn
Markdown
Pillow
python-slugify
requests

这里有个坑需要注意,如果你使用了 awesome-slugify,请尝试使用 python-slugify,因为有的服务器可能无法正常安装 awesome-slugify,具体 BUG 可参考:Clashes with python-slugify package。

步骤二

修改项目相关配置,并进行静态资源收集

由于我需要将我的网站部署到生产环境,所以我需要关闭 Django 的调试模式,并修改静态资源相关配置,示例配置如下所示:

settings.py

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')

DEBUG = os.environ.get('DJANGO_DEBUG', False)

TEMPLATE_DEBUG = os.environ.get('DJANGO_TEMPLATE_DEBUG', False)

ALLOWED_HOSTS = ["*"]

TEMPLATES = [
  {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
    'APP_DIRS': True,
    'OPTIONS': {
      'context_processors': [
        'django.template.context_processors.debug',
        'django.template.context_processors.request',
        'django.contrib.auth.context_processors.auth',
        'django.contrib.messages.context_processors.messages',
      ],
    },
  },
]

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
  os.path.join(BASE_DIR, 'static'),
]

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

然后执行如下命令进行静态资源收集:

python manage.py collectstatic

之后,我还需要创建一个 Gunicorn 进程的相关配置,示例配置如下所示:

gunicorn.conf.py

# 安装
# sudo pip3 install gunicorn

import sys
import os
import logging
import logging.handlers
from logging.handlers import WatchedFileHandler
import multiprocessing

BASE_DIR = '/home/hippie/hippiezhou.fun/src'
sys.path.append(BASE_DIR)

LOG_DIR = os.path.join(BASE_DIR, 'log')
if not os.path.exists(LOG_DIR):
  os.makedirs(LOG_DIR)

# 绑定的ip与端口
bind = "0.0.0.0:8000"

# 以守护进程的形式后台运行
daemon = True

# 最大挂起的连接数,64-2048
backlog = 512

# 超时
timeout = 30

# 调试状态
debug = False

# gunicorn要切换到的目的工作目录
chdir = BASE_DIR

# 工作进程类型(默认的是 sync 模式,还包括 eventlet, gevent, or tornado, gthread, gaiohttp)
worker_class = 'sync'

# 工作进程数
workers = multiprocessing.cpu_count()

# 指定每个工作进程开启的线程数
threads = multiprocessing.cpu_count() * 2

# 日志级别,这个日志级别指的是错误日志的级别(debug、info、warning、error、critical),而访问日志的级别无法设置
loglevel = 'info'

# 日志格式
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"'
# 其每个选项的含义如下:
'''
h     remote address
l     '-'
u     currently '-', may be user name in future releases
t     date of the request
r     status line (e.g. ``GET / HTTP/1.1``)
s     status
b     response length or '-'
f     referer
a     user agent
T     request time in seconds
D     request time in microseconds
L     request time in decimal seconds
p     process ID
'''

# 访问日志文件
accesslog = os.path.join(LOG_DIR, 'gunicorn_access.log')
# 错误日志文件
errorlog = os.path.join(LOG_DIR, 'gunicorn_error.log')
# pid 文件
pidfile = os.path.join(LOG_DIR, 'gunicorn_error.pid')

# 访问日志文件,"-" 表示标准输出
accesslog = "-"
# 错误日志文件,"-" 表示标准输出
errorlog = "-"

# 进程名
proc_name = 'hippiezhou_fun.pid'

# 更多配置请执行:gunicorn -h 进行查看

之后可用通过如下方式启动我们的网站:

# 启动方式(首先需要切换到项目根目录,即和 manage.py 在同级目录下):

gunicorn -c gunicorn.conf.py website.wsgi:application

# 或
gunicorn website.wsgi:application -b 0.0.0.0:8000 -w 4 -k gthread

# 或
gunicorn website.wsgi:application -b 0.0.0.0:8000 -w 4 -k gthread --thread 40 --max-requests 4096 --max-requests-jitter 512

# 查看进程
ps aux | grep gunicorn

步骤三

配置 Nginx

通过前两步,我们可以成功将我们的网站跑起来,但是目前还只能在内部访问,所以我们需要通过 Nginx 来做反向代理,供外网访问。

执行下述命令进行安装和配置

sudo apt-get install nginx

sudo service nginx start

# 备份默认配置
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

# 启动 Vim 修改我们的网站配置
sudo vim /etc/nginx/sites-available/default

示例配置如下所示:

server{
    ...
    server_name hippiezhou.fun *.hippiezhou.fun;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    ...

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        # try_files $uri $uri/ =404;
        proxy_pass     http://127.0.0.1:8000; #此处要和你 gunicore 的 ip 和端口保持一致
        proxy_redirect   off;

        proxy_set_header  Host         $host;
        proxy_set_header  X-Real-IP      $remote_addr;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto  $scheme;
    }

    location /static {
        alias /root/hippiezhou.fun/src/staticfiles; # 此次需要配置为你的网站对应的静态资源的绝对路径
    }

    location /media {
        alias /root/hipiezhou.fun/src/media; # 如果你的网站有上传功能,需要配置该结点并指向目标路径
    }

    ...
}

配置完成后执行下述操作即可将我们的网站运行起来

# 若网站未启动执行该命令
gunicorn -c gunicorn.conf.py website.wsgi:application

sudo nginx -t
sudo service nginx restart

如果不出意外,网站应该是可以正常访问,如果静态资源依然不能访问,打开网站的 开发者工具看一下是什么错误。

  • 如果是 404 的问题,请确保你的 settings 相关配置和我上面列出来的是一致的;
  • 如果是 403 的问题,应该是 Nginx 无权访问你指定的静态资源,你需要修改 Nginx 的用户类型,亲执行下述命令
sudo vim /etc/nginx/nginx.conf

将 user 后面的值修改为 root,然后重启 Nginx 即可。

最后,关于如何配置 HTTPS,这里就不过多介绍了,直接列出相关示例脚本:

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx

sudo certbot --nginx

# sudo certbot renew --dry-run

sudo ufw allow https

sudo systemctl restart nginx

总结

在部署的过程中,其实遇到最多的问题就是关于静态资源无法问题的问题,但是看到网上很多文章,都不一样,并且有的写的还是错误的。所以这里就总结一些。还好,一切顺利。算是填了 4 年前的一个坑吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
基于python3 类的属性、方法、封装、继承实例讲解
Sep 19 Python
基于Python socket的端口扫描程序实例代码
Feb 09 Python
Python基于生成器迭代实现的八皇后问题示例
May 23 Python
python之线程通过信号pyqtSignal刷新ui的方法
Jan 11 Python
pow在python中的含义及用法
Jul 11 Python
Django 使用easy_thumbnails压缩上传的图片方法
Jul 26 Python
用Python画一个LinkinPark的logo代码实例
Sep 10 Python
python实现大量图片重命名
Mar 23 Python
全网首秀之Pycharm十大实用技巧(推荐)
Apr 27 Python
python selenium xpath定位操作
Sep 01 Python
如何用python 操作zookeeper
Dec 28 Python
一文读懂python Scrapy爬虫框架
Feb 24 Python
初次部署django+gunicorn+nginx的方法步骤
Sep 11 #Python
python 如何将数据写入本地txt文本文件的实现方法
Sep 11 #Python
学习Django知识点分享
Sep 11 #Python
windows 10 设定计划任务自动执行 python 脚本的方法
Sep 11 #Python
使用Python为中秋节绘制一块美味的月饼
Sep 11 #Python
python破解bilibili滑动验证码登录功能
Sep 11 #Python
python修改FTP服务器上的文件名
Sep 11 #Python
You might like
PHP mcrypt可逆加密算法分析
2011/07/19 PHP
PDO防注入原理分析以及使用PDO的注意事项总结
2014/10/23 PHP
Linux下安装PHP MSSQL扩展教程
2014/10/24 PHP
浅析php设计模式之数据对象映射模式
2016/03/03 PHP
让ThinkPHP的模板引擎达到最佳效率的方法详解
2017/03/14 PHP
广告显示判断
2006/08/31 Javascript
一些不错的js函数ajax
2008/08/20 Javascript
JavaScript setTimeout和setInterval的使用方法 说明
2010/03/25 Javascript
基于jQuery的消息提示插件之旅 DivAlert(三)
2010/04/01 Javascript
javascript学习笔记(十三) js闭包介绍(转)
2012/06/20 Javascript
js改变鼠标的形状和样式的方法
2014/03/31 Javascript
详解Jquery的事件操作和文档操作
2016/12/19 Javascript
canvas学习之API整理笔记(二)
2016/12/29 Javascript
原生js实现中奖信息无间隙滚动效果
2017/01/18 Javascript
在js代码拼接dom对象到页面上去的模板总结(必看)
2017/02/14 Javascript
利用Jquery实现几款漂亮实用的时间轴(附示例代码)
2017/02/15 Javascript
jQuery EasyUI window窗口使用实例代码
2017/12/25 jQuery
vue 国际化 vue-i18n 双语言 语言包
2018/06/07 Javascript
JS获取当前时间的实例代码(昨天、今天、明天)
2018/11/13 Javascript
基于three.js实现的3D粒子动效实例代码
2019/04/09 Javascript
微信小程序canvas动态时钟
2020/10/22 Javascript
[00:32]2018DOTA2亚洲邀请赛iG出场
2018/04/03 DOTA
利用Python脚本在Nginx和uwsgi上部署MoinMoin的教程
2015/05/05 Python
python开发简易版在线音乐播放器
2017/03/03 Python
浅谈Django自定义模板标签template_tags的用处
2017/12/20 Python
Django web框架使用url path name详解
2019/04/29 Python
numpy concatenate数组拼接方法示例介绍
2019/05/27 Python
django mysql数据库及图片上传接口详解
2019/07/18 Python
室内设计专业个人的自我评价
2013/10/19 职场文书
工商管理专业职业生涯规划
2014/01/01 职场文书
新三好学生主要事迹
2014/01/23 职场文书
阿德的梦教学反思
2014/02/06 职场文书
企业管理毕业生求职信范文
2014/03/07 职场文书
七年级作文之英语老师
2019/10/28 职场文书
Golang二维数组的使用方式
2021/05/28 Golang
Win2008系统搭建DHCP服务器
2022/06/25 Servers