初心者向け! Rails6+CircleCI+Capistrano+AWS(EC2)で自動デプロイ

#はじめに

先日、ポートフォリオ作成後、AWSにCapistranoとCircleCIを使ってCIツールによる自動デプロイを実装できたので、備忘録として残しておこうと思います。

なお、前述したとおり備忘録としてなので参考になる保証はありません。

#前提

・Railsアプリが作成できていること
・EC2にCapistranoで自動デプロイを実現できていること

以上の条件に当てはまる場合にのみCIツールによるCapistranoの自動デプロイを行います。

#開発環境

##ローカル
・Rails6
・MySQL5.6.50
・Docker
・docker-compose

##本番
・EC2
・RDS(MariaDB)
・Unicorn
・Nginx
・Capistrano

本願環境にはDockerとdocker-composeは用いていません。

#手順
①CircleCIにEC2にログインするための秘密鍵を設定する
②.circleci/config.ymlにssh接続の記述をし、ログインできるか確かめる
③githubのmasterブランチにmergeもしくはpushしたときにCapistranoによるデプロイを行う

#1)CircleCIにEC2ログインの秘密鍵を設定する

多くの人はここで詰まる事が多く、筆者自身も２時間くらいつまりました。
まず、**どの鍵が必要なのかがわからない**ということでつまります。
必要なのは、`ssh`からEC2へログインする時に使う`キーペア`と呼ばれる鍵です。

インスタンスを作成する時に`pemファイル`形式でダウンロードする秘密鍵をCircleCIにも登録します。

ここで１つ注意点があり、CircleCIで使えるのは`pem形式のみ`ということです。
`OPENSSH`形式の場合は`pem形式`にする必要があるので下記の記事を参考に実行してみてください。(筆者の場合は最初からpem形式だったため、この辺は詳しくないので。。。)

>[CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた](https://qiita.com/YK0214/items/98bbdf7ce25c557c77a3)

ということなので、ターミナルの`ssh`ディレクトリに移って、以下のコマンドを実行します。

```ruby:ターミナル
.ssh % cat XXXXXXXXXXXXX.pem
# ご自身のEC2にログインする際のキーペア
```

すると以下のように非常に長い暗号が出力されます。

```ruby:ターミナル
-----BEGIN RSA PRIVATE KEY-----
WWIEXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# まだまだありますが割愛
-----END RSA PRIVATE KEY-----%    
```

これを`-----BEGIN RSA PRIVATE KEY-----`から`-----END RSA PRIVATE KEY-----%   `までコピーします。

もしくは以下のような方法で一括コピーも可能です。

```ruby:ターミナル
.ssh % pbcopy < ~/.ssh/XXXXXXXXX.pem
```

このコマンドを使うことで先ほどの長い暗号をコピーすることができます。

## 1-2)CircleCIにキーペア登録
CircleCIのprojectに移り、project settingにを開きます。(右上の歯車アイコンをクリック)
![171a000a3a3105940bd7d90856926ca8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/7f86c91b-84dc-c307-6a53-bbeb9afa76b3.png)

すると以下のように設定画面に遷移するので、メニューバーの`SSH Keys`を選択して、鍵を設定します。
![27f8250132f8c8f66b26738a49dd32dd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/cede68d6-3974-cd24-f288-31402c6d072c.png)


ページが切り替わったら、スクロールして以下の`Add SSH Key`をクリックしましょう。
![ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/58b653c2-f188-a2b7-4e3b-0a18d831aff7.png)

クリックすると以下のようになるので、`Hostname`と`Private Key`を入力して、`Add SSH Key`をクリックします。

`Hostname`には`ElasticIP`を入れてもいいですが、筆者の場合は独自ドメインを取得していたため`www.myapp.com`のような形で記入しました。

続いて`Private Key`には、先ほどコピーした暗号を貼り付けます。
![sshsh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/2e0e7f42-c7ad-8e08-1c8c-660123d1d121.png)

しばらくすると、元の画面に戻ると思います。すると、`Fingerprint`なる項目に数字と文字と「:」の文字列が存在していると思います。それをコピーしてメモなどに保存しておきましょう。

また、以下のように`Deploy Key`と`User Key`を設定しておきましょう。
![gitdeploy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/5af1dbb7-0898-98ee-3d1a-d2423ce411fd.png)

これの設定をしないと、CircleCiの`Code Check`の段階で`Git`を認証せずにエラーになるため、必ず設定しましょう。


CircleCI(GUI)での設定は以上です。

#2).Circlci/cofig.ymlの記述

次にCircleCIでSSH接続できるか確認します。
以下のように存在している記述の`steps:` `- checkout`の下などに記述を加えます。
筆者の場合はCapistranoの前はHerokuとCIパイプラインを構築してたため記述を加え、`git push`しました。

```ruby:.circleci/config.yml
- add_ssh_keys:
    fingerprints: "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"
```
この記述を加え確認しましょう。
以下のように成功していたらOKです。
![install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/5039090e-72a8-e651-499d-eaf7490900a6.png)

#3)githubのmasterブランチにmergeもしくはpushしたときにCapistranoによるデプロイを行う

ここからが実際に、CIツールによるCapistrano自動デプロイの実装です。

まずこちらが成功したコードです。

```ruby:.circleci/config.yml
version: 2.1

orbs:
  ruby: circleci/ruby@1.1.0

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
          BUNDLER_VERSION: 2.1.4
    steps:
      - checkout
      - run: gem install bundler -v 2.1.4
      - run:
          name: Which bundler?
          command: bundle -v
      - ruby/install-deps

  deploy:
    docker:
      - image: circleci/ruby:2.6.5-node-browsers
        environment:
          BUNDLER_VERSION: 2.1.4
    steps:
      - checkout
      - ruby/install-deps
      - add_ssh_keys:
          fingerprints: "XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"
      - deploy:
          name: Capistrano deploy
          command: bundle exec cap production deploy

workflows:
  version: 2.1
  build-deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master
```

筆者が参考にしたのは参考文献にもある記事と公式ですが、難しかったです(笑)

１つずつ解説すると、dockerのimageは自分のrubyのバージョンに合わせ、bundlerの自分のバージョンに合わせるような記述をしました。

まず`job`としてコードチェックのための`build`を行い、bundlerのインストールするようにします。

そして`deploy job`ではCapistranoを走らせるようにして、どのSSHに接続するかを指定しています。
これが先ほど設定したり、記述した`add_ssh_keys:`という記述に当たります。

その下のコマンドで実際にCapistranoが走るという構図になっています。

そして`workflows`では`only: master`としてmasterブランチにpushもしくはmergeがあった場合に行うように設定しています。

詳しい説明は下記の記事や、記事内で参考にしていた文献に書いてありますので、そちらの方も合わせて読むとより理解しやすいと思います。

>[【circleCI】rails5.2/Capistrano/CICD環境によるAWSへの自動デプロイ](https://qiita.com/AK4747471/items/882b70f663f4a80ae770)

結構、苦労しましたが、なんとか実装できました。
皆さんも頑張ってください。

#参考文献

[公式ドキュメント](https://circleci.com/docs/ja/2.0/deployment-integrations/)

[CircleCI + Capistrano + AWS(EC2) + Railsで自動デプロイしてみた](https://qiita.com/YK0214/items/98bbdf7ce25c557c77a3)