Deploy Django with Fabric

作者: shanliangliuxing
发布时间:2015-07-29 11:32:19

转自:http://gibuloto.com/blog/deploy-django-with-fabric/

Deploy Django with Fabric

Install

1
2
# 不要安裝在 virtualenv 裡面,不然每次 fab 都要進去 virtualenv 也是很麻煩
$ sudo pip install fabric

Operations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 在 remote 執行指令
run()

# 在 remote 執行需要 sudo 的指令
sudo()

# 在 localhost 執行指令
local()

# 在 remote 執行 change directory,通常會搭配 with 使用
cd()

# 在 localhost 執行 change directory
lcd()

cd()run()sudo() 只能用在 remote SSH 登入,本機的話要用 lcd()local()local('sudo some_command')

run() 默認的工作目錄就是 SSH 登入進去的家目錄,local(), 則是 fabfile.py 所在的目錄。

References:

Example

我把 deploy 環境分成三種,productionstagingdevelopment,分別對應到一個 fabfile。fabfile 實際上就是一個 .py 檔案,因為 Fabric 說穿了就是用 Python 來寫一串 bash 指令。

目錄結構如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jojogo/
├── app_product/
├── fabfile.py
├── fabfiles/
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── development.py
│   ├── development.pyc
│   ├── production.py
│   ├── production.pyc
│   ├── staging.py
│   └── staging.pyc
├── jojogo/
├── manage.py
├── requirements.txt
├── static/
└── templates/

in fabfile.py

1
2
3
4
5
from fabric.api import *

from fabfiles import production as pro
from fabfiles import staging as sta
from fabfiles import development as dev

Usage:

1
2
3
4
$ fab -l
$ fab pro.uwsgi
$ fab sta.uwsgi
$ fab dev.django

in production.py (remote: Ubuntu)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import os
import sys
from datetime import datetime

from fabric.api import *
from fabric.colors import *


def set_env():
    env.FABFILE_NAME = 'production'
    env.PROJECT_NAME = 'jojogo'
    env.PROJECT_PATH_REMOTE = '/src/jojogo'
    env.PROJECT_PATH_LOCAL = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
    env.SOURCE_VIRTUALENVWRAPPER = 'source /usr/local/bin/virtualenvwrapper.sh'
    env.VIRTUALENV_NAME = env.PROJECT_NAME
    env.VIRTUALENV_WORKON = '%s && workon %s' % (env.SOURCE_VIRTUALENVWRAPPER, env.VIRTUALENV_NAME)

    env.host_string = 'REMOTE SERVER IP'
    env.user = 'REMOTE SERVER SSH LOGIN USERNAME'
    env.key_filename = 'ABSOLUTE PATH OF KEY PAIR FILE'



@task
def checkout():
    '''
    Checkout project from Subversion
    '''

    set_env()

    sudo('apt-get update')
    sudo('apt-get install git mercurial subversion')
    run('svn co --username USERNAME https://SVN_REPO_URL/')


@task
def setup():
    '''
    Install all services & apps
    '''

    def install_postgresql_and_postgis():
        sudo('apt-get install binutils gdal-bin libproj-dev postgresql-9.1-postgis postgresql-server-dev-9.1 python-psycopg2')

    def install_nginx():
        run('wget http://nginx.org/keys/nginx_signing.key')
        sudo('apt-key add nginx_signing.key')
        put('config/etc/apt/sources.list.d/nginx.list', '/etc/apt/sources.list.d/nginx.list', use_sudo=True)
        sudo('apt-get update')
        sudo('apt-get install nginx')

        # 上傳配置文件
        put('config/nginx/nginx.conf', '/etc/nginx.conf', use_sudo=True)
        put('config/nginx/conf.d/guangdj.conf', '/etc/nginx/conf.d/guangdj.conf', use_sudo=True)

        # 刪除範例的配置文件
        sudo('rm /etc/nginx/conf.d/default.conf')
        sudo('rm /etc/nginx/conf.d/example_ssl.conf')

        sudo('service nginx restart')

    def install_pip():
        sudo('curl http://python-distribute.org/distribute_setup.py | python')
        sudo('curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python')

    def install_virtualenvwrapper():
        sudo('pip install virtualenvwrapper')

    def install_pil():
        sudo('apt-get install apt-get build-dep python-imaging')

    def install_uwsgi():
        sudo('apt-get install build-essential python-dev libxml2-dev')

        log_dir = '~/log/uwsgi'

        run('mkdir -p %s' % log_dir)
        run('touch %s/guangdj.log' % log_dir)

    set_env()

    install_postgresql_and_postgis()
    install_nginx()
    install_pip()
    install_virtualenvwrapper()
    install_pil()
    install_uwsgi()

    with prefix(env.SOURCE_VIRTUALENVWRAPPER):
        '''
        必須 source virtualenvwrapper.sh
        否則會出現 /bin/sh: workon: command not found
        '''

        run('mkvirtualenv --no-site-packages %s' % env.VIRTUALENV_NAME)

        with prefix(env.VIRTUALENV_WORKON):
            with cd(env.PROJECT_PATH_REMOTE):
                run('pip install -r requirements.txt')
                run('yolk -l')
                run('mkdir -p static_root')
                run('python manage.py collectstatic --clear --noinput')


@task
def syncdb():
    '''
    Update & migrate Django database
    '''

    set_env()

    with prefix(env.VIRTUALENV_WORKON):
        run('python manage.py syncdb')


@task
def nginx():
    '''
    Reload nginx
    '''

    set_env()

    sudo('service nginx restart')


@task
def celery():
    '''
    Reload Celery
    '''

    set_env()

    with prefix(env.VIRTUALENV_WORKON):
        try:
            sudo("ps auxww | grep 'celery' | awk '{print $2}' | xargs kill -9")
        except:
            print(green('雖然有錯誤訊息,但是 celeryd 還是有被 kill'))

        sudo('python manage.py celeryd_detach')


@task
def uwsgi():
    '''
    Reload uWSGI
    '''

    set_env()

    with prefix(env.VIRTUALENV_WORKON):
        run('svn up')
        run('python manage.py collectstatic --clear --noinput')
        run('killall -9 uwsgi')
        run('uwsgi --ini config/uwsgi_conf.ini')

in development.py (localhost: Mac)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import os
import socket
import sys
from datetime import datetime

from fabric.api import *
from fabric.colors import *


def set_env():
    env.FABFILE_NAME = 'development'
    env.PROJECT_NAME = 'jojogo'
    env.PROJECT_PATH_LOCAL = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
    env.EXPORT_POSTGRESQL_BIN = 'export PATH=/usr/local/Cellar/postgresql/9.1.4/bin:$PATH'
    env.SOURCE_VIRTUALENVWRAPPER = 'source /usr/local/bin/virtualenvwrapper.sh'
    env.VIRTUALENV_WORKON = '%s && workon %s' % (env.SOURCE_VIRTUALENVWRAPPER, env.PROJECT_NAME)
    env.CURRENT_IP = socket.getaddrinfo(socket.gethostname(), None)[0][4][0]


@task
def setup():
    '''
    Install all services & apps
    '''

    def install_postgresql_and_postgis():
        local('brew update')
        local('brew install postgresql')
        local('brew versions postgis')

    def install_virtualenvwrapper():
        local('sudo pip install --upgrade virtualenvwrapper')

    def install_pil():
        local('brew install jpeg lzlib')

    set_env()

    install_postgresql_and_postgis()
    install_virtualenvwrapper()
    install_pil()

    with prefix(env.SOURCE_VIRTUALENVWRAPPER):
        '''
        必須 source virtualenvwrapper.sh
        否則會出現 /bin/sh: workon: command not found
        '''

        local('mkvirtualenv --no-site-packages %s' % env.PROJECT_NAME)

        with prefix(env.VIRTUALENV_WORKON):
            local('pip install -r requirements.txt')
            local('yolk -l')


@task
def postgresql(run_in='backgound'):
    '''
    Run PostgreSQL
    '''

    set_env()

    with prefix(env.EXPORT_POSTGRESQL_BIN):
        if run_in == 'backgound':
            local('pg_ctl -D ~/Developer/postgresql/%s -l /tmp/postgresql.%s.log start' % (env.PROJECT_NAME, env.PROJECT_NAME))
        else:
            local('pg_ctl -D ~/Developer/postgresql/%s start' % (env.PROJECT_NAME))


@task
def celery(run_in='backgound'):
    '''
    Run Celery
    '''

    set_env()

    with prefix(env.VIRTUALENV_WORKON):
        if run_in == 'backgound':
            try:
                local('python manage.py celeryd_detach')
            except:
                print(green('celery 已經在執行了'))
        else:
            local('python manage.py celery worker --loglevel=info')


@task
def django():
    '''
    Run Django
    '''

    set_env()

    with prefix(env.VIRTUALENV_WORKON):
        local('python manage.py runserver %s:8000' % env.CURRENT_IP)


@task
def run_all():
    '''
    Run all services in backgound
    '''

    set_env()

    with prefix(env.VIRTUALENV_WORKON):
        postgresql()
        celery()
        django()





标签: Django Go
来源:http://blog.csdn.net/shanliangliuxing/article/details/881164

推荐: