Capistranoでデプロイしてみます

私の専門が主にPHP言語で書いていますけど、２か月前に、Rubyのプロジェクトに参加しています。最初はRubyの書き方を学ぶとか、各定義とか。。。２か月に過ぎした。Rubyが好きになっています。デプロイの件も学びたいですので、Capistranoを見つけました。始めて利用ですから、かならず誤解ところがあります。ご指摘ありがとうございます。

#Agenda
1. Capistranoとは？
2. Rsyncとは？
3. デモ
4. 結論

## 1. Capistranoとは？
CapistranoとはRuby製でデプロイというツールです。Ruby言語で書いていますけど、どのフレームワークと他の言語でもデプロイができます。

production デプロイするとき、以下のコマンドで実行されます。

```
$ cd my-capistrano-enabled-project 
$ cap production deploy 
```

capを実行すると、SSH経由リクエストをデプロイします。さらに、義務というタスクを設定するできます。
例えば：

```ruby:task.rb
task :go_to_project do
  on roles(:worker) do
    execute "cd project_name"
  end
end
after "deploy:published", "go_to_project"
```
なぜCapですか、どのターゲットからCapを選択されますか？
現在色々デプロイツールがあるけど、それぞれツールが弱点と強点があります。Capの一つ点が大好きのが、SSH経由で直接デプロイします。そして、機能が多いです。

- 強力な規則
- 複数のステージ
- パラレル実行
- サーバルール
- コミュニティドリブン
- SSH経由

### Capをインストール
必須のは：

- Rubyバージョンは2.0以上です。
- Gitを利用しています。
- Bundlerです。

**1.1** 以下のコマンドでCapistrano gemをインストールします。

```
gem "capistrano", "~> 3.11", require: false
```
**1.2** Gemfileに追記してbundle installで実行してください。

```
$ bundle install
```

**1.3** 設定ファイル作成

```
bundle exec cap install
```
**1.4** 上記のコマンドを実行すると、以下のファイルがあります。

```
├── Capfile
├── config
│   ├── deploy
│   │   ├── production.rb
│   │   └── staging.rb
│   └── deploy.rb
└── lib
    └── capistrano
            └── tasks
```

**1.5** Capのコマンド

```
# list all available tasks
$ bundle exec cap -T

# deploy to the staging environment
$ bundle exec cap staging deploy

# deploy to the production environment
$ bundle exec cap production deploy

# simulate deploying to the production environment
# does not actually do anything
$ bundle exec cap production deploy --dry-run

# list task dependencies
$ bundle exec cap production deploy --prereqs

# trace through task invocations
$ bundle exec cap production deploy --trace

# lists all config variable before deployment tasks
$ bundle exec cap production deploy --print-config-variables
```

## 2. Rsyncとは？

Rsyncでアプリとbundled gemsをインストールします。
Capistrano::BundleRsyncの作業フォローです。

- Do ```git clone --mirror URL .local_repo/mirror``` on a deploy (local) machine.
- Extract a branch by ```git archive {branch}``` to ```.local_repo/releases/{datetime}```
- Do ```bundle --without development test --path .local_repo/bundle``` on a deploy (local) machine.
- Deploy the ```release``` directory to remote machines by ```rsync```.
- Deploy the ```bundle``` directory to remote machines by ```rsync```.

**2.1** 具体設定

| 名前       　　　 |       デフォルト 　 |    説明             |
|:-----------------|------------------:|:------------------:|
| repo_url         |    。 　　　　　　　|      GitのURLです|
| branch           |    master 　　　　 |    ブランチデプロイ|
| ssh_options      |    {}             |        SSH設定     |
| keep_releases    |               5   |         リリースバージョン保持         |

ほかの設定があります。詳細については、下記のリンク参考してみます。

https://github.com/sonots/capistrano-bundle_rsync

**2.2** BundleRsyncのタスクコマンド

```
$ cap stage deploy --trace | grep Execute
** Execute bundle_rsync:check
** Execute bundle_rsync:clone
** Execute bundle_rsync:update
** Execute bundle_rsync:create_release
** Execute bundle_rsync:bundler:install
** Execute bundle_rsync:rsync_release
** Execute bundle_rsync:rsync_shared
** Execute bundle_rsync:bundler:rsync
** Execute bundle_rsync:clean_release
** Execute bundle_rsync:set_current_revision
```

## 3. デモ

話題：本番で画像サーバをデプロイしてください。

```ruby:Capfile
set :deploy_config_path, 'cap/deploy.rb'
set :stage_config_path, 'cap/deploy'

# Load DSL and Setup Up Stages
require 'capistrano/setup'

# Includes default deployment tasks
require 'capistrano/deploy'

require 'capistrano/rbenv'
require 'capistrano/bundle_rsync'
require 'whenever/capistrano'

$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')

Dir.glob('cap/lib/capistrano/tasks/*.rake').each { |r| import r }

```

```ruby:Gemfile
source 'https://rubygems.org'

gem 'capistrano', '3.4.0'
gem 'capistrano-rails'
gem 'capistrano-rbenv'
gem 'capistrano3-unicorn'
gem 'capistrano-bundle_rsync'
gem 'whenever'
```

```ruby:deploy.rb

set :user, 'user'
set :deploy_app_name, 'deploy_app_name'
set :application, 'application'

set :deploy_to, "/data/#{fetch(:user)}/#{fetch(:deploy_app_name)}"
set :rbenv_type, :user
set :scm, :bundle_rsync
set :bundle_rsync_max_parallels, ENV['PARA']
set :bundle_rsync_rsync_bwlimit, ENV['BWLIMIT']
set :keep_releases, 3
set :pty, true
set :bundle_binstubs, nil
set :use_sudo, true
set :rbenv_path, '$HOME/.rbenv'

namespace :deploy do
  task :rsync_files do
    config = Capistrano::BundleRsync::Config
    run_locally do
      hosts = release_roles(:all)
      Parallel.each(hosts, in_threads: config.max_parallels(hosts)) do |host|
        execute "rsync -az -e ssh /home/#{fetch(:user)}/.alias #{host}:/home/#{fetch(:user)}/"
      end
    end
  end

  task :sync_shared_config do
    config = Capistrano::BundleRsync::Config

    on roles(:image) do
      path = "#{fetch(:deploy_to)}/shared"
      execute :sudo, :mkdir, '-p', path
      execute :sudo, :chown, '-R', "#{fetch(:user)}:#{fetch(:user)}", deploy_to

      run_locally do
        hosts = release_roles(:all)
        Parallel.each(hosts, in_threads: config.max_parallels(hosts)) do |host|
          execute "rsync -az -e ssh shared/ #{host}:#{path}"
        end
      end
    end
  end


  task :pre_rsync_action do
    on roles(:image) do
      config = Capistrano::BundleRsync::Config
      run_locally do
        execute ("cd #{config.local_release_path} && /usr/local/bin/composer install #{fetch(:composer_install_flags)}")
      end
    end
  end

end

before 'deploy:starting', 'deploy:sync_shared_config'
before 'bundle_rsync:rsync_release', 'deploy:pre_rsync_action'

```

```ruby:product.rb
set :application, "image-product"
set :stage, :production
set :ssh_options, { forward_agent: true }
set :repo_url, 'git@github.com:project-demo/project-demo.git'
set :branch, ENV['BRANCH'] || 'master'
set :composer_install_flags, '--no-dev --prefer-dist --no-interaction --optimize-autoloader'

set :linked_files, %w{.env}
set :god_roles, %i(image)
set :god_log_level, 'info'
set :bundle_rsync_skip_bundle, true
set :linked_dirs, []

role :image, %w{192.198.10.33}, user: fetch(:user)

```

上記の全部設定したあと、次のステップに進みます。下記のコマンドを実行してください。

```
bundle exec cap product deploy
```
そのとき、本番にデプロイしています。ちょっと時間がかかります。　完了したら、このＩＰ```192.198.10.33```確認してみましょう。
ここまで大体完了します。初めてＣａｐを利用してメーモします。違うところとか誤解とかがあれば、ご指摘してください。

## 4. 結論
最近デプロイツールが多いですけど、弱点と強点もあります。自分で適当ツールを選択したほうがいいと思います。

**良い日を！**