一个计算机技术爱好者与学习者

0%

好好学Python:Django部署到线上(修改版)

1. 前言

《Django部署到线上》一文中,很多步骤不是必须的,有些部分甚至是错误的,本文就精简修改一下。
目标:把djsite项目部署到/home/web目录中,并且给它分配一个域名为djsite.voidking.com。

2. 环境准备

2.1. supervisor

参考《CentOS安装配置Supervisor》,安装配置好supervisor。

2.2. python虚拟机

参考《CentOS安装配置pyenv》,安装好python3.6.1。

3. 项目部署

3.1. 代码准备

1、在/home/web目录中,执行命令克隆项目
git clone https://github.com/voidking/djsite.git

2、安装django
pip install django==1.11.7

3、安装pymysql
pip install pymysql

3.2. 数据库准备

1、创建数据库

1
2
# mysql -uroot -p
mysql> create database `djsite` default character set utf8 collate utf8_general_ci;

2、修改mysql的binlog格式为混合模式:

1
2
mysql> set global binlog_format=mixed;
mysql> exit;

3、修改djsite/djsite/settings.py中的数据库配置
vim djsite/djsite/settings.py

4、创建表结构

1
2
python manage.py makemigrations
python manage.py migrate

3.3. 启动项目

1、启动命令
python manage.py runserver

2、服务器测试访问
curl localhost:8000/blog/index

3、本地测试访问
使用浏览器查看 http://ip:8000/blog/index ,无法访问。
启动命令改为:python manage.py runserver 0.0.0.0:8000,此时即可在浏览器看到部署好的项目。

如果还是不能访问,尝试先关闭防火墙:systemctl stop firewalld

4. nginx配置

1、首先,在万网上配置域名解析,添加A记录,解析到阿里云服务器IP。假设解析好的域名为django.voidking.com。

2、在nginx的vhost中,添加django.voidking.com.conf,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80;
server_name django.voidking.com;
charset utf-8;
location /{
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 1024m;
client_body_buffer_size 128k;
client_body_temp_path data/client_body_temp;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_temp_path data/proxy_temp;

proxy_pass http://127.0.0.1:8000;
}
}

3、重启nginx,./nginx -s reload

4、测试访问
服务器:curl django.voidking.com/blog/index
本地浏览器:http://django.voidking.com/blog/index

至此,django项目已经部署成功,没有用到uwsgi。如果给django添加守护进程,那么我们的部署就接近完美了。那么,uwsgi又能干什么呢,我们继续研究。

5. uwsgi

5.1. 安装uwsgi

pip install uwsgi

编写测试:

1
2
3
4
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]

启动测试:
uwsgi --http :8001 --wsgi-file test.py

访问 http://ip:8001 ,即可看到Hello World 。

5.2. 一般启动

1、编写wsgi.py文件
编写django_wsgi.py文件,将其放在与文件manage.py同一个目录下。

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python
# coding: utf-8

import os,django
from django.core.handlers.wsgi import WSGIHandler

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djsite.settings")
django.setup()
application = WSGIHandler()

2、启动项目
uwsgi --http :8000 --chdir /home/web/djsite/ --module django_wsgi

3、查看启动结果
lsof -i :8000ps aux | grep uwsgi

4、测试访问
http://ip:8000/blog/index
此时,页面是没有样式的,也就是说静态资源加载失败。

5、配置静态资源
uwsgi --http :8000 --chdir /home/web/djsite/ --module django_wsgi --static-map=/static=static
此时,页面样式就正常了。

5.3. 高级启动

1、新建uwsgi.ini,与manage.py在同一级目录。

1
2
3
4
5
[uwsgi]
http = :8000
chdir = /home/web/djsite/
wsgi-file = django_wsgi.py
static-map = /static=static

2、启动uwsgi
uwsgi uwsgi.ini

3、测试访问
http://ip:8000/blog/index

6. 使用supervisor管理

6.1. 守护uwsgi

1、在/etc/supervisor中新建djsite.conf文件:

1
2
3
4
5
6
7
[program:djsite]
command=/root/.pyenv/versions/3.6.1/bin/uwsgi --http :8000 --chdir /home/web/djsite/ --module django_wsgi --static-map=/static=static
directory=/home/web/djsite/
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true

2、重启supervisor

1
2
3
ps aux | grep supervisord
systemctl stop supervisord
systemctl start supervisord

附:重启djsite命令

1
supervisorctl -c /etc/supervisord.conf restart djsite

3、测试访问
http://ip:8000/blog/index
页面显示正常,至此守护进程配置成功。

4、djsite.conf可以精简修改为:

1
2
3
4
5
6
7
[program:djsite]
command=/root/.pyenv/versions/3.6.1/bin/uwsgi --ini uwsgi.ini
directory=/home/web/djsite/
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true

6.2. 静态资源问题(可忽略)

假设,uwsgi.ini为:

1
2
3
4
[uwsgi]
http = :8000
chdir = /home/web/djsite/
wsgi-file = django_wsgi.py

静态资源就无法访问了。在不添加static-map的情况下,需要修改两个文件:
(1)修改djsite/djsite/settings.py文件,添加:

1
STATIC_ROOT = '/home/web/djsite/static/'

(2)修改djsite/djsite/settings.py文件为:

1
2
3
4
5
6
7
8
9
from django.conf.urls import url,include
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/', include('blog.urls', namespace='blog')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

6.3. admin静态资源问题

如果以python manage.py runserver启动django,那么静态资源没有问题。

如果以uwsgi启动django,静态资源看起来没有问题,但是,如果访问 http://ip:8000/admin ,就会发现这个页面的静态资源无法获取。

一个Django应用,一般有两类静态文件。一是应用内的静态文件,二是Django自带的静态文件。应用内的静态文件在djsite/static目录下。此外,在INSTALLED_APPS中配置了django.contrib.admin, 则还会有另外一组静态文件,在Django安装位置里。

例如,一个root在Python 3.6版本安装的Django,admin的静态文件在: /usr/local/lib/python3.6/site-packages/django/contrib/admin/static/admin/。

最终,在STATIC_URL里,会有两类静态文件, /static/*/static/admin/*

了解原理,原因就很显然了。python manage.py runserver知道静态文件的位置,而uWSGI不知道静态文件在什么位置。

解决办法如下:
(1)修改djsite/djsite/settings.py文件:

1
2
3
SITE_ROOT = os.path.dirname(os.path.abspath(__file__))
SITE_ROOT = os.path.abspath(os.path.join(SITE_ROOT, '../'))
STATIC_ROOT = os.path.join(SITE_ROOT, 'collectedstatic')

(2)收集所有静态文件到collectedstatic目录
python manage.py collectstatic

(3)修改uwsgi.ini配置

1
2
3
4
5
[uwsgi]
http = :8000
chdir = /home/web/djsite/
wsgi-file = django_wsgi.py
static-map = /static=collectedstatic

7. nginx+uwsgi

以上,我们的djsite项目已经通过uwsgi方式启动起来,并且可以保持后台运行。nginx配置不改变的情况下,我们可以正常访问 http://django.voidking.com/blog/index 。此时,nginx作为反向代理,和uwsgi间通过http交互。

接下来,就配置下nginx和uwsgi通过socket结合的方式。原理:用户发送http请求到nginx,nginx通过socket把请求交给uwsgi,uwsgi拿到django的处理结果,通过socket返还给nginx,nginx通过http返回结果给用户。

1、因为nginx和uwsgi通过socket方式交互,我们需要修改uwsgi.ini的配置为:

1
2
3
4
5
6
7
8
9
[uwsgi]
socket = :8000
chdir = /home/web/djsite/
wsgi-file = django_wsgi.py
static-map = /static=collectedstatic
master = true
processes = 2
enable-threads = true
daemonize = /home/web/djsite/uwsgi.log

2、重启supervisor
systemctl stop supervisord
systemctl start supervisord

3、修改nginx配置djsite.voidking.com.conf:

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name djsite.voidking.com;
charset utf-8;

location / {
uwsgi_pass 127.0.0.1:8000;
include uwsgi_params;
}
}

5、重启nginx
./nginx -s reload

6、测试访问
此时,访问 http://ip:8000/blog/index 失败,访问 http://django.voidking.com/blog/index 正常。因为8000端口不再提供http服务,而是一个和nginx连接的socket。

8. 加速静态资源

1、修改nginx配置djsite.voidking.com.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name djsite.voidking.com;
charset utf-8;

location / {
uwsgi_pass 127.0.0.1:8000;
include uwsgi_params;
}

location /static {
alias /root/djsite/collectedstatic;
}
}

2、修改nginx.conf

1
user root;

3、重启nginx
./nginx -s reload

9. 小结

至此,django部署完毕,我们实现了三种部署方法:

  • nginx + django(http方式)
  • nginx + uwsgi(http方式)
  • nginx + uwsgi(socket方式)

10. 书签

使用uWSGI提供静态文件 (更新至1.9)

解决uWSGI里的Django静态文件丢失