ubuntu django+uwsgi+nginx部署与持续集成.

之前的文章中将uwsgi, nginx mysql 等全部安装完毕.
本篇内容最终达到的效果是提交代码到某分支, 远程服务器自动更新.
在将django项目正式部署到测试服务器上之前需要做一点点修改.

不同的环境应用不同的配置.

由于脚本的特点, 从上往下执行, 以下几行简单代码可以根据不同的环境导入不同的配置文件.

import sys

SERVER_ENVIRONMENT = None

if os.path.exists(os.path.join(BASE_DIR, "setting-environment-local")):
    SERVER_ENVIRONMENT = 'local'
    from .settings_local import *
if os.path.exists(os.path.join(BASE_DIR, "setting-environment-develop")):
    SERVER_ENVIRONMENT = 'develop'
    from .settings_dev import *

if SERVER_ENVIRONMENT == None:

    # SERVER_ENVIRONMENT = 'develop'
    # from .settings_dev import *
    raise RuntimeError("没有找到 环境标记文件")
    # sys.exit()

上面的代码 根据项目路径来判断当前环境.
有两个环境标记文件.
setting-environment-local 本机环境
setting-environment-develop 测试服务器

环境标记文件使用vim 创建即可, 对os.path.exists(os.path.join(BASE_DIR, "setting-environment-local")这行代码来说, 文件和路径是一样的效果.

记得环境标记文件需要使用.gitignore忽略版本管理. !!!!!!!!!!!!!

上面的代码中有.setting_local.setting_dev 两个文件, 这个我们手动创建的配置文件, 两个文件内容分别为本地环境的配置和测试环境的配置, 主要不同点在于数据库配置.

setting0.png

settingdev 与settinglocal两个文件的内容除了 "user" "password"不同, 其余基本相同.

创建依赖列表.

cd 到项目的manage.py 同一目录下
# 切换工作环境
workon python35
pip freeze >requirements.txt

此时项目中多出requirements.txt文件.
内容为各个依赖库与版本. 例如

certifi==2017.7.27.1
chardet==3.0.4
coreapi==2.3.3
coreschema==0.0.4
Django==1.11.6
django-rest-swagger==2.1.2
django-simple-serializer==2.0.7
djangorestframework==3.7.1
future==0.16.0
idna==2.6
itypes==1.1.0
Jinja2==2.9.6
MarkupSafe==1.0
olefile==0.44
openapi-codec==1.3.2
Pillow==4.3.0
PyMySQL==0.7.11
pytz==2017.2
requests==2.18.4
simplejson==3.11.1
uritemplate==3.0.0
urllib3==1.22

将静态文件单独放入一个目录下方便nginx管理

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'common_static')
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "common_static"),
)

urls.py 文件

from django.conf.urls import url, include
from django.contrib import admin
from rest_framework_swagger.views import get_swagger_view
from rest_framework.routers import DefaultRouter
from rest_framework.documentation import include_docs_urls
from rest_framework.schemas import get_schema_view
from django.contrib.auth.models import User
from ifacerecognition.views import home, uploadImage
from ifacerecognition import views as ifacerecognitionViews
from django.conf.urls.static import static
from django.conf import settings
from ifacerecognition.developer import urls as DeveloperUrls
from django.views.static import serve
# from facerecognition.settings import STATIC_ROOT as SettingStaticRoot

urlpatterns = [
    # 为pad android 开发板等提供的接口
    url(r'^api/', include('ifacerecognition.urls')),
    # 接口文档
    url(r'^docs/', ifacerecognitionViews.SwaggerSchemaView.as_view(), name='apiDocs'),
    # django
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^admin/', admin.site.urls),
    # html 页面
    url(r'^pages/uploadImage$', uploadImage),
    # url(r'^developer/', include(DeveloperUrls)),
    url(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
    url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
    url(r'^$', home),

]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

执行以下命令

workon python35
python manage.py collectstatic

此时发现common_static目录下有很多文件. 这个目录下的文件使用nginx管理.

远程服务器拉取代码

cd 到一个合适的目录 例如创建一个目录叫做webapps
cd webapps

git clone "项目地址"

cd 到manage.py 文件所在目录下
# 创建环境标记文件,  :wq 不写内容或者写入任意内容
vim setting-environment-develop

切换分支. 例如切换到develop分支, 以后只要向develop分支提交代码就会更新测试服务器. 向master分支提交代码可以配置为更新正式服务器.

编写uwsgi 配置文件

vim mysite.ini

mysite.ini文件是此项目的uwsgi 配置. 举个配置的例子.

[uwsgi]
project = xxx
chdir = /data/apps/xxx_server/xxx
module = xxx.wsgi
home = /root/.virtualenvs/xxx
socket = /uwsgi_sock/xxx.sock
chmod-socket = 664
master = true
processes = 7
vacuum = true
daemonize = /data/logs/uwsgi_xxx.log
py-autoreload = 1
log-maxsize = 50000000
pidfile = /uwsgi_sock/xxx.pid
touch-reload = /uwsgi_sock/xxx-reload
disable-logging = true
[uwsgi]
# 项目名称
project = xxx 
# 项目路径
chdir = /data/apps/xxx_server/xxx  
# wsgi文件名
module = xxx.wsgi
# python环境目录
home = /root/.virtualenvs/xxx
# 监听端口(文件)
socket = /uwsgi_sock/xxx.sock
# 分配权限.
chmod-socket = 664
#
master = true
# 开多少工作进程, (视服务器配置和项目需求而定.)
processes = 7
#
vacuum = true
# 日志文件路径
daemonize = /data/logs/uwsgi_xxx.log
# 是否自动重启服务器, 例如项目某文件有变换直接重启服务器
py-autoreload = 1
# 日志文件大小
log-maxsize = 50000000
# 配置端口, 向.pid文件发命令控制服务器停止, 重启等等.
pidfile = /uwsgi_sock/xxx.pid
# touch reload文件, 意思就是 touch xxx-reload 文件, 项目立即重启
touch-reload = /uwsgi_sock/xxx-reload
#
disable-logging = true

各种路径应该提前创建. 例如上面的uwsgi_sock路径等等.
应用此配置.

uwsgi --ini /data/apps/xxx_server/xxx/mysite.ini

此命令执行一次即可.

上面的配置例子. 使用了virtualenv创建的python环境./root/.virtualenvs/xxx
监听/uwsgi_sock/xxx.sock文件(和监听端口一个意思, 还可以监听8000之类的端口).

nginx配置

cd /etc/nginx/conf.d
# 再次目录下创建项目配置文件
vim xxx.conf

文件内容

server{
        listen       80 ;
        access_log /var/log/nginx/access.log;
        error_log  /var/log/nginx/error.log;
          
        location / {
          include         uwsgi_params;
          uwsgi_pass      unix:/uwsgi_sock/xxx.sock;
        }

        location /static {
            alias /data/apps/xxx_server/xxx/common_static;
        }
        
        location /media {
            alias /data/apps/xxx_server/xxx/media;
        }
    
}  

上面的配置表示nginx监听80端口, 将80端口收到的一切信息发送到/uwsgi_sock/xxx.sock/ 而 uwsgi也监听 /uwsgi_sock/xxx.sock 这样就达到了 nginx向uwsgi 发送消息的目的. 而静态文件使用了nginx管理.

重启nginx 以应用配置.

/etc/init.d/nginx restart

其他命令

sudo /etc/init.d/nginx stop 
sudo /etc/init.d/nginx start

持续集成

持续集成其实就是提交代码之后想办法立即让远程服务器执行一个脚本.
按照这个思路. 需要测试服务器运行一个web项目用来监听 脚本运行请求, 需要对应项目的更新脚本, 需要web项目接口的调用机制.

1.用来运行脚本的项目. 此项目可以直接使用jenkins 也可以自己写一个, 我新建的一个叫做runshell的django项目(增加的代码一共也不到10行的样子)用来跑 更新脚本.
2.如何提交代码的同时触发更新机制. 我这里使用gitlab 创建一个hock即可

webhock.png

当然浏览器直接执行以下也一样, 提交代码之后访问指定url 即执行脚本.

用来运行脚本的简单项目

接口内容如下

def build_face(request):

    status = os.system('sh /data/apps/runShell/buildApp')

    return HttpResponse("success", content_type="application/json", )

简单脚本.

运行buildApp脚本
buildApp内容


workon xxx
cd /data/apps/xxx_server/
git pull
cd /data/apps/xxx_server/xxx
pip install -r requirements.txt
python manage.py makemigrations
python manage.py migrate
touch /uwsgi_sock/xxx-reload

切换python环境
cd到项目目录下
拉取代码
安装依赖库
创建数据库表.
重启服务器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容