CakePHP2.3アプリケーションを Jenkins + Capistrano で、ユニットテスト&ビルドが成功した時に、自動デプロイする方法です。(ユニットテスト&ビルドの自動化はこちら

環境
デプロイ元:GMO VPS / CentOS6.0 / ALMinium(Redmine + Git + Jenkins)
デプロイ先:EC2 / Amazon Linux

1. Capistranoをインストール
デプロイ元に以下をインストールします。

sudo gem install capistrano
sudo gem install capistrano_colors
sudo gem install capistrano-ext
sudo gem install railsless-deploy

2. SSHの設定
デプロイ先サーバとSSH接続できるように設定します。

デプロイ元とデプロイ先のサーバに同じユーザーを作成。

# useradd deployuser
# passwd deployuser

デプロイ元で作成したSSH公開鍵をデプロイ先へ登録。
登録方法はこちらのサイトに詳しく書かれています。

デプロイ元から接続の確認。

[deployuser@xxx ~]$ ssh deployuser@xxx.xxx.xxx.xxx

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2012.09-release-notes/

There are 21 security update(s) out of 151 total update(s) available
Run "sudo yum update" to apply all updates.
Amazon Linux version 2013.03 is available.
[deployuser@ip-xxx-xxx-xxx-xxx ~]$

3. デプロイ定義ファイルの作成
ここからはこちらのサイトを参考。

デプロイ定義ファイルを作成したいディレクトリに移動して以下を実行すると、デプロイ定義ファイルが作成されます。

capify .

今回はjenkinsに新しいデプロイ用プロジェクトを作成して、ワークスペースにcapディレクトリを作成。そこに作成しました。

4. デプロイ先のステージの準備
上記のサイトを参考に、デプロイ先用として、config/deploy/develop.rbを作成。
とりあえず、IPとユーザーだけ設定。

role :web, "xxx.xxx.xxx.xxx" 
set :user, "deployuser"

5. デプロイの手順の定義
Capfileを以下に変更。

require "capistrano/ext/multistage"
require "capistrano_colors"
require "railsless-deploy"
require "rubygems"
set :application, "xxx"

set :scm, :git
set :repository,  "/var/opt/alminium/git/xxx"
set :branch, "master"

set :deploy_to, "/home/deployuser/xxx"
set :deploy_via, :copy
set :use_sudo, true

6. デプロイ先deployuserのsudo設定
デプロイ先サーバでdeployuserがパスワード入力なしでsudoできるように設定。

#vi /etc/sudoers
#Defaults requiretty
Defaults:deployuser !requiretty   # developerユーザーはtty無し

deployuser ALL=(ALL) NOPASSWD:ALL # パスワード無し

7. テスト
ワークスペース/cap/に移動して以下を実行。

# sudo -u deployuser cap develop deploy:setup
# sudo -u deployuser cap develop deploy

とここで、エラー。

failed: "sh -c 'cd /home/deployuser/xxx/releases && tar xzf /tmp/20130602133841.tar.gz && rm /tmp/20130602133841.tar.gz'" on xxx.xxx.xxx.xxx

確認してみると所有者がrootになっていました。

$ ls -l xxx
合計 8
drwxrwxr-x 2 root root 4096  6月  2 22:34 2013 releases
drwxrwxr-x 2 root root 4096  6月  2 22:34 2013 shared

所有者をdeployuserに変更

$ sudo chown -R deployuser:deployuser xxx

もう一回実行。OK!
current(シンボリックリンク)が作成されました。

CakPHPの通常構成の場合であれば、current/app/webroot がドキュメントルートになるようWebサーバを設定するようなのですが、弊社の今回のプロジェクトはディレクトリ構成が通常と異なるため、currentディレクトリ内のファイルを現在のドキュメントルート/var/www/html/にコピーするようにCapfileに設定しました。

8. Jenkinsのデプロイ用プロジェクトの設定
3.で作成していたデプロイ用プロジェクトの「シェルの実行」シェルスクリプトに以下を設定。

cd ${WORKSPACE}/cap && sudo -u deployuser cap develop deploy

9. Jenkinsユーザーのsudo設定
jenkinsユーザーがシェルスクリプトでsudoできるように設定。

#vi /etc/sudoers
#Defaults requiretty
Defaults:jenkins !requiretty   # jenkinsユーザーはtty無し

jenkins ALL=(ALL) NOPASSWD:ALL # パスワード無し

10. Jenkinsのユニットテスト&ビルド用プロジェクトの設定
ビルド後の処理→他のプロジェクトのビルド、でデプロイ用プロジェクトを入力。成功した場合のみ起動を選択。

以上で設定完了!

またこれを機に、
・デバッグレベルの設定(Apacheの環境変数を利用)
・データベースの切り替え(database.phpを環境に合わせて複数用意して切り替え)
・データベースのマイグレーション
・test.phpの無効化
・バージョンアップ時のキャッシュ削除
も自動化しました。下の4つはCapfileに記述。

実際に動かしてみると、
・ローカルPCからGitExtensionsでALMinium(Redimine+Git)のリポジトリにhttps Push
・それをトリガに、ユニットテスト&ビルド用プロジェクトが起動・・・約10分・・・成功!
・それをトリガに、デプロイ用プロジェクトが起動・・十数秒・・成功!!

毎回、手動で設定変更&ftpでアップするのに十数分はかかっていたのですが、わずか十数秒でアップできるようになりました。且つ、常に最新ビルドのファイルがサーバにあがっているという素敵な状態になりました。

2013.07.25追記
今週、約十数万件の病院・クリニックの情報を扱う医療系ポータルサイトのリニューアルが本番リリースとなりました。上記で作成したテスト環境へのデプロイで成功したソースを、本番環境へデプロイするプロジェクト(トリガは手動)を用意しておいたことで、緊急での修正にも迅速に対応することができました。DBの接続先や各種設定など毎回考慮する必要なく、jenkinsのビルド実行ボタンを押せば、十数秒で確実にデプロイされます。やるべき作業に集中できるとは正にこのことで、自動デプロイの威力を十分に感じることができました。


Tagged on: