Nginx + uWSGI 部署Django站点

Django有Apache和Nginx两种常见部署方式

主要工具:

  • 一台远程服务器
  • Nginx
  • uWSGI
  • Django

知识点:

  • 站点结构
  • Nginx结构
  • debug方式

主机使用的是DigitalOcean家的基础版ubuntu,版本16.01。

从裸机开始的环境准备

基础环境

zsh,oh-my-zsh,vimrc从github上pull过来,一切都是熟悉的感觉。
apt-get 要更新。

Python3/pip 和 虚拟环境

主要是为了环境简洁和适应版本

Nginx 安装

远程服务器这个是第一步的,没有服务器,开发调试都是头疼的事情。Nginx是一款反向代理服务器,可以让网站的内容呈现给客户。

# install
sudo apt-get install nginx

# basic operation
sudo /etc/init.d/nginx start
sudo /etc/init.d/nginx stop
sudo /etc/init.d/nginx restart

or:
sudo service nginx start
sudo service nginx stop
sudo service nginx restart

启动后访问服务器ip,会看到Welcome to nginx!信息。

uWSGI 安装

uWSGI是实现了WSGI的服务器。WSGI一个Web接口。提供规范化协议,提高服务器的工作效率。uWSGI本身已经可以胜任服务器的工作,为什么要再前面挡一个Nginx,这是出于更好的安全性,更有效率的工作和Nginx作为专业的服务器的优势。可以详见这个讨论

#install
apt-get install python-dev
sudo pip install uwsgi --upgrade

用wWSGI挂起一个最简单的程序,创建一个文件命名test.py

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

用wWSGI挂起:

uwsgi --http :8000 --wsgi-file test.py

这条命令是说,使用http协议,8000端口,加载指定文件。文件很简单,收到GET请求后,返回Hello World,在浏览器输入ip:8000就可以看到结果了。

安装Django

#install
pip install django

#create project
django-admin.py startproject project-name

#create app
python manage.py startapp app-name

#同步数据库
python manage.py makemigrations
python manage.py migrate

#开发服务器
python manage.py runserver #localhost
python manage.py runserver 0.0.0.0:8000  #ip:8000端口

理解Nginx服务器的结构

Nginx结构

最重要的文件:一开始就要加载

默认下,Nginx会安装在/usr/local/nginx,所有的配置文件在/etc/nginx下,最主要的配置文件是 /etc/nginx/nginx.conf,这个文件建议放在git上,或者进行周期性备份

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.$(date "+%b_%d_%Y_%H.%M.%S")

nginx.conf 的结构如下:

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
    worker_connections 768;
}

http {
    ......
}

nginx.conf 配置了主要的工作功能,include允许从后面的地址中找到配置文件,这样可以让主配置文件看起来更加精简,但是多层套用include也不推荐,让代码不易读。从默认的配置文件可以看出,/etc/nginx/conf.d/里所有的配置文件和/etc/nginx/sites-enalbed/里的配置文件都会在一开始被加载。log文件在/var/log/nginx/下。

HTTP模块:全局配置

HTTP 模块会处理所有来自于网络的HTTP请求,这是Nginx的大门。
重点说下/etc/nginx/sites-enalbed/这个目录,它可以让不同的虚拟域名分开来。一般都是通过软连接将配置文件连接进这个目录,很容易修改,ngnix提供了一个配置模版:

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com

Server模块:虚拟域名的配置

/etc/nginx/sites-enalbed/下配置的格式:

server {
    listen 80
    root /usr/share/nginx/html;
    
    server_name localhost;
    
    location / {
    
    }
}

server 模块是用户修改量最大的地方。对于每一个虚拟域名都可以有不同的配置文件。/usr/share/nginx/html这个路径现在已经是Nginx默认存放静态文件的路径了,不需要再配置。

listen: 用来监听端口
server_name: 自己网站的域名

是否可以使用不有效的域名呢?
完全可以,在局域网中,是一个很好的办法。

log: log文件,HTTP模块已经设置过,在server模块里可以更细致。

access_log logs/example.access.log;
access_log /srv/www/example.com/logs/access.log;

建议使用完全路径,相对路径是与现在的路径下部分匹配的,不好控制。

location:文件系统配置
location设置可以让服务器去应答一些要服务器资源的请求。例如:

# http://example.com/blog/

location /blog/ { }

注意字符串的匹配是最佳匹配,Nginx会选择匹配的最好的location。更复杂的匹配情况请参照官方文件。

部署一个Nginx的最小Web结构

实践是检验真理的唯一标准,这里部署一个Nginx的最小结构,看看Nginx能不能正常工作。

linux 新建用户名用于部署Nginx并赋予权限.

visudo
# 添加权限:
username    ALL=(ALL) ALL

nginx.conf用户名修改为当前用户。
在当前用户的根目录下创建如下结构:

mysite:
    - mysite.conf
    - www
    - media
        -test.png   
    - log

最简单的目标就是通过ip访问网站里的静态内容。简单的配置下,注意使用绝对路径:

server {
    listen 8000;
    server_name mysite.com
    charset utf_8;

    access_log /home/username/mysite/log/access.log;
    error_log /home/username/mysite/log/error_log;

    location /media/ {
        alias /home/username/mysite/media/;
    }

}

# 命令行软连接到Nginx
sudo ln -s /home/username/mysite/mysite.conf /etc/nginx/sites-enabled/

重启Nginx后,在 http://mysite.com/media/test.png能够看到正常显示内容就说名Nginx正常工作了。log文件显示正常。

常见的错误

403 forbidden

这里就要注意下用户名了,很多时候登录一台主机用户是root,而Nginx用户不是root,所以忽略了用户名的部署多会遇到这个问题。

  1. 可以将Nginx的用户名改为root,这样风险会很大。
  2. 网站静态内容部署在当前用户目录下,如列子所示。
  3. /usr/share/nginx/html下部署静态文件或软连接到网站目录。

404 notfound

一般出现这个问题是目录的配置出现问题,使用绝对路径可解决

调试方法

最好的办法就是log文件了,每次的请求,错误记录都会非常详细。

理解Django部署结构

djangoe结构

每个环节都要理解

到现在为止,已经可以分别用Nginx和uWSGI挂起服务器了。说明这两个部分都是通的:

web-server
web-uWSGI-Python

用uWSGI挂起Django:

uwsgi --http :8000 --module mysite.wsgi

这里sWSGI会找到 mysite下的wsgi的配置文件,即mysite/wsgi.py如果看到Django的“it worked!”信息,则说明Django被成功挂起。

web-uWSGI-Django

通过socket连接Nginx和uWSGI

socket中文翻译为套接字,它的作用就像一个连接器,比方说把两段水管连接起来,每段管子都有自己不同的编号,下面就来试验下套接字的作用。
带socket的Nginx配置多了这个部分:

upstream django {
    # server unit:///path/to/yourmysite/mysite.sock;
    server 127.0.0.1:8022; #for a webport socket
}

这是要说明监听来自8022端口的请求,8022口做什么了呢?

uwsgi --socket :8022 --wsgi-file test.py

8022挂起了最先的python测试文件,如果有GET请求,则返回hello world。Nginx则设置为监听8023端口。通过socket,有检测到8023口的外部请求,则交给8022端口去处理,这就是socket的作用,非常灵活。也说明了这一套结构都通了:

Web-Nginx-Socket-uWSGI-Python

Django sockect

upstream django {
    server unit:///path/to/yourmysite/mysite.sock;
    # server 127.0.0.1:8022; #for a webport socket
}

重启Nginx,挂起uWSGI:

uwsgi --socket mysite.sock --wsgi-file test.py

在当前项目下可以看到生成了空的文件mysite.sock,2023口测试通过。

最后拉起整个Django项目:

uwsgi --socket mysite.sock --module mysite.wsgi

看到Django工作界面,完成,Done!


Web-Nginx-Socket-uWSGI-Python

常见错误

connect() to unix:mysite.sock failed (2: No such file or directory)

基本是路径设置问题,upstrem和socket都要使用绝对路径。

connect() to uunix:mysite.sock failed (13: Permission denied)

添加socket权限:

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)

参考资料:
Django Document django官方最权威的参考文档
Setting up Django and your web server with uWSGI and nginx uWSGI提供的参考文档,有些小问题
How To Serve Django Applications with uWSGI and Nginx on Ubuntu 16.04 DigitalOcean提供的部署指导
How to Configure nginx 如何配置Nginx

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容