Amazon EC2+Jenkins+capistranoでLaravel5をデプロイする




アプリケーションの更新のたびに発生するデプロイ作業。
そのデプロイをCapistranoで自動化するということを目標とし、EC2+Jenkins+Capistranoでデプロイ環境を構築する。




目次

Capistranoとは

Rubyで作られたデプロイメントツール。
高度な設定まで対応しており、学習コストが比較的高いが、いろいろ出来て便利。

何が出来るの?

設定ファイルを作成し、そのメソッド的なものを叩くことで汎用性の高いデプロイメントを行える。

デプロイはsshによるcopyや、gitなどのソースダウンロードが出来る。

今回はデプロイ先サーバにgitでソースをデプロイさせることとする。

EC2上にセットアップしたJenknsサーバにSSHで接続する

先回セットアップしたJenkinsサーバにログインを行う。

$ ssh ec2jenkins
Last login: Sun Apr 12 03:11:12 2015 from xxx

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

JenkinsサーバにCapistranoをインストール

capistranoは転送元サーバーにのみインストールされていれば良い。
今回はJenkinsサーバにそのままインストールすることとする。

Capistranoのインストール

gemで一発。

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

capistrano-colorsは見やすくなるので、入れておいたら便利
railsless-deployはRailsアプリ以外のDeployでは必須。
#今回はPHPのLaravel5アプリを想定しているため必須。

SSHのユーザ設定を行う

転送元サーバと転送先サーバに同じユーザを作る

転送元サーバ(Jenkins)と転送先サーバ(Develop)に双方同じユーザを作成する必要がある。
# そのユーザがSSHログイン等を行ないデプロイを行うため。

Jenkinsサーバ・Developサーバ両方

# useradd deployuser
# passwd deployuser

両方に同名ユーザを作ります。

次に、転送元サーバのSSH鍵を生成します。

転送元サーバユーザで鍵を生成

# su - deployuser
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/deployuser/.ssh/id_rsa):
Created directory '/home/deployuser/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/deployuser/.ssh/id_rsa.
Your public key has been saved in /home/deployuser/.ssh/id_rsa.pub.
The key fingerprint is:
xxx deployuser@xxx
The key's randomart image is:
+--[ RSA 2048]----+
|              ...|
|         . .   oE|
|      . o +  ....|
|       + =. . .  |
|.   = + S...     |
| o + * ..        |
|  o =  .         |
|   . ..          |
|      ..         |
+-----------------+

 公開鍵の取得

$ cd ~/.ssh/
$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwGgynlLOIgA0GH0N0mCuVHhCC/n2UN5mSxv1kfCJeSsgk+2cEd3eWAqLoaD8oJhY7AT2nKdMh~ deployuser@xxx

 鍵の内容(上記の最終行)をコピーする。

転送先サーバに転送元ユーザの鍵を登録する

まずはホスト情報を作る。面倒なんで、自分自身にSSHアクセスしてベース作る。

su - deployuser
$ ssh deployuser@localhost
The authenticity of host 'localhost (127.0.0.1)' can't be established.
RSA key fingerprint is xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
Permission denied (publickey).

 次に、転送元サーバの公開鍵を既知ホストとして登録する。

$ cd ~/.ssh
$ vi authorized_keys

上記ファイルの最終行に公開鍵情報をペーストし、上書き保存。
そして権限情報を最適化。

$ chmod 600 authorized_keys

これで転送元→転送先のSSH設定は終わりです。
上手く設定出来たか確認してみましょう。

転送元サーバから転送先サーバへSSHで接続確認

# su - deployuser
$ ssh deployuser@[転送先サーバのIP]
Last login: Sun Apr 12 04:13:22 2015 from xxx

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

すらすら書いているけど、権限関連でかなり詰まった・・・。

両方のサーバにGitをインストール

基本的にインストールされている可能性もありますが、年の為記載。
今回、デプロイはGitを活用するため、インストールしていないと「git clone」が行えないため、当然コケる。

転送元サーバ、転送先サーバにgitをインストール

$ sudo yum install -y git

JenkinsサーバにCapistranoを設定

Capistranoの設定ファイル群を作成していく。
ここがデプロイプロジェクトの肝となる。

$ su -deployuser
$ mkdir ~/deploy_setting
$ cd ~/deploy_setting/
$ cap install
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

 「cap install」で基本系のファイル群がジェネレートされる。

# Capistrano2では「capify [dir]」だったが、Capistrano3からは「cap install」に変わっているため注意。

Capistranoの設定ファイルを記述

プロジェクト共通設定ファイル(/home/deployuser/deploy_setting/config/deploy.rb)

# config valid only for current version of Capistrano
lock '3.4.0'

set :use_sudo, true
set :pty, true

namespace :environment do

    desc "Copy Environment Variables"
    task :sync do
        on roles(:app), in: :sequence, wait: 5 do
            execute :echo, "-n /etc/environment", raise_on_non_zero_exit: false
            fetch(:default_environment).each do |key, value|
                execute :sudo, :echo, "'#{key}=\"#{value}\"' >> sudo /etc/environment"
            end
            execute :sudo, :service, "httpd restart"
        end
    end

end

namespace :composer do

    desc "Running Composer Self-Update"
    task :update do
        on roles(:app), in: :sequence, wait: 5 do
            execute :sudo, :composer, "self-update"
        end
    end

    desc "Running Composer Install"
    task :install do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path  do
                execute :sudo, :composer, "install --no-dev --quiet"
            end
        end
    end

end

namespace :laravel do

    desc "Setup Laravel folder permissions"
    task :permissions do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path  do
                execute :sudo, :chmod, "u+x artisan"
                execute :sudo, :chmod, "-R 777 storage/"
                execute :sudo, :chown, "-R deployuser  ."
                execute :sudo, :chgrp, "-R deployuser  ."
            end
        end
    end

    desc "Run Laravel Artisan migrate task."
    task :migrate do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path  do
                execute :php, "artisan migrate"
            end
        end
    end

    desc "Run Laravel Artisan seed task."
    task :seed do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path  do
                execute :php, "artisan db:seed"
            end
        end
    end

    desc "Optimize Laravel Class Loader"
    task :optimize do
        on roles(:app), in: :sequence, wait: 5 do
            within release_path  do
                execute :php, "artisan clear-compiled"
                execute :php, "artisan optimize"
            end
        end
    end

end

namespace :deploy do

    after :published, "composer:update"
    after :published, "composer:install"
    after :published, "environment:sync"
    after :published, "laravel:permissions"
    after :published, "laravel:optimize"
    after :published, "laravel:migrate"
    after :published, "laravel:seed" 
end

env毎の設定ファイル(/home/deployuser/deploy_setting/config/deploy/develop.rb)

# Develop Settings

# Git Repository
set :scm, "git"
set :repository, "[github address(ex git@github.com/aaa/)]"
set :branch, "[develop]"

# Server Setting
ec2server = "deployuser@xxx.compute.amazonaws.com"
role :app, ec2server
role :web, ec2server
role :db, ec2server, :primary => true

server 'xxx.compute.amazonaws.com'
set :user, "deployuser"
set :ssh_options, {
        user: 'deployuser',
        keys: %w{/home/deployuser/.ssh/id_rsa},
#       forward_agent: true
        #auth_methods: %w{publickey}
}
set :deploy_to, "/var/www/laravel5-project"

set :default_environment, {
  "PR_ENV" => "localhost",
  "APP_DEBUG" => "true",
  "APP_KEY" => "[hogehogehoge]",
  "DB_HOST" => "[db_host]",
  "DB_DATABASE" => "[db_name]",
  "DB_USERNAME" => "[db_user]",
  "DB_PASSWORD" => "[db_pass]",
  "CACHE_DRIVER" => "file",
  "SESSION_DRIVER" => "file",
}

書き終わったらチェックする。

デプロイ先サーバでsudoを実行できるよう権限付与。

$ sudo vi /etc/sudoers

#Defaults requiretty
Defaults:deployuser !requiretty   # デプロイユーザーの指定
deployuser ALL=(ALL) NOPASSWD:ALL # no password

デプロイテストの実行

コマンド一覧の確認

$ cap -T
cap composer:install               # Running Composer Install
cap composer:update                # Running Composer Self-Update
cap deploy                         # Deploy a new release
cap deploy:check                   # Check required files and directories exist
cap deploy:check:directories       # Check shared and release directories exist
cap deploy:check:linked_dirs       # Check directories to be linked exist in shared
cap deploy:check:linked_files      # Check files to be linked exist in shared
cap deploy:check:make_linked_dirs  # Check directories of files to be linked exist in shared
cap deploy:cleanup                 # Clean up old releases
cap deploy:cleanup_rollback        # Remove and archive rolled-back release
cap deploy:finished                # Finished
cap deploy:finishing               # Finish the deployment, clean up server(s)
cap deploy:finishing_rollback      # Finish the rollback, clean up server(s)
cap deploy:log_revision            # Log details of the deploy
cap deploy:published               # Published
cap deploy:publishing              # Publish the release
cap deploy:revert_release          # Revert to previous release timestamp
cap deploy:reverted                # Reverted
cap deploy:reverting               # Revert server(s) to previous release
cap deploy:rollback                # Rollback to previous release
cap deploy:set_current_revision    # Place a REVISION file with the current revision SHA in the current release path
cap deploy:started                 # Started
cap deploy:starting                # Start a deployment, make sure server(s) ready
cap deploy:symlink:linked_dirs     # Symlink linked directories
cap deploy:symlink:linked_files    # Symlink linked files
cap deploy:symlink:release         # Symlink release to current
cap deploy:symlink:shared          # Symlink files and directories from shared to release
cap deploy:updated                 # Updated
cap deploy:updating                # Update server(s) by setting up a new release
cap environment:sync               # Copy Environment Variables
cap install                        # Install Capistrano, cap install STAGES=staging,production
cap laravel:migrate                # Run Laravel Artisan migrate task
cap laravel:optimize               # Optimize Laravel Class Loader
cap laravel:permissions            # Setup Laravel folder permissions
cap laravel:seed                   # Run Laravel Artisan seed task

テスト実行

$ sudo -u deployuser cap develop deploy:check

ここでエラーチェックを行う。
エラーの大半は権限関係やインストール不足なので、ひとつずつ確認して潰していく。

JenkinsにCapistranoの実行を紐付け

ここまで来るとなんということは無いですね。

ビルドが成功した後のシェルの実行に下記のようにしてcapistranoのトリガを紐付け

cd $[deploy_dir] && sudo -u deployuser cap develop deploy

上手く実行出来ないと思ってたら、Jenkinsユーザがsudoを実行出来なかったためでした。
sudoersにJenkinsユーザも追記

$ sudo vi /etc/sudoers
#Defaults requiretty
Defaults:jenkins !requiretty   # デプロイユーザーの指定
jenkins ALL=(ALL) NOPASSWD:ALL # no password

これでひとまず設定完了です。

しかし、もう少しenv設定などの取り回しを柔軟にしたいなーと思っています。
しばらくこれで回してみて問題が見えたらHackしていきましょう。

みなさん、よいCIを。

スポンサーリンク
スポンサーリンク




スポンサーリンク




シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
スポンサーリンク