『入る学科間違えた高専生』の日記

プログラミングのコードを書いたりする予定です。あとは日記等。あといつまで高専生やねん

Fabricを使ったDjangoアプリのDeployをやってみた

追記 (2019-01-06 02:48)

こちらの記事は古いので fabric==2.4.0 を使う場合は以下を参照ください。

nnsnodnb.hatenablog.jp

はじめに

今まで、Djangoアプリをサーバにデプロイする時に毎回毎回、 ssh して cd して git pull して migrate して gunicorn を再起動させて、とかやってたんですが、
さすがに面倒になりました!

知り合いから Fabricはいいぞ と進められてあんまり乗り気じゃなかったので、相当すっぽかしていましたが、ようやく暇(暇じゃない)になったのでやってみたのでそれのサンプル的なソレ
簡単なことしかやってないので、難しいことは以下の公式ドキュメントを見るといいかもです。

Welcome to Fabric! — Fabric documentation

前提条件・環境情報

Django2.0.xアプリをFabricを使用してサーバにデプロイします。

厳密に言ったらまだ前提条件とか環境情報足りないかもだけど、足りなかったら今度修正します。

ローカル側のPythonバージョンが 2.7.14 なのは、公式 fabric2.5-2.7 のサポートになってるからです!!
Forkリポジトリfabric3 というものがあるらしいのですが、こちらは今回試してません。

公式 (Python2系のみ)

github.com

Fork (Python3系対応済み)

github.com

準備

今回は、セキュリティ的にもRSAでのSSH接続を行っています。
ローカルに ~/.ssh/config があって、それを fabric でも指定して使えるとのことなので、記入しておきます。

Host server
    Hostname example.com
    User username
    Port 22
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_rsa

大体こんな感じにしておきました。

Python2.7.x 環境下で、 fabric をインストール

$ pip install fabric

fabfile.py にやりたいことを書く

from fabric.api import cd, env, run
import os.path

env.hosts = ['server']  # ~/.ssh/config で設定した、Hostをここに記入
env.ssh_config_path = '~/.ssh/config'
env.use_ssh_config = True

def deploy():
    BASE_DIR = '/path/to/django_application_server'
    PIP = os.path.join(BASE_DIR, '/path/to/pip')
    PYTHON = os.path.join(BASE_DIR, '/path/to/python')
    GUNICORN = os.path.join(BASE_DIR, '/path/to/gunicorn')

    with cd(BASE_DIR):
        run('git pull origin master')

        run('{} install -U pip'.format(PIP))
        run('{} install -r requirements.txt'.format(PIP))

        run('{} -V'.format(PYTHON))
        run('{} manage.py migrate'.format(PYTHON))

        run('cp {} {}'.format(os.path.join(BASE_DIR, 'deploy', 'settings.py'),
                              os.path.join(BASE_DIR, 'django_application_server', 'settings.py')))  # DEBUGやDATABASEの設定を変更しておきたいので予め変更しておいたファイルを deploy ディレクトリにおいておきました。

        run('kill `cat gunicorn.pid`')
        run('{} django_application_server.wsgi:application -c gunicorn_conf.py'.format(GUNICORN))

上記中にも、ちょっとコメントでも書いてるんですが、 deploy というディレクトリを用意してその中に本番環境用の settings.py を置いておきました。

このままだと gunicorn_conf.py が見つからないというようなエラーで怒られると思うので、適当に書いておいてください!

import os.path

bind = 'unix://gunicorn.sock'
daemon = True
pidfile = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gunicorn.pid')
reload = True

みたいな。

デプロイする

今回は、 deploy という関数を作ったので、 fab コマンドの引数に deploy を使用できるようになりました!
ということで以下のようにすると行ける。

$ fab deploy

いけたよね!エラー吐かれたら何かしらのでミスがあるので頑張って修正!!

終わったら一応Slackに流したい

今回は、簡単にパパっとやってしまいたいので、 slackweb を使用した。

$ pip install slackweb

Slack側のIntegrationは Incoming WebHooks を使用しました。

api.slack.com

上で作った、 fabfile.pyrun('{} django_application_server.wsgi:application -c gunicorn_conf.py'.format(GUNICORN)) の下に同じインデントレベルで以下のように

もちろん、 import slackweb は書いてね。

Webhook URL が作られるのでそれを WEBHOOK_SECURE_URL に置き換えてサンプル置きます。

slack = slackweb.Slack(url='WEBHOOK_SECURE_URL')
slack.notify(text='デプロイ成功したよー!!', link_name=True, username='Fabric')

みたいな感じで2行書いたら送信されているはずです。

あとは、Jenkinsとかでテストしたあとに自動デプロイとか各自で設定する感じで。

最後に

今まで、なんで使わなかったのかわからないぐらい簡単にできてびっくりしましたね。
これだけ簡単に操作ができるなら今後もたくさん使っていきたいです!(なんだこれ、