Capistrano3でSymfony2をデプロイする


Capistrano自体はRubyで作られたツールなのでPHPerにはあまりなじみの薄いツールなのかもしれません。
最近ではRuby界隈ではCapistranoをつかったデプロイが一般的になってきているような気がします。

そんなRuby製のCapistranoですが、[Capistrano::Symfony](https://github.com/capistrano/symfony)を使えばSymfony2のプロジェクトのデプロイは驚くほど簡単にできるんです。
ちなみに[DoctrineMigrationsBundle](http://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html)にも対応しているので、デプロイ時にマイグレーションを行う事も出来ます。

# 実際にデプロイしてみる

今回はさくらVPSのサーバにローカルのMacからCapistrano3を利用してデプロイしてみようと思います。
事前にデプロイするサーバ側にSSHキー登録しておきパスワードなしでログイン出来るようにしておきましょう。
また、事前にRubyとGemが使えるようにして且つ、Bundlerがインストールされている状態にしておいてください。

また今回使用したcapistranoのファイルは[ここ](https://github.com/polidog/capsymfony2-sample)に上がっています。


## 前提条件

前提条件をいくつか記載してきます。

- symfony2のプロジェクトがgithub or gitのリポジトリとして管理している
- apacheを利用している
- apacheのドキュメントルートは`/var/www/vhost/test/current`



## 下準備

まずは下準備ということでgemでcapistranoとcapistrano/symfonyを入れます。

適当にディレクトリを作成しましょう。

```
$ mkdir -p ~/capistrano/test
$ cd ~/capistrano/test
```

次にGemfileを作成します。

``` ~/capistrano/test/Gemfile
$ vim Gemfile

source 'https://rubygems.org'
gem 'capistrano',  '~> 3.1'
gem 'capistrano-symfony', '~> 0.1', :github => 'capistrano/symfony'
```

あとはbundle installするだけ。

```
$ bundle install --path=vendor/bundler
```

#### cap installを行う

capistrano無事は言ったと思うので、続いてcapistranoのファイルたちを用意します。

```
$ bundle ex cap install
```

たったこれだけで完了です。

```
$ tree
.
├── Capfile
├── Gemfile
├── Gemfile.lock
├── config
│   ├── deploy
│   │   ├── production.rb
│   │   └── staging.rb
│   └── deploy.rb
└── lib
    └── capistrano
        └── tasks

5 directories, 6 files
```

treeコマンドを叩くと上記のようなディレクトリ構成になっています。
これで準備完了です。

## デプロイ用の設定を記述する

まずCapistrano3を使うにあたって必要なファイルは以下の３です。
最初はそれだけ覚えていれば大丈夫かと思います。

1. Capfile
1. config/deploy.rb
1. config/deploy/*.rb

今回はこの３つだけ編集するようにします。

### Capfile
利用するライブラリを読み込みます。
今回はCapistrano::Symfonyを使うので以下のように追記してください。

```diff:Capfile
# Load DSL and Setup Up Stages
require 'capistrano/setup'
# Load DSL and Setup Up Stages
require 'capistrano/setup'

# Includes default deployment tasks
require 'capistrano/deploy'

++ # Include Symfony2 tasks
++ require 'capistrano/symfony'

# Includes tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
#   https://github.com/capistrano/rvm
#   https://github.com/capistrano/rbenv
#   https://github.com/capistrano/chruby
#   https://github.com/capistrano/bundler
#   https://github.com/capistrano/rails
#
# require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
# require 'capistrano/bundler'
# require 'capistrano/rails/assets'
# require 'capistrano/rails/migrations'

# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

```

### config/deploy/*.rb
config/deploy/ディレクトリの中に、`prodcution.rb`と`staging.rb`があります。
これはステージング用の設定を`staging.rb`に記述して本番環境用の設定を`production.rb`に記載します。

ちなみに共通化する内容を`config/deploy.rb`に記述します。
今回はproduction環境のみしか使わないのでproduction.rbを編集しましょう。

#### Roleの設定
私自身そこまでちゃんとロールを理解できているわけではありませんが、webサーバ用のデプロイや、batchサーバ、applicationサーバ等でロールをわけれる感じの利用のしかたで問題ないと思います。そこに属するサーバを記載するって認識で大丈夫だと思います。

今回はRoleをこんな感じで設定してみましょう

```diff:config/deploy/production.rb
-- role :app, %w{deploy@example.com}
-- role :web, %w{deploy@example.com}
-- role :db,  %w{deploy@example.com}
++ role :app, %w{hogeuser@fuga.com}
```
`hogeuser@fuga.com`の部分はデプロイ先のサーバを指定します。

#### serverの指定
次にデプロイするサーバの指定をしましょう

```diff:config/deploy/production.rb
-- server 'example.com', user: 'deploy', roles: %w{web app}, my_property: :my_value
++ server 'blog.polidog.jp', user:'polidog', role: [:app]
```

## config/deploy.rb
さて本番環境の指定ができたところで、デプロイに関する諸々をdeploy.rbに指定してきます。
将来的にステージング環境が出来る事を想定して、共通か出来る部分をdeploy.rbに書くようにします。

### プロジェクト名とリポジトリの指定

まずはプロジェクト名とgitのリポジトリを適当に指定します。

```diff:config/config.rb
-- set :application, 'my_app_name'
-- set :repo_url, 'git@example.com:me/my_repo.git'
++ set : application 'symfony2bbs'
++ set :repo_url, 'git@github.com:polidog/symfony2bss.git'
```
## デプロイする先のサーバのディレクトリの指定
次にapacheのベースとなるディレクトリを指定しましょう。


```diff:config/config.rb
-- # set :deploy_to, '/var/www/my_app'
++ set :deploy_to, '/var/www/vhost/test'
```

### デプロイしても変化してほしくないファイルを指定する

デプロイしても普遍的にしたファイルがあったら、linked_filesで指定しましょう。
よくあるのがcomposer install後に対話式で設定するparameters.ymlですよね。
こんな感じで指定しましょう。

```diff:config/config.rb
--  # set :linked_files, %w{config/database.ym
++ set :linked_files, %w{app/config/parameters.yml}

```

### webサーバを実行しているユーザーを指定

webサーバを実行しているユーザーを指定します。
今回はapacheユーザーで動かしているのでapacheを指定することにします。

```diff:config/config.rb
++ set :webserver_user,        "apache"
```

### デプロイが終わったタイミングでassets:install,assets:dumpを指定する

以下のように記載します。


```diff:config/config.rb
--  desc 'Restart application'
--  task :restart do
--    on roles(:app), in: :sequence, wait: 5 do
--      # Your restart mechanism here, for example:
--      # execute :touch, release_path.join('tmp/restart.txt')
--    end
--  end

--  after :publishing, :restart

--  after :restart, :clear_cache do
--   on roles(:web), in: :groups, limit: 3, wait: 10 do
--      # Here we can do anything such as:
--      # within release_path do
--      #   execute :rake, 'cache:clear'
--      # end
--    end
--  end

++  after 'deploy:updated',   'symfony:assets:install'
++  after 'deploy:updated',   'symfony:assetic:dump'
```

### Composerの設定
今回はデプロイ時にcomposerを利用するので、composer用の設定をしましょう。
先ほど記述した`after 'deploy:updated',   'symfony:assetic:dump'`の後ろに記述しましょう。

```diff:config/config.rb
after 'deploy:updated',   'symfony:assetic:dump'
++ before :starting, 'composer:install_executable'
```

以上でだいたいの本番設定が完了になりました。


## デプロイでできるか確認してみる
本当に上記の設定で問題ないのか確認してみましょう。
確認する為には以下のコマンドを実行します。

```
$ bundle ex cap procution deploy:check

ERRORlinked file /var/www/vhost/test/shared/app/config/parameters.yml does not exist on blog.polidog.jp
cap aborted!
```

私のばあいこのようなエラーがでました。
ちなみにディレクトリの書き込み権限がないとそれはそれでエラーになるので注意してください。

さて、この場合は以下のようにかいてshardsの中にparameters.ymlが置けるようにします

```diff:config/config.rb
namespace :deploy do
  after 'deploy:updated',   'symfony:assets:install'
  after 'deploy:updated',   'symfony:assetic:dump'

++task :upload do
++    on roles(:app) do |host|
++      upload!('config/parameters.yml',"#{shared_path}/app/config/parameters.yml")
++    end
++  end
++end
```




さてこのように書いたら一旦以下のコマンドを実行してください

```
$ bundle ex cap production deploy:upload
```

これにより、デプロイ対象となるサーバ側にparameters.ymlがアップロードされます。
そして再度checkコマンドを実行してみましょう

```
$ bundle ex cap procution deploy:check
```
今度はエラー無く終わるかと思います。

## デプロイする

```
$ bundle ex cap procution deploy
```

これでcomposer installからデプロイまで全て完了します。


いかがでしたでしょうか？複数台のサーバ運用しているプロジェクトやちょっとしたときにちょうど良かったり、あとはロールバックもできるので本当になにかと便利なツールです。
また、シェルスクリプト書くよりもメンテナンスしやすいし、拡張性もあるので、ぜひPHPerな人もつかってみてください。

# 最後に
差分ばかりサンプルがわかりづらいと思うので、今回使用したサンプルファイルは[ここ](https://github.com/polidog/capsymfony2-sample)に上がています。