在Apache中部署Django应用
在apache中部署的时候,需要启用apache的mod_wsgi模块,这个模块用来兼容python的wsgi应用,包括Django。How to use Django with Apache and mod_wsgi中有详细介绍。
安装Apache和mod_wsgi
建议使用第二种方式,安装ius源中python**wsgi。
使用yum直接安装mod_wsgi
CentOS中提供了mod_wsgi的安装包,安装的时候会连同依赖的apache(在CentOS中名为httpd)一起安装:
$ yum install -y mod_wsgi
Dependencies Resolved
================================================================================
Package Arch Version Repository
Size
================================================================================
Installing:
mod_wsgi x86_64 3.4-18.el7 os 77 k
Installing for dependencies:
apr x86_64 1.4.8-3.el7_4.1 os 103 k
apr-util x86_64 1.5.2-6.el7 os 92 k
httpd x86_64 2.4.6-88.el7.centos os 2.7 M
httpd-tools x86_64 2.4.6-88.el7.centos os 90 k
mailcap noarch 2.1.41-2.el7 os 31 k
但是根据Django Apache and Virtualenv ImportError: No module named site中的说法,如果wsgi编译时使用的python版本和django应用使用python版本不一致,可能会出现找不到python package的情况:
#日志文件 /var/log/httpd/error_log
ImportError: No module named site
ImportError: No module named site
ImportError: No module named site
ImportError: No module named site
ImportError: No module named site
ImportError: No module named site
mod_wsgi中建议使用pip安装,看了一下还是挺麻烦的。Django Apache and Virtualenv ImportError: No module named site中的标题为Solved in CentOS 7 with Apache 2.4.6
答案中给出的用ius源安装的方法比较方便。
使用ius源中的python36u-mod_wsgi
首先安装ius源:
$ curl https://setup.ius.io/ | bash
ius源中包含了不同python版本的mod_wsgi:
$ yum search mod_wsgi
python35u-mod_wsgi-debuginfo.x86_64 : Debug information for package python35u-mod_wsgi
python36u-mod_wsgi-debuginfo.x86_64 : Debug information for package python36u-mod_wsgi
koschei-frontend.noarch : Web frontend for koschei using mod_wsgi
mod_wsgi.x86_64 : A WSGI interface for Python web applications in Apache
python35u-mod_wsgi.x86_64 : A WSGI interface for Python web applications in Apache
python36u-mod_wsgi.x86_64 : A WSGI interface for Python web applications in Apache
viewvc-httpd-wsgi.noarch : ViewVC configuration for Apache/mod_wsgi
我使用的是python3.6,直接安装python36u-mod_wsgi,如果ius里也没有你用的版本,那么就考虑自己编译安装mod_wsgi。
yum erase mod_wsgi # 卸载之前安装的mod_wsgi
yum install -y python36u-mod_wsgi
安装完成之后会生成文件 /etc/httpd/conf.modules.d/10-wsgi-python3.6.conf,这个就是新安装的apache模块的配置文件。
在httpd.conf配置wsgi应用
Apache和mod_wsgi安装完成之后,在httpd.conf中添加下面的配置(路径根据实际情况配置),可以直接在 /etc/httpd/conf/httpd.conf
中添加,也可以在/etc/httpd/conf.d/
单独创建一个包含下面配置的文件:
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonHome /path/to/venv
WSGIPythonPath /path/to/mysite.com
<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIScriptAlias
后面紧跟着的是应用的base URL路径,然后是应用的wsgi文件。
如果Django应用使用的是virtualenv创建的运行环境,用WSGIPythonHome
指定virtuanenv的路径。
WSGIPythonPath
指定整个项目的文件目录,是import时的根路径,确保所有的项目文件都在这个目录中。
<Directory>
中的配置是允许apache读取wsgi.py文件。
Apache2.4以前的版本,需要把Require all granted
换成Allow from all
。
如果配置不生效,到/var/log/httpd/error_log
中找线索。
将mod_wsgi配置成daemon模式
在非windows平台上,mod_wsgi推荐使用daemon模式。使用daemon模式后,前面的配置的WSGIPythonHome
和WSGIPythonPath
要去掉,改为在WSGIDaemonProcess
中用python-home
和python-path
指定,修改后的配置如下:
WSGIProcessGroup example.com
WSGIDaemonProcess example.com python-home=/path/to/venv python-path=/path/to/mysite.com lang='en_US.UTF-8' locale='en_US.UTF-8'
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py process-group=example.com
注意WSGIDaemonProcess一行中的en_US.UTF-8,如果Django应用会打印utf-8编码的字符,需要将wsgilang和local设置为UTF-8,否则wsgi会报错:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 154-155: ordinal not in range(128)
如果在shell终端用python ./manage.py runserver
运行时也报同样的错误,修改/etc/locale.conf文件后重新登录:
$ cat /etc/locale.conf
LANG=en_US.utf8
LC_CTYPE=en_US.UTF-8
一个配置wsgi配置样例
下面这个独立的(Apache Virtual Host Containers in Separate Files)配置文件中,将django的日志也拆分了出来:
# cat /etc/httpd/conf.d/discount.conf
<VirtualHost *:80>
ServerName 127.0.0.1 # 根据实际情况设置
WSGIProcessGroup discount
WSGIDaemonProcess discount python-home=/opt/discount/env python-path=/opt/discount/mysite lang='en_US.UTF-8' locale='en_US.UTF-8'
WSGIScriptAlias / /opt/discount/mysite/mysite/wsgi.py process-group=discount
<Directory /opt/discount/mysite/mysite/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
LogLevel info
ErrorLog "logs/discount_error_log"
CustomLog "logs/discount_access_log" combined
</VirtualHost>
上面的logs目录是/etc/httpd/logs,它是符号链接,链接到了/var/log/httpd。
Django的日志和wsgi的日志是分开的,但是用mod_wsgi运行django应用的时候,Django的日志目录需要能够被apache用户读写,因为httpd进程的用户是apache。
最好创建一个单独的目录,并且目录所属修改为apache:
mkdir -p /var/log/discount/
chwon apache:apache /var/log/discount/
注意Django日志文件不能在/tmp目录中,Django日志位于/tmp目录中时,wsgi虽然不报错,但是日志文件也不会创建,比较奇怪。
下面是Django的日志配置(在项目的settings.py中):
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s',
}
},
'handlers': {
'file': {
'level': 'DEBUG',
'formatter': 'standard',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/discount/discount.log',
'maxBytes': 1024*1024*100,
'backupCount': 10,
},
'console':{
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'standard',
}
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
'wechat': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
}
},
}
文件服务器
Django本身不提供文件服务,静态文件服务的需要用nginx、apache等软件实现。