从零开始在 Ubuntu 下部署 Nginx__uWSGI__Django 服务器

<br />
个人技术博客地址:http://songmingyao.com/


<br />

环境:Ubuntu 16.04

1 准备工作

2 安装并配置虚拟环境(本机)

2.1 更新软件源

sudo apt-get update
sudo apt-get upgrade
  • update是更新软件列表
  • upgrade是对比本地软件版本和线上最新软件版本,然后升级

2.2 安装虚拟环境

sudo pip2 install virtualenv
  • virtualenv是虚拟环境安装包,创建虚拟环境可以更好地控制包的版本,包的版本不会因为2.1中的升级操作而升级,保证了项目的稳定性
  • 不同虚拟环境之间的运行环境相互独立,互不干扰
sudo pip2 install virtualenvwrapper
  • virtualenvwrappervirtualenv的扩展管理包,可以将所有的虚拟环境整合在一个目录下
  • 使用前需要先进行以下配置
  1. 创建虚拟环境管理目录
mkdir ~/.virtualenvs
  1. 打开.bashrc
sudo vi ~/.bashrc 
  1. .bashrc的末尾增加以下内容
export WORKON_HOME=$HOME/.virtualenvs  # 所有虚拟环境存储的目录
source /usr/local/bin/virtualenvwrapper.sh
  1. 启用配置文件
source ~/.bashrc

2.3 创建虚拟环境

mkvirtualenv django_blog
  • 创建虚拟环境需要联网
  • 创建完虚拟环境之后会自动进入虚拟环境,可以通过命令行前缀(下图红框)判断是否在虚拟环境内


  • 虚拟环境常用命令
# 创建虚拟环境
mkvirtualenv <name>

# 列出所有虚拟环境
workon TAB*2

# 进入虚拟环境
workon <name>

# 退出虚拟环境
deactivate

# 删除虚拟环境
rmvirtualenv <name>

2.4 安装django包

pip install django==1.8.2
  • 包后面加==用来选择包的版本

3 创建一个django演示项目(本机)

3.1 创建项目

django-admin startproject project_test
  • 项目建立在home目录或其子目录,以免权限问题带来的不便

3.2 创建应用

  • 进入项目目录并查看项目结构
cd project_test/
tree
  • 项目目前结构如下


  1. 创建应用
python manage.py startapp app_test
  • 创建应用后项目结构如下


3.3 修改项目配置

3.3.1 修改环境变量

  • 打开IDE(此处使用的是Pycharm)
  • 选择File/Settings,进入Project Interpreter,选择虚拟环境内的python版本
  • 如果选项内没有,就点击右侧的齿轮,选择Add Local,
    选择所在虚拟环境下的python版本,如/home/python/.virtualenvs/django_blog/bin/python2.7

3.3.2 创建模板文件夹、静态文件文件夹和应用urls

  • 在项目根目录分别创建statictemplates文件夹
  • static文件夹下创建jscssimg三个文件夹,以后用来存放静态文件
  • templates文件夹下创建app_test(应用名)文件夹,以后用来存放模板文件
  • 在应用文件夹下创建urls.py文件,以后用来存放应用的urls映射表
  • 创建完成之后的目录结构如下:


3.3.3 修改settings

  • 打开/project_test下的settings.py
  • 添加应用__在INSTALLED_APPS中将我们刚创建的应用加到最后面
  • 修改模板路径__在TEMPLATES里的DIRS修改为'DIRS': [BASE_DIR, 'templates'],
  • 修改静态文件路径__在最后添加
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

3.4 创建页面

3.4.1 修改项目urls

  • 打开/project_test下的urls.py,在urlpatterns内添加一行,意思是只要不是匹配到admin,都转到app_test应用
url(r'^', include('app_test.urls')),
  • 打开/app_test下的urls.py,添加以下内容:
#coding=utf-8
from django.conf.urls import  url
from . import views  # 从当前文件夹内引入views

urlpatterns = [
    url(r'^$', views.index),  # 匹配到根目录,就执行views文件内的index函数
]
  • 打开/project_test下的views.py,添加刚才urls.py内提到的index函数
#coding=utf-8
from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, 'app_test/index.html')
    # 对请求值不做任何处理,直接跳转到模板目录下app_test文件夹下的index.html页面
  • 将一张图片放在/static/img文件夹内
  • templates/app_test文件夹下,创建模板文件index.html,内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
    <h1>下面有一张图片</h1>
    ![](/static/img/test.jpg)  // 寻找static(settings里面的STATIC_URL)文件夹下img文件夹里的test.jpg图片
</body>
</html>

3.5 打开页面

  • 在项目根目录文件夹下,在终端内(确保已进入虚拟环境)
python manage.py runserver
  • 终端显示如下(红色字体暂不用管,因为我们并没有创建models):


  • 打开红框内显示的IP地址(127.0.0.1:8000)
  • 浏览器成功显示创建的页面


4 将项目上传至服务器(本机 & 服务器)

4.1 导出虚拟环境内的包(本机)

pip freeze > plist.txt
  • 此操作将虚拟环境内所有的包都保存在了list.txt里面

4.2 将项目文件夹整体上传至服务器

  • 传输文件可以用samba,ftp,scp等等,此处使用的是scp
scp -r <YOUR_LOCAL_PROJECT_DIR> <SERVER_USERNAME>@<SERVER_IP>:<YOUR_SERVER_PROJECT_DIR>

4.3 在服务器上安装虚拟环境(服务器)

  • 在服务器上重复2.1~2.3的步骤,安装虚拟环境
  • 进入虚拟环境,进入项目目录,根据本地计算机提供的包列表安装所需要的包
pip install -r plist.txt

5 安装uWSGI(服务器)

  • 安装Python开发版本(因为安装uWSGI过程中需要编译)
sudo apt-get install python-dev
  • 安装gcc(因为安装uWSGI过程中需要C编译器)
sudo apt-get install gcc
  • 安装uWSGI
pip install uwsgi
  • 使用uwsgi --version命令查看版本号,确认已正确安装

6 配置Django(服务器)

  • 配置项目settings,修改以下一项
ALLOWED_HOSTS = ['*', ]
  • 在项目根目录文件夹下,在终端内(确保已进入虚拟环境)
python manage.py runserver 0:8000
  • 在本地计算机浏览器中输入以下地址以测试Django在服务器上是否正常运行
<YOUR SERVER IP>:8000

2017.06.08更新

  • 如果不能正常显示页面,一般为以下两个原因:

1.请检查防火墙状态,保证8000端口是能够被访问的,代码如下( 更多防火墙设置可以参考我这篇文章http://t.cn/RSuX8Qj

# 检查防火墙状态
sudo ufw status

# 可以临时关闭防火墙
sudo ufw disable

# 或者保持防火墙开启,允许8000端口连接
sudo ufw allow 8000

2.请检查服务器安全组规则,如阿里云服务器,可以在进入管理控制台后,按以下步骤设置( 如要了解更多服务器安全组规则设置,请参见阿里云官方文档http://t.cn/RST7Sgz

3.重启服务,再次在本地计算机浏览器中查看

  • 确定服务器正常后,打开settings,修改以下一项
DEBUG = False

7 配置uWSGI(服务器)

7.1 打通uWSGI和Python

  • 在项目根目录创建test.py文件,内容如下
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return ["Hello World"]  # python2
    # return [b"Hello World"]  # python3
  • 运行uWSGI(表示使用http协议,并使用8000端口,加载指定文件test.py)
uwsgi --http :8000 --wsgi-file test.py
  • 打开浏览器,输入
127.0.0.1:8000
  • 若显示'Hello World'则表示运行正常,说明以下三个环节是相通的
web client <-> uWSGI <-> Python

7.2 打通uWSGI和Django

  • 在项目根目录创建文件my_uwsgi.ini,并写入以下内容
[uwsgi]
# 使用nginx连接时使用
# socket = 0:8001

# 直接做web服务器使用
http = 0:8080

# 项目目录
chdir = /home/python/Desktop/project_test

# 项目中wsgi.py文件的目录
wsgi-file = /home/python/Desktop/project_test/project_test/wsgi.py

# 主进程
master = true

# 多进程&多线程
processes = 6
threads = 2

# .sock文件目录需与Nginx文件内的配置相同
# socket = /home/python/Desktop/project_test/my_sock.sock
# chmod-socket = 666

# 以守护进程的方式启动
vacuum = true


# 存储pid进程
pidfile=uwsgi.pid

# 存储log日志
daemonize=uwsgi.log
  • 启动uWSGI服务
uwsgi --ini my_uwsgi.ini
  • 终端显示以下内容即代表开启成功
[uWSGI] getting INI configuration from my_uwsgi.ini
  • 打开浏览器,地址栏输入以下地址
<YOUR_SERVER_IP>:8080
  • 可以看到,文字正常显示,图片无法显示,这是正常现象


  • 以上步骤说明以下三个环节是相通的

web client <-> uWSGI <-> Django
  • 停止uWSGI服务
uwsgi --stop uwsgi.pid

8 配置Nginx(服务器)

8.1 安装Nginx

  • 安装Nginx
sudo apt-get install nginx
  • Nginx安装成功后,系统会自动开启 Nginx 服务,默认使用80端口,打开浏览器并输入你服务器的IP地址,就可以看到 nginx 的测试页面
Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.

Thank you for using nginx.
  • 说明以下两个环节是相通的
web client <-> the web server(Nginx)

8.2 配置Nginx

  • /etc/nginx/目录下的uwsgi_params复制到项目文件夹,对此文件不做任何改动
cp /etc/nginx/uwsgi_params .
  • 在项目根目录创建文件my_nginx.conf,并写入以下内容
upstream django {
    server    127.0.0.1:8001;
    # server      unix://home/python/Desktop/project_test/my_sock.sock;
}

server {
    listen      8000;  # 端口号
    server_name 127.0.0.1;  # 服务器 ip 或是域名
    charset     utf-8;  # 字符集

    # 最大上传限制
    # client_max_body_size 75M;

    location /media  {
        alias /home/python/Desktop/project_test/media_common;  # 媒体文件所在文件夹
    }

    location /static {
        alias /home/python/Desktop/project_test/static_common;  # 静态文件所在文件夹
    }


    # 将所有非媒体请求转到Django服务器上
    location / {
        uwsgi_pass      django;  # 最上方已定义
        # 将所有参数都转到uwsgi下
        include         /home/python/Desktop/project_test/uwsgi_params; # uwsgi_params的路径
    }
}

  • 这个配置文件表示将静态文件和媒体文件由Nginx处理,而其它的请求转入uWSGI处理

  • 与Nginx配置目录建立软链接

sudo ln -s /home/python/Desktop/project_test/my_nginx.conf /etc/nginx/sites-enabled/
  • 创建静态文件与媒体文件存放目录
sudo mkdir static_common
sudo mkdir media_common
  • 修改项目settings,在最后面添加
STATIC_ROOT = os.path.join(BASE_DIR, 'static_common')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media_common')
  • 进入项目根目录,执行静态文件迁移命令
python manage.py collectstatic
  • 提示输入选项时选yes即可

  • 重启Nginx服务

sudo /etc/init.d/nginx restart

9 Nginx & uWSGI & Django(服务器)

9.1 测试Nginx

  • 在浏览器内输入<YOUR_SERVER_IP>:8000/static/admin/css/base.css,检查是否能正常显示这个css文件

  • 将一张测试图片test.jpg放入media_common文件夹中,在浏览器中输入<YOUR_SERVER_IP>:8000/media/test.jpg,如果出现403则将图片的权限改为666,成功显示图片

9.2 测试uWSGI

  • 回到项目根目录,输入以下命令
uwsgi --socket :8001 --wsgi-file test.py
  • 打开浏览器,地址栏输入<YOUR_SERVBER_IP>,看是否能正常显示'Hello World'

9.3 用UNIX socket取代TCP port

  • 修改my_nginx.conf最终版如下:
upstream django {
    # server    127.0.0.1:8001;
    server      unix:///home/python/Desktop/project_test/my_sock.sock;
}

server {
    listen      8000;  # 端口号
    server_name songmingyao.com;  # 服务器 ip 或是域名
    charset     utf-8;  # 字符集

    # 最大上传限制
    # client_max_body_size 75M;

    location /media  {
        alias /home/python/Desktop/project_test/media_common;  # 媒体文件所在文件夹
    }

    location /static {
        alias /home/python/Desktop/project_test/static_common;  # 静态文件所在文件夹
    }


    # 将所有非媒体请求转到Django服务器上
    location / {
        uwsgi_pass      django;  # 最上方已定义
        # 将所有参数都转到uwsgi下
        include         /home/python/Desktop/project_test/uwsgi_params; # uwsgi_params的路径
    }
}
  • 修改my_uwsgi.ini最终版如下
[uwsgi]
# 使用nginx连接时使用
# socket = 0:8001

# 直接做web服务器使用
# http = 0:8080

# 项目目录
chdir = /home/python/Desktop/project_test

# 项目中wsgi.py文件的目录
wsgi-file = /home/python/Desktop/project_test/project_test/wsgi.py

# 主进程
master = true

# 多进程&多线程
processes = 6
threads = 2

# .sock文件目录需与Nginx文件内的配置相同
socket = /home/python/Desktop/project_test/my_sock.sock
chmod-socket = 666

# 以守护进程的方式启动
vacuum = true

# 存储pid进程
pidfile=uwsgi.pid

# 存储log日志
daemonize=uwsgi.log
  • 重启Nginx和uWSGI
sudo /etc/init.d/nginx restart

uwsgi --stop uwsgi.pid
uwsgi --ini my_uwsgi.ini
  • 打开浏览器,地址栏输入网址<YOUR_SERVER_IP>:8000,查看图片和文字是否显示正常

  • 此时以下环节已全部打通

web client <-> web server(nginx) <-> the socket <-> uwsgi <-> Django

9.4 服务器开机自启

  • 修改/etc/rc.local,添加以下内容到exit 0之前
/usr/local/bin/uwsgi --ini /home/python/Desktop/project_test/my_uwsgi.ini

<br />


个人技术博客地址:http://songmingyao.com/
<br />

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

推荐阅读更多精彩内容