[ Docker x Rails ]アプリをproduction環境でHerokuにデプロイする手順

# モチベーション
RailsのProduction環境のデプロイはmaster.keyの複製がややこしくかなり苦戦した。
また、いくつかDockerイメージをHerokuにデプロイする方法があるが、手順がややこしかったり制約が厳しい上動作しなかったりと面倒臭い。
なんとか自動化でき開発に集中できるようになったので備忘録としてまとめておく。(結果的にGithub　Actionsを用いたCDになった)

# 範囲
手順Dockerを使ったRailsアプリをGithub Actionsを使ってデプロイする手順を記載する。
Herokuにてアプリの作成方法やデプロイ用のDockerfileを含め個々の技術要素の説明は含めない。(備考に参考になる記事を貼っておく)

# 前提
2022.10.01現在
## 構築環境
- Ruby 2.7.2
- Ruby on Rails 6.0.5
- docker 20.10.13
- docker-compose 1.29.2
- node 17.6
- PostgreSQL 14.5
- heroku 7.52.0(darwin-x64/node-v12.21.0)

## 構成
- APIモード Rails(Rails.env=production)
- データベース PostgreSQLのみ
- platform linux/amd64(M1 Macだと指定する必要がある)
- M1 Mac
- ディレクトリ
    - MyApp(アプリ名)
        - .github
            - workflows
                - deploy_to_heroku.yml
        - app
        - Dockerfile

# 手順
下記5つの手順。ただし4は開発だと当たり前にやること、5は機械の仕事。
1. Herokuにてアプリを作成しておく
2. Github Actions用ファイルの作成
3. Github Secretsに環境変数を保持しておく
4. masterブランチにPRを出しマージする。
5. PRがマージされたらGithub ActionsでHerokuにデプロイする。

## 1. Herokuにてアプリを作成しておく
heroku create アプリ名 など

## 2. Github Actions用ファイルの作成
以下コピペ。
作成するフォルダは固定、ファイル名はお好みで変更できる。

```.github/workflows/deploy_to_heroku.yml
name: Build & Push to Heroku Docker Registry
on:
  pull_request:
    branches:
    - main
    types: [closed]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # checkout source
    - name: Git Checkout
      uses: actions/checkout@v2
    # Login in Heroku
    - name: Heroku Container Registry login
      env:
        HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
      run: heroku container:login
    - name: Create rails master key for build
      run: |
        touch $GITHUB_WORKSPACE/master.key
        echo ${{ secrets.RAILS_MASTER_KEY }} > $GITHUB_WORKSPACE/master.key
    # Build and push Docker image
    - name: Build and push
      env:
        HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
      run: heroku container:push -a ${{ secrets.HEROKU_APP_NAME }} web
    # Release
    - name: Release
      env:
        HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
      run: |
        heroku container:release -a ${{ secrets.HEROKU_APP_NAME }} web
        heroku run bundle exec rails db:migrate RAILS_ENV=production -a ${{ secrets.HEROKU_APP_NAME }} web

```

## 3. Github Secretsに環境変数を保持しておく
上記deploy_to_heroku.ymlには環境変数が必要である。
Github Secretsにて下記の3つを作成しておく。
アプリのGithubリポジトリにてSettings->Secrets->New repository secretで作成しておく。
- `HEROKU_API_KEY       #Heroku Account settingから取得`
- `HEROKU_APP_NAME      #heroku create時に設定されたもの`
- `RAILS_MASTER_KEY     #railsアプリの config/master.keyの内容をコピペ`

<b>変数は記事などには絶対に公開したらダメ。</b>

### 補足 Github Secrets
環境変数など外部に知られたくない情報を保持してくために使う。
初めての際は具体例がなく操作に手間取るので補足しておく。
設定は各変数につき1つの新規作成を行う。今回は3個Secretを作成する。

![スクリーンショット 2022-10-01 22.43.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/744524/986180f6-d5a2-6734-bb23-92eb9a03d6a6.png)
![スクリーンショット 2022-10-01 22.45.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/744524/3db242a8-9476-2461-23de-7581c8d1550e.png)


## 4. masterブランチにPRを出しマージする
普段通りアプリ開発をしてmasterブランチにPR出してマージすればGithub Actionsが勝手にデプロイしてくれる。

## 5. PRがマージされたらGithub ActionsでHerokuにデプロイする
Github Actionsの仕事



# 備考
僕が試したDockerを用いてHerokuにデプロイする方法は大きく3種類ある。
1. 手元でコンテナを作成してHerokuにデプロイする方法
1. heroku.ymlの構成ファイルを作成してデプロイする方法
1. 今回紹介するGithub Actionsを用いてHerokuにデプロイする方法

<b>ネックになるのがProduction環境をデプロイする際はmaster.keyをデプロイ環境にコピーしないといけない点。</b>(※1)

1の手元でイメージをビルドしそれをデプロイするのはDockerの知識がかなり必要になる。(※2)
2のheroku.ymlを使ったデプロイはベータ版であるがDBも記述できたりと便利であるが、ビルドの手順に融通が効かないためmaster.keyの受け渡しを行えず仕様を満たせなかった(※3)
3はたまたま良い記事を見つけ簡単に実行できたため採用した(※4)

## ※1 master.keyについて
master.keyは秘匿しないといけない情報だから本番環境にデプロイする時はコピーできないよ、でも本番環境でコマンド実行しても新しく作られるだけでうまく機能しないよって話(記事の中盤)
https://qiita.com/scivola/items/cc06ddbfd94d3118f693

## ※2 Docker buildツールやDockerマルチステージビルドを使ったmaster.keyのコピーが紹介されている
マルチステージビルドでログも残さずmaster.keyをコピーできる話。試してみたがうまくいかなかった。うまくいっていたのかもしれないが他の要因でうまくいっていなかったのかも。うまくいった人がいたら教えてください。
https://techblog.lclco.com/entry/2021/07/27/110000

## ※3 heroku.ymlでのデプロイ(Heroku公式サイト)
設定ファイルを作っておけばデータベースの設定や実行するDockerfileの指定、コンテナの実行後にコマンドを実行できる。痒いところに手が届かない感じ
https://devcenter.heroku.com/ja/articles/build-docker-images-heroku-yml#creating-your-app-from-setup

## ※4 Github Actionsを用いたHerokuへのデプロイ
Github Actions, Github Secretsを使えば秘匿情報を本番環境にコピーできるよって話。JDK11, MavenはJavaの開発環境で必要だけどRailsでは不要なので読み飛ばしてOK(記事の中盤)
https://medium.com/geekculture/deploy-to-heroku-from-a-macbook-m1-heroku-cli-or-githubactions-868bc3a50935

## その他Herokuについて
### Dockerを用いたデプロイ(公式)
https://devcenter.heroku.com/ja/articles/container-registry-and-runtime

### Dockerを用いたデプロイ(最もわかりやすいと感じた記事)
https://zenn.dev/tama8021/scraps/7119380d7fb456

### Dockerを用いないデプロイ(公式)←多分使わない
https://devcenter.heroku.com/ja/articles/getting-started-with-rails6#migrate-your-database

### HerokuのCLI操作リスト
デプロイがうまくいかなくてアプリを消す時に重宝した。
Heroku上でアプリを削除するだけでなく、github上のherokuブランチも削除する必要がある。その時のコマンドコピー先
`heroku apps:destroy --app アプリ名`
https://qiita.com/chihiro/items/5c3ff400f6cb99deb945