本文介绍的是如何将Django的工程代码部署到现网上,供外网用户访问。
写在前面
本地开发我们知道,需要将配置文件 settings.py 中的 DEBUG
设置为 True
即可满足我们本地开发的需求,那么要将代码部署到现网环境需要考虑的内容就比较多,比如静态资源的访问上,我们需要使用nginx来帮助我们处理静态资源,以提高访问的高可用和高可靠性,还有服务进程的管理上也是需要使用Procfile来帮助我们管理进程,下面将讲述我通过 Nginx + gunicorn + Django 来实现正式环境部署Django工程代码的。
静态资源合并
要将Django工程代码部署到现网,我们肯定是需要在现网环境执行 pip install -r requirements.txt
来将项目所依赖的库进行下载安装,之后我们就需要将工程的所有静态文件还有Django admin的静态资源进行打包,如何进行资源整合的呢?(这里说的静态资源指: javascript / css / images 等文件)
在工程的配置文件 settings.py 中有三个配置项: STATICFILES_DIRS / STATIC_ROOT / STATIC_URL,和工程的静态资源息息相关,下面分别介绍一下:
- STATICFILES_DIRS: 表示工程里静态资源的引用路径,默认为空
[]
,将只会引用各个application目录下面的static子目录下的内容,我们可以将其设置为如下工程目录下的 static 目录,那么静态资源会先从 STATICFILES_DIRS 中查询,如果没有查到,才会去application下的静态资源目录中查询STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]
- STATIC_ROOT: 表示执行命令
python manage.py collectstatic --noinput
之后,工程所有的静态资源存放路径,我们可以将其设置为 `STATIC_ROOT = 'staticfiles',那么执行完命令之后,就会在工程目录下创建一个目录名为 staticfiles,里面存放的是工程的所有静态资源 - STATIC_URL: 表示静态资源的访问url,默认为 static。比如在本地开发环境下,我们想要访问某个application下的 static/js/test.js 文件,可以在浏览器中输入 http://127.0.0.1:8000/static/js/test.js,该域名中的 static 就是这里的 STATIC_URL 的值决定的
通过执行命令 python manage.py collectstatic --noinput
命令之后,就会将工程的所有静态资源进行打包,放在 STATICFILES_DIRS 目录下,这样做的目的,是为了方便后面nginx能够方便访问到。
nginx的搭建部署
这里我参考的是这里安装的nginx,一些库的作用大致说明一下:
- pcre: 是为了支持配置文件 nginx.conf 中使用正则表达式
- zlib: 是为了支持http包的内容做gzip格式的压缩,在配置文件 nginx.conf 中配置
gzip on
# 安装nginx依赖的一些包
yum -y install make pcre pcre-dev zlib zlib-devel gcc-c++ libtool openssl openssl-devel
mkdir -p /data/jshan/applications/nginx/
cd /data/jshan/applications/nginx/
# 下载包并解压
wget http://nginx.org/download/nginx-1.16.0.tar.gz
wget https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz
wget http://zlib.net/zlib-1.2.11.tar.gz
tar -zxf nginx-1.16.0.tar.gz && mv nginx-1.16.0 nginx-src
tar -zxf pcre-8.43.tar.gz
tar -zxf zlib-1.2.11.tar.gz
# 安装nginx
cd nginx-src
./configure --prefix=/data/jshan/applications/nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream --with-debug --with-pcre=../pcre-8.43 --with-zlib=../zlib-1.2.11
make && make install
# 启动nginx
../sbin/nginx
为了保证nginx能够访问到我们的Django应用中的静态资源,这里需要配置一下 nginx.conf 配置文件,由于我的Django工程静态资源所在目录为 /data/jshan/django-project/test_pipeline/staticfiles,工程的启动服务访问地址为 http://127.0.0.1:8001,那么我的 nginx.conf 配置文件内容为:
server {
listen 8011;
access_log /data/jshan/django-project/test_pipeline/logs/access.log;
error_log /data/jshan/django-project/test_pipeline/logs/error.log;
location /static/ {
alias /data/jshan/django-project/test_pipeline/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8001;
}
}
这样要访问工程的静态资源就可以使用 http://xxx.xxx.xxx.xxx:8001/static/js/test.js 来访问到服务器上 /data/jshan/django-project/test_pipeline/staticfiles/js/test.js 文件了。
gunicorn
我们在本地启动Django工程可以直接使用 python manage.py runserver 127.0.0.1:8080
方式来启动,但是到了现网环境,为了保证服务进程数量的控制,这样启动是不合适的,这里可以使用 gunicorn 方式来启动,它可以设置工程启动的进程数和线程数等等,gunicorn的使用可以参考这里,我这里启动的命令是:
gunicorn test_pipeline.wsgi -w 1 --threads 1 -b 127.0.0.1:8001 --daemon --access-logfile /data/jshan/django-project/test_pipeline/access_app.log --error-logfile /data/jshan/django-project/test_pipeline/error_app.log --access-logformat '[%(h)s] %({request_id}i)s %(u)s %(t)s "%(r)s" %(s)s %(D)s %(b)s "%(f)s" "%(a)s"'
但是为了方便管理工程的启动命令,我这里使用的是 Procfile 来管理进程,如何操作的呢?就是在工程目录下面新建一个文件,文件名为 Procfile,里面的内容如下:
web: gunicorn test_pipeline.wsgi -w 1 --threads 1 -b 127.0.0.1:8001 --daemon --access-logfile /data/jshan/django-project/test_pipeline/access_app.log --error-logfile /data/jshan/django-project/test_pipeline/error_app.log --access-logformat '[%(h)s] %({request_id}i)s %(u)s %(t)s "%(r)s" %(s)s %(D)s %(b)s "%(f)s" "%(a)s"'
这样做的好处,主要是为了将该工程相关的所有需要启动的进程,放在一起集中管理。要去解析并执行该进程管理文件,可以使用 honcho、heroku等,这里我使用的是 honcho,这样工程的启动命令如下,在工程的根目录下执行(Procfile文件需在此目录下):
cd /data/jshan/django-project/test_pipeline
honcho -d . start # -d 表示后台运行
至此正式环境部署发布Django工程的整个流程就走完了,最后说明一下Django配置文件 settings.py 中的一些配置在正式环境中部署时,遇到的一些情况进行说明和解释,如需了解更多该配置文件中的配置项的使用情况,可以查阅这里。
DEBUG
当设置DEBUG = False
时,如果不设置ALLOWED_HOSTS
,即该值为空[]
,那么在访问Django工程的时候,会返回 Bad Request (400)
当设置DEBUG = True
时,如果不设置ALLOWED_HOSTS
,其值为['localhost', '127.0.0.1', '[::1]']
,所以本地开发的时候,可以访问,可以查阅这里了解详情TIME_ZONE
配置TIME_ZONE
默认为 UTC,在查看日志的时候,会发现和中国的时间差距8小时;在Django工程中使用datetime.datetime.now()
得到的时间也是 UTC 的时间,与中国的时间少了8小时,所以如果为了将其转化为东八区的时间,这里我们需要设置该配置的值为 Asia/Shanghai,具体可以参考这里.
参考
- Deploying Django with nginx and gunicorn