Capistranoの試し書きメモ

# Capistranoの試し書きメモ

今更ではあるが、Capistranoを使いたくなってみたので使い方を学ぶ過程でのメモ。

基本的にはドキュメントが充実しているので、以下を参照する。  
http://capistranorb.com/

## Capistranoを使うための準備

プロジェクトを作成する。

```
$ mkdir my-capistrano-enabled-project
$ cd my-capistrano-enabled-project
```


`Gemfile`を作成する。

```ruby
group :development do
  gem "capistrano", "~> 3.10", require: false
end
```

`bundle install`でCapistranoをインストール。

```
$ bundle install
Using rake 12.3.0
Using net-ssh 4.2.0
Using net-scp 1.2.1
Using sshkit 1.16.0
Using airbrussh 1.3.0
Using bundler 1.16.1
Using concurrent-ruby 1.0.5
Using i18n 0.9.5
Using capistrano 3.10.2
Bundle complete! 1 Gemfile dependency, 9 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

Capistranoを利用できるように初期セットアップ

```
bundle exec cap install
```

## ディレクトリ構造


```
$ tree my-capistrano-enabled-project
my-capistrano-enabled-project
├── Capfile
├── Gemfile
├── Gemfile.lock
├── config
│   ├── deploy
│   │   ├── production.rb
│   │   └── staging.rb
│   └── deploy.rb
├── lib
│   └── capistrano
│       └── tasks
└── log
    └── capistrano.log
```

* `Capfile`
    * `require`などの設定と`lib`以下のtaskの読み込みに利用する。
* `config/deploy.rb`
    * 全ステージ共通の設定を書く。
* `config/deploy`
    * 最初は`production.rb`と`staging.rb`しかない。
    * ローカル環境用やQA環境用など追加したい場合は、後述の手順を参照する。
    * `production.rb`などには、各ステージの設定を書く。サーバのIPアドレスや専用のtaskなど。
* `lib/capistrano/tasks`
    * オリジナルのtaskを追加したい場合に使う。

## 基本的なコマンド

* オリジナルのタスクの確認

```
$ bundle exec cap -T
```

`lib/capistrano/tasks`配下にタスクを定義したrakeファイルを作成するとこれも追加される。

* ステージにデプロイ

```
$ bundle exec cap [ステージ名(production/stagingなど)] deploy
```

* ステージにデプロイする前の確認

```
$ bundle exec cap [ステージ名(production/stagingなど)] deploy --dry-run
```


## ステージ用のファイルを追加する。

ステージファイルを増やしたい場合は、以下のようなコマンドで可能。  
たとえば、local環境、sandbox環境、qa環境用のステージファイルを作成したいい場合は、以下のようになる。

```
$ bundle exec cap install STAGES=local,sandbox,qa
```

## `config/deploy.rb`の設定

`deploy.rb`には、全ステージ共通の設定を書く。  

```ruby
# Capistranoのバージョン
lock "~> 3.10.2"

# アプリケーションの名前
set :application, "ChainerPractice"

# リポジトリの名前
set :repo_url, "https://github.com/48hands/ChainerPractice.git"

# リポジトリのブランチ
set :branch, 'master'

# sudoをコマンドにつけるか設定する。
set :use_sudo, false
```

ここで、`set`は変数をセットしている。  
たとえば、以下のように独自の変数を定義することができる。

```ruby
set :other_config,  "hogehoge"
```

`set`で定義した変数を`config/deploy.rb`や,`config/deploy/[ステージ].rb`で利用するには`fetch`を使う。

```ruby
set :special_thing, -> { "SomeThing_#{fetch :other_config}" }
```

## Capistranoを使ったはじめてのデプロイ

早速、Capistranoでデプロイしてみる。  
今回はローカル環境に構築したVMに対してデプロイしてみる。
筆者は、`config/deploy/local.rb`を以下のように編集した。

```ruby
# # deploy先のサーバ情報
role :myLocalVM, %w{vagrant@192.168.33.41　vagrant@192.168.33.42}

# deploy先のディレクトリ
set :deploy_to, "/tmp/#{fetch(:application)}"

# SSHの設定情報
set :ssh_options, {
  port: 22,
  forward_agent: true,
  keys: %w(/Users/48hands/Desktop/work_vm/.vagrant/machines/vm2/virtualbox/private_key
  /Users/48hands/Desktop/work_vm/.vagrant/machines/vm2/virtualbox/private_key
  )
}
```

この状態で、`bundle exec cap [ステージ] deploy`すると、デプロイが体感できる。

```
bundle exec cap local deploy
00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 vagrant@192.168.33.41 0.278s
      Uploading /tmp/git-ssh-ChainerPractice-local-nagakuray.sh 100.0%
      02 chmod 700 /tmp/git-ssh-ChainerPractice-local-nagakuray.sh
    ✔ 02 vagrant@192.168.33.41 0.051s
00:00 git:check
      01 git ls-remote https://github.com/48hands/ChainerPractice.git HEAD
      01 7ed08a9ccf8e758eff6230e0d6892488fb4b8e01	HEAD
    ✔ 01 vagrant@192.168.33.41 1.459s
00:01 deploy:check:directories
      01 mkdir -p /tmp/ChainerPractice/shared /tmp/ChainerPractice/releases
    ✔ 01 vagrant@192.168.33.41 0.054s
00:02 git:clone
      The repository mirror is at /tmp/ChainerPractice/repo
00:02 git:update
      01 git remote set-url origin https://github.com/48hands/ChainerPractice.git
    ✔ 01 vagrant@192.168.33.41 0.052s
      02 git remote update --prune
      02 Fetching origin
    ✔ 02 vagrant@192.168.33.41 1.432s
00:03 git:create_release
      01 mkdir -p /tmp/ChainerPractice/releases/20180422094055
    ✔ 01 vagrant@192.168.33.41 0.056s
      02 git archive master | /usr/bin/env tar -x -f - -C /tmp/ChainerPractice/releases/2…
    ✔ 02 vagrant@192.168.33.41 0.057s
00:03 deploy:set_current_revision
      01 echo "7ed08a9ccf8e758eff6230e0d6892488fb4b8e01" > REVISION
    ✔ 01 vagrant@192.168.33.41 0.062s
00:04 deploy:symlink:release
      01 ln -s /tmp/ChainerPractice/releases/20180422094055 /tmp/ChainerPractice/releases…
    ✔ 01 vagrant@192.168.33.41 0.053s
      02 mv /tmp/ChainerPractice/releases/current /tmp/ChainerPractice
    ✔ 02 vagrant@192.168.33.41 0.065s
00:04 deploy:log_revision
      01 echo "Branch master (at 7ed08a9ccf8e758eff6230e0d6892488fb4b8e01) deployed as re…
    ✔ 01 vagrant@192.168.33.41 0.050s
```

実際にデプロイできているか確認するために、SSHでVMにログインして確認するとデプロイできていることがわかる。

```
[vagrant@192.168.33.41 ~]$ ls -l /tmp/ChainerPractice/
合計 4
lrwxrwxrwx. 1 vagrant vagrant  44  4月 19 21:35 current -> /tmp/ChainerPractice/releases/20180422094055
drwxrwxr-x. 4 vagrant vagrant  50  4月 19 21:35 releases
drwxrwxr-x. 7 vagrant vagrant 156  4月 19 21:35 repo
-rw-rw-r--. 1 vagrant vagrant 216  4月 19 21:35 revisions.log
drwxrwxr-x. 2 vagrant vagrant   6  4月 19 20:25 shared
```

## タスクを定義

`config/deploy/local.rb`

```ruby
# # deploy先のサーバ情報
role :myLocalVM, %w{vagrant@192.168.33.41 vagrant@192.168.33.42}
role :ftpserver , %w{vagrant@192.168.33.41}

# # deploy先のディレクトリ
set :deploy_to, "/tmp/#{fetch(:application)}"

# SSHの設定情報
set :ssh_options, {
  port: 22,
  forward_agent: true,
  keys: %w(
    /Users/nagakuray/Desktop/lesson_vm/.vagrant/machines/rabbit1/virtualbox/private_key
    /Users/nagakuray/Desktop/lesson_vm/.vagrant/machines/rabbit2/virtualbox/private_key
  )
}

# タスクを定義
namespace :ftp do
  desc 'stop ftp server'
  task :stop do
    on roles(:ftpserver) do
      # コマンドの標準出力結果を取得
      output = capture "hostname"
      execute "echo #{output}"
      execute "sudo systemctl stop vsftpd.service"
    end
  end
end
```

以下のように、`ftp:stop`タスクを実行できる。

```
$ bundle exec cap local ftp:stop
00:00 ftp:stop
      01 echo rabbit1
      01 rabbit1
    ✔ 01 vagrant@192.168.33.41 0.062s
      02 sudo systemctl stop vsftpd.service
    ✔ 02 vagrant@192.168.33.41 0.103s
```

## オリジナルタスクを定義

`lib/capistrano/tasks/sample.rake`

```ruby
namespace :utils do
  desc "ls command exec"
  task :ls do
    on roles(:myLocalVM) do
      execute "ls /tmp"
    end
  end
end
```

以下のように`utils:ls`タスクを実行できる。

```
$ bundle exec cap local utils:ls
```

## よくやりそうなタスクの例

* ファイルアップロード,ダウンロード
    * アップロードは`upload!`メソッドを利用する。
    * ダウンロードは`downlod!`メソッドを利用する。ログ収集とかで使えそう。

```ruby
namespace :config do
  task :upload do
    on roles(:myLocalVM) do
      sudo "chmod 777 /etc"
      # 第一引数はローカルのファイルパス
      # 第二引数はリモートのファイルパス
      upload!("/tmp/hogehoge", "/tmp/hogehoge")
      sudo "chown vagrant:vagrant /tmp/hogehoge"
    end
  end

  task :download do
    on roles(:myLocalVM) do
      # 第一引数はリモートのファイルパス
      # 第二引数はローカルのファイルパス
      download! "/tmp/hogehoge", "/tmp/fugafuga"
    end
  end
end
```

```
$ echo "testfile" > /tmp/hogehoge
$ bundle exec cap local config:upload
00:00 config:upload
      01 sudo chmod 777 /etc
    ✔ 01 vagrant@192.168.33.41 0.348s
      Uploading /tmp/hogehoge 100.0%
      02 sudo chown vagrant:vagrant /tmp/hogehoge
    ✔ 02 vagrant@192.168.33.41 0.059s

$ bundle exec cap local config:download
00:00 config:download
      Downloading /tmp/fugafuga 100.0%
```