django应用的部署一般我从前到后采用nginx+ gunicorn + django +mysql的方式。这里总结了一下部署该博客网站的过程。就是在回忆过程中可能会有些遗漏和错误。。。。。。。
主要分为
- 数据库部署
- virtualenv环境搭建
- 代码部署
- nginx和gunicorn配置
这里使用社区版mysql作为后台数据库,还是蛮轻量的,比较适合中小型网站,mysql很流行也很稳定,而且开源免费、网络上文档非常多。
操作系统使用的是centos7,而django我用的是1.8版本python最低需要2.7版本。centos7自带的就是python2.7,相较centos6内置的python2.6,免去了升级的功夫(不过我用virtualenv搭建python环境,至于操作系统是2.7还是2.6没啥关系),还有由于centos7内置的repo源里没有加入mysql,所以需要自己另外添加repo源。
可以这样做:
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5.noarch.rpm yum install mysql-server #安装python的MySQL库 yum install MySQL-python #启动mysql 貌似centos7改变了服务启动方式么 = = service mysqld start Redirecting to /bin/systemctl start mysqld.service #默认数据库root密码为空,登录 mysql -uroot #建库 create database dbname character set utf8 collate utf8_bin; grant all privileges on dbname.* to usrname@localhost identified by 'xxxxx'; FLUSH PRIVILEGES;
OK,数据库建好了,用mysql -uusername 登录下,能登录就说明成功了。到时候建表啊或改表等操作,可以用django提供的migrate来做,十分方便。
虽然是一个小站,但是也应该养成定时备份的好习惯。整个库十分轻量,不写文章N天也不见得会有更新。可以每天定时把整个库或者自己用的几张表备份下,我这边就把除了django自建的表外的都备份了一下。脚本如下:
#!/bin/bash #backup mysql tables #Don't need tables: auth* django* MySQL_USER=xxxxx MySQL_PASSWORD=xxxxx MySQL_HOST=localhost MySQL_PORT=3306 MySQL_DUMP_PATH=/mysql_backup MySQL_DATABASE_NAME=blog DATE=$(date '+%Y-%m-%d') a=0 [ -d ${MySQL_DUMP_PATH} ] || mkdir ${MySQL_DUMP_PATH} cd ${MySQL_DUMP_PATH} [ -d logs ] || mkdir logs [ -d ${DATE} ] || mkdir ${DATE} cd ${DATE} TABLE_NAME_ALL=$(mysql -u${MySQL_USER} -p${MySQL_PASSWORD} -P${MySQL_PORT} -h${MySQL_HOST} ${MySQL_DATABASE_NAME} -e "show tables"|egrep -v "(Tables_in*|auth*|django*)" ) for TABLE_NAME in ${TABLE_NAME_ALL} do mysqldump -u${MySQL_USER} -p${MySQL_PASSWORD} -P${MySQL_PORT} -h${MySQL_HOST} ${MySQL_DATABASE_NAME} ${TABLE_NAME} >${TABLE_NAME}.sql echo "${TABLE_NAME} dump ok" let a=$a+1 sleep 1 done [ "$?" == 0 ] && echo "${DATE}: Backup tables succeed" >> ${MySQL_DUMP_PATH}/logs/BlogMysqlDump.log [ "$?" != 0 ] && echo "${DATE}: Backup tables not succeed" >> ${MySQL_DUMP_PATH}/logs/BlogMysqlDump.log echo "total records: $a" exit 0
之后就设一个定时每天跑就是了,时间长了。可以手动或写个脚本把30天前甚至更久前的备份删除。
#backup mysql every day 0 3 * * * /root/tools/mysqlbackup.sh >> /tmp/backupmysql.log 2>&1
virtualenv可以帮助解决在同一台服务器上共存不同python版本和不同环境的问题。它能提供一个虚拟环境,将不同的版本放在各自的虚拟环境中而互不影响,起到相互隔离的作用。
在安装前,先设计一个目录结构
sites/
└── myblog
├── database
├── media
│ └── pic
├── source
│ └── myblog
├── static
│ ├── admin
│ ├── bootstrap
│ ├── css
│ ├── jquery
│ └── pic
└── virtualenv
├── bin
├── include
├── lib
├── lib64 -> lib
└── pip-selfcheck.json
在sites目录下面建立站点名称。然后在下层目录结构中分别存放数据库、图片、程序代码、静态文件、和虚拟环境。数据库目录可以不要,因为我使用的是mysql,如果使用sqlite的话就可以把文件存在database目录中了。
安装的话pip install virtualenv 然后cd 到virtualenv目录下,创建虚拟环境, virtualenv . 注意这里有个点。而且这台服务器用的python版本默认是2.7,如果需要指定版本的话需要先安装对应版本的python,然后指定该python环境创建。
virtualenv创建好虚拟环境后应该就会有bin include lib lib64 这几个目录了。那如何进入虚拟环境呢,cd 到 bin目录下 source activate 就可以了。
然后就可以根据自己的需要安装python模块了。 然后安装完了可以pip freeze > requirement.txt 生成虚拟环境所需的包列表,在当前的虚拟环境下安装的python模块是相互间隔离的。
我的代码是提交到github上面的,部署的话很简单。先cd 到上面提到的source目录 git clone XXXXX,就能把代码下载到本地了,然后需要注意的是配置文件的修改,特别是DATABASES TIME_ZONE STATIC_URL 等等以及多说的相关配置,是与本地开发电脑不同的,需要改成线上环境的配置。像是配置文件的话一般是不需要每次更新的,可以在配置文件所在的目录下创建一个.gitignore文件,在里面添加不需要更新的文件,例如/settings.py 。那么以后的更新就可以用git pull 来进行了。
这一块主要的目的是用nginx来伺服静态页面和图片,同时将nginx暴露在公网上更加安全可靠。gunicorn是专业的python WSGI http服务器,因为在生产环境下不应该再使用django自带的开发服务器了。
具体的我之前已经写过了 = = 可以参考过去的博客文章,就当作这篇是一个补充或者拾遗把。
今天需要重新部署一套django环境,所以照着原来自己写的文档部署,结果发现——————并没有什么卵用。。。。。挺多细节的地方都忘了。
所以记录以下几点提醒下自己。
首先是nginx,nginx直接到官方网上http://nginx.org/packages/下载对应系统的rpm包。不多说了
然后再/etc/nginx/conf.d下另建一个配置文件,内容如下为例
server { listen 8000; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/log/host.access.log main; location / { #nginx反向代理默认是80端口,如果前面配置的listen是80的话这里只要配proxy_set_header Host $host;如果是其他端口要加$server_port变量,否则http请求头传递端口信息会变成80端口,这样就错了 proxy_set_header Host $host:$server_port; #获取用户ip proxy_set_header X-Forwarder-For $remote_addr; proxy_pass http://127.0.0.1:8999; } location /static { alias /root/workorder/static; } location /media { alias /root/workorder/media; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
这里贴一下,以后可以用作模板。主要是提醒下自己因为实际的工作环境中django肯定是关闭debug模式的,一旦关闭debug模式,django框架就不再伺服静态文件了。所以nginx还要配置location /static项,如果有必要处理图片的话 要配置location /media 。而且还有一点要补充,如果项目中使用了django框架admin模块里的日期插件等js和css的话,开发中可以直接在页面中引入
<link rel="stylesheet" type="text/css" href="/static/admin/css/forms.css" /> <script type="text/javascript">window.__admin_media_prefix__ = "/static/admin/";</script> <script type="text/javascript">window.__admin_utc_offset__ = "28800";</script> <script type="text/javascript" src="/admin/jsi18n/"></script> <script type="text/javascript" src="/static/admin/js/core.js"></script> <script type="text/javascript" src="/static/admin/js/jquery.js"></script> <script type="text/javascript" src="/static/admin/js/jquery.init.js"></script> <script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script> <script type="text/javascript" src="/static/admin/js/actions.js"></script> <script type="text/javascript" src="/static/admin/js/calendar.js"></script> <script type="text/javascript" src="/static/admin/js/admin/DateTimeShortcuts.js"></script>
但是一旦debug模式关闭后,由于改为nginx伺服静态页面,这些就失效了,会报找不到这些js的。需要将django源码中admin模块用的js和css文件放到自己django项目中的static目录中。我就图方便直接将admin模块里存放静态文件的整个admin文件夹放到static目录中了,这样html标签也就不需要修改了。
另外遇到个奇葩问题,就是django的setting.py文件中我配置了STATIC_ROOT项目,照理说,配置完成后使用python manage.py collectstatic 命令就会把对应django项目中的static目录中的文件拷贝到STATIC_ROOT所配置的目录中,但是这次不知道为啥,一执行该命令,等了很久也不输出东西,用top监控一下系统 就会看到该进程将一颗CPU的负载占满了,= = !。 不过没关系,知道了原理,在部署脚本里把文件拷贝过去就可以了。
第三点,由于使用gunicorn作为wsgi server。启动的时候经常是手工配置参数的,这次决定写一个配置文件,这样方便管理。配置文件如下:
bind = "127.0.0.1:8999" workers = 2 chdir = "/root/workorder/source/workordersys" accesslog = "/root/workorder/logs/gunicorn_access.log" errorlog = "/root/workorder/logs/gunicorn_error.log" daemon = True
bind表示绑定的ip端口,就是前面nginx转发过来流量的地址
workers表示启动多少个处理请求的进程数,官网文档中有这么配置,将workers开到cpu线程数X2+1,将配置文件作为python source file,在里面引用python模块写成python代码,不过我不推荐这样。不是高并发业务,处理请求的进程数也没必要开那么大。
import multiprocessing bind = "127.0.0.1:8000" workers = multiprocessing.cpu_count() * 2 + 1
chdir 表示转换工作目录。 因为启动的时候后面要跟 一个字符串 表示django中的wsgi的application方法,所以要指定工作目录。
accesslog和errorlog分别表示日志和错误日志
daemon 表示开启守护进程
启动的话也不需要 nohup gunicorn XXXXXXX & 这种方式了 ,直接gunicorn -c gunicorn.cfg workordersys.wsgi:application 就可以了。
Cloudhu 个人随笔|built by django|
沪ICP备16019452号-1