fabricでデプロイ自動化
独学マンなので、書き方等ご指摘頂けますと幸いです。
背景
- python3.6で書かれたjobを、ec2上に構築
- shceduleでスケジューリング
- supervisorでdaemon化
までできていた。デプロイ作業を失敗しそうなので、自動化した時の備忘録。自動デプロイツールとしてfabricを利用。
ちなみに現状、fabric本家はpython3系をサポートいません。参考: FabricのPython3への対応についてそのためforkされたprojectから、インストールする必要があります。
pip3 install fabric3
ディレクトリ構成はこんな感じ。シンプル。
... ├── fabfile │ ├── __init__.py # module読み込み │ ├── deploy.py # 基本処理の記述 │ ├── envs.py # 基本設定を記述 ...
基本処理の記述
from fabric.api import run, abort, env, cd, local from fabric.decorators import task class LocalHandler(object): """localでのデプロイ周りの処理""" def push(self): """localの変更をgithubへpushする commitまではされている想定 """ self.__check_has_commited() self.__check_on_master() self.__update_requirements() local('git push origin master') def __update_requirements(self): """requirements.txtをupdateするスクリプト""" req_txt = 'requirements.txt' local('pip freeze > {}'.format(req_txt)) res = local('git ls-files -m', capture=True) if res == req_txt: local('git add {}'.format(req_txt)) local('git commit -m "update requirements.txt"') def __check_has_commited(self): """変更がちゃんとcommitされているかを確認""" res = local('git ls-files -m', capture=True) if res: abort('there are some diff on git supervised files') def __check_on_master(self): """master branchにいるか確認""" branch = local('git rev-parse --abbrev-ref HEAD', capture=True) if branch != 'master': abort('you should call this on master branch') class RemoteHandler(object): def pull(self): """master branchに移動してソースコードの更新""" with cd(env.app_path): self.__check_no_change() run('git checkout master') run("git pull origin master") def restart_daemon(self): """svcを使って、restartさせる""" self.__install_required_package() res = run('supervisorctl restart {}'.format(env.daemon_name)) if res.failed: abort('REMOTE: fail restart daemon {}'.format(env.daemon_name)) return res def __install_required_package(self): req_txt = 'requirements.txt' with cd(env.app_path): run('pip3 install -r {}'.format(req_txt)) def __check_no_change(self): """変更がちゃんとcommitされているかを確認""" res = run('git ls-files -m') if res: abort('REMOTE: there are some diff on git supervised files') @task def deploy(): LocalHandler().push() rh = RemoteHandler() rh.pull() res = rh.restart_daemon() if res.succeeded: print("SUCCESS!! WELL DONE") else: print("TRY ONcE MORE :D")
基本設定を記述
from fabric.api import env from fabric.decorators import task @task def production(): """ 本番 """ env.environment = "production" env.app_path = '/path/to/project_root' env.daemon_name = 'supervisor daemon_name' env.user = 'ec2-user' env.hosts = ['host_name'] env.key_filename = '~/.ssh/key.pem'
module読み込み
このままだと、プロジェクトルートからfabricのタスクを呼べない。init.pyにimport書いてモジュール化する。
from fabfile.envs import production from fabfile.deploy import deploy
実際に自動デプロイをする
下記のコマンドをローカルで叩く。
$ fab production deploy