Django部署到线上(修改版)

文章目录
  1. 1. 前言
  2. 2. 环境准备
    1. 2.1. supervisor
    2. 2.2. python虚拟机
    3. 2.3. 安装python3.6
  3. 3. 项目部署
    1. 3.1. 代码准备
    2. 3.2. 数据库准备
    3. 3.3. 启动项目
  4. 4. nginx配置
  5. 5. uwsgi
    1. 5.1. 安装uwsgi
    2. 5.2. 一般启动
    3. 5.3. 高级启动
  6. 6. supervisor
    1. 6.1. 配置supervisor
    2. 6.2. 守护uwsgi
    3. 6.3. 静态资源问题(可忽略)
    4. 6.4. admin静态资源问题
  7. 7. nginx+uwsgi
  8. 8. 加速静态资源
  9. 9. 小结
  10. 10. 书签

前言

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

环境准备

supervisor

1、安装

1
2
3
yum install python-pip
yum install supervisor
pip install supervisor

2、创建sock

1
2
touch /tmp/supervisor.sock
chmod 777 /tmp/supervisor.sock

python虚拟机

1、安装pyenv套装
curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
内容除了包含 pyenv 以外,还包含如下插件:

  • pyenv-doctor
  • pyenv-installer
  • pyenv-update
  • pyenv-virtualenv
  • pyenv-which-ext

2、路径添加
vim ~/.bash_profile,添加:

1
2
3
export PATH="/root/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

3、使配置立即生效
source ~/.bash_profile

4、查看安装情况
pyenv -v

5、常用命令

  • 查看可安装的python版本列表:pyenv install -l
  • 安装指定版本的python:pyenv install 3.6.1
  • 查看已安装的python:pyenv versions
  • 查看当前设为默认的python版本:pyenv version

安装python3.6

1、配置pyenv下载源为本地目录(可选操作,不做的话下载速度会很慢)

1
2
3
4
5
6
7
8
9
10
11
12
mkdir /root/python/ && cd /root/python/

# 设置变量
export PYTHON_BUILD_CACHE_PATH=/root/python

# 设置变量
export PYTHON_BUILD_MIRROR_URL=/root/python

# 查看变量设置
env | grep PYTHON_BUILD_MIRROR_URL

wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz

2、安装python3.6.1,pyenv install 3.6.1
报错,ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib? 需要安装依赖包:

1
2
3
4
yum install readline readline-devel readline-static -y
yum install openssl openssl-devel openssl-static -y
yum install sqlite-devel -y
yum install bzip2-devel bzip2-libs -y

3、改变全局版本
pyenv global 3.6.1python -V

附:改变回原版本
pyenv global systempython -V

4、刷新数据库
python rehash

项目部署

代码准备

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

2、安装django
pip install django==1.11.7

3、安装pymysql
pip install pymysql

数据库准备

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

启动项目

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

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又能干什么呢,我们继续研究。

uwsgi

安装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 。

一般启动

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
此时,页面样式就正常了。

高级启动

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

supervisor

配置supervisor

1、开机启动
systemctl enable supervisord

2、生成配置文件

1
2
mkdir -p /etc/supervisor/
echo_supervisord_conf > /etc/supervisord.conf

3、修改配置文件
vim /etc/supervisord.conf,添加:

1
2
[include]
files = /etc/supervisor/*.conf

4、运行
supervisord -c /etc/supervisord.conf

守护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

静态资源问题(可忽略)

假设,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)

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

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。

加速静态资源

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

小结

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

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

书签

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

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