[heroku]DockerとherokuとCircleCIでアプリをらくらくデプロイ

# 概要
dockerでflaskアプリを作成しherokuへアップロードした後、circleciを使ってはじめのアップデート後の自動デプロイまでを実装したのでその方法をまとめる。おそらくflask以外のアプリでもこの方法で自動デプロイまでできるのでさんこうまでに。

# 仕様

|  技術  |  バージョン  |
| ---- | ---- |
|  Docker  |  20.10.2    |
|  docker-compose  |  1.27.4  |

# 流れ

herokuのdockerでのデプロイの流れは以下のようになる。

**①herokuのログイン**

**②herokuのアプリ作成**

**③herokuとgitの紐付け**

**④herokuへdockerコンテナをpush**

**⑤herokuでdockerコンテナを起動する**

**⑥herokuでアプリの確認**

**⑦herokuのログの確認**

**⑧herokuのサーバーの停止と再起動**

**⑨herokuのapikeyの作成**　←CircleCIに必要なため

※前提として全てアプリのディレクトリ内を想定している。

### ①herokuのログイン
herokuへのログインは以下のコマンドを叩く。
container:loginはdockerを起動するために必要なので必ず両方のコマンドをしなければならない。

```:terminal
# herokuへのログイン
heorku login

heroku  container:login
```

###②herokuのアプリ作成
次にherokuで作成するアプリの名前を決める。
※マイナーな名前にしないと既に使われているとか言われてエラーになるので注意

```:terminal
# app名に自分の付けたいアプリの名前を入れる
heroku create app名
```

###③herokuとgitの紐付け
gitとherokuを連携するために以下のコマンドを叩く。
app名には②で指定したapp名をいれる。

```:terminal
heroku git:remote -a app名
```
###④herokuへdockerコンテナをpush
herokuへdockerのコンテナをデプロイするために以下のコマンドを叩く。
コンテナの立ち上げをするためここは時間がかかる。
ここでデプロイされるのはdocker-composeなので注意する。

```
heroku container:push web
```

※注意
webの部分がdocker-composeのserviceで付けた名前のことだと思ってappとしていてずっとエラーで詰まっていた。結論としては`web`がbackendを表示させるためのdefaultの設定らしいので変更できないとのこと。

###⑤herokuでdockerコンテナを起動する
ついにherokuでコンテナを起動する。

```:terminal
heroku container:release web
```

###⑥herokuでアプリの確認
以下のコマンドで実際にアプリが立ち上がってるページへ転移することが出来る。

``` :terminal
heroku open
```

###⑦herokuのログの確認
⑥でAppliaction Errorが起きた際などにどのようなエラーが起きていたか、backendの処理がきちんとできているか以下のコマンドでlogを確認することが出来る。

```:terminal
heroku logs --tail
```

###⑧herokuのサーバーの停止と再起動
サーバーの片付けと再起動は以下のコマンドを叩く。
web=0or1で管理できるのは非常に簡易的だ。

```:terminal
#サーバーの停止
heroku ps:scale web=0

#サーバーの再起動
heroku ps:scale web=1
```

以下のコマンドでサーバーが起動しているかどうか確認できる。

```:terminal
heroku ps
```

### ⑨herokuのapikeyの作成
以下のコマンドでapikeyが作成できる。

```
heroku authorizations:create
```

# つまづいたところ
以下のエラーでつまづいた。
## Web process failed to bind to $PORT within 60 seconds of launch

```
Web process failed to bind to $PORT within 60 seconds of launch
```

[stackoverflow](https://stackoverflow.com/questions/15693192/heroku-node-js-error-web-process-failed-to-bind-to-port-within-60-seconds-of)の回答によると、herokuでは動的にポートが割り当てられるためポートに固定値を設定しようとしたために起きたエラーとのこと。
そのため、私の場合flaskのapp.runの部分を以下のように書き直した。
このように記述することで環境変数からポートを見た後に、ない場合に5000番ポートへルーティングするような処理にすることが出来る。

```:app.py
#before
app.run(debug=True, host='0.0.0.0',
            port='5000')

#after
app.run(debug=True, host='0.0.0.0',
            port=int(os.environ.get('PORT', 5000)))

```

# CircleCIによる自動デプロイ
CircleCIの自動デプロイには位置からworkflowを作成するのではなく、CircleCI Orbsを使用した。

CIrcleCI Orbsはherokuで言えば、herokuへのログインやherokuへのコンテナのpushなどあらかじめ必要な動作を`一連のまとめとして使い回せるようにしたもの`で、Orbsを使用することで簡単にCircleCIのherokuの自動デプロイを達成することが出来る。

CircleCIのせっていの流れは以下のようになる。

**①CircleCIの公式サイトよりsetupをする**

**②CircleCI Orbsよりherokuのデプロイに使用できそうなorbsを探す**

**③.circleci/config.ymlの作成**

**④CircleCIの環境変数の設定**

**⑤githubのリポジトリへpushする**

### ①CircleCIの公式サイトよりsetupをする
まずCircleCIの公式サイトにGithubと連携してログインを済ませる。すると、サイドバーからProjectを選択でき、以下の写真の様な画面になるので`Set Up Project`を押してsetupを開始する。
`Unfollw  Project`はすでにCircleCIの設定が完了しているProjectである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/e569473b-69e3-6ffa-ef31-005d86d2380e.png)

そして以下の画面の中心部分にある青いボタンのCommit and Runを押してsetupを完了する。
※はじめにサンプルのciが起動するが気にしなくて良い。

### ②CircleCI Orbsよりherokuのデプロイに使用できそうなorbsを探す
[CircleCIの検索ページ](https://circleci.com/developer/orbs)へ行き、`heroku docker`などの検索ワードで使用できそうなorbsを探す。

今回私は、[pbrisbin/heroku-container@1.0.0](https://circleci.com/developer/orbs/orb/pbrisbin/heroku-container)を使用した。

JobsとCommandsの部分で自分で設定しなければならない。
今回使用するorbsでは以下の写真のようにapp-nameがひつようなのがわかる。

`✅となっている部分が自分で設定しなければならない変数となっている。`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/fa6870e2-a3cb-8d79-ed00-eb8146651b4b.png)

また、自分でProjectに設定しなければならない環境変数がある。
環境変数については何が必要かわかりづらいもので注意が必要。
今回は以下のようにloginでHEROKU_EMAILとHEROKU_API_KEYが必要なのがわかる。

`Environment variable`でページ内検索すると分かる可能性があるので ⌘+F でEnvironment variableで検索するのが良いだろう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/8716b4a3-b1d9-220c-5a83-5b82e1337526.png)

### ③.circleci/config.ymlの作成
CircleCIはgithubリポジトリの.circleci/config.ymlをもとに実行されるので作成する。
まず以下のコマンドで.circleci/config.ymlを作成する。

```:terminal
mkdir .circleci
touch .circleci/config.yml
```

次に以下のようにconfig.ymlを記述する。
※ version2.1以上でないとorbsが使えないので注意
これでmasterブランチへpushされたときにherokuへ自動デプロイが実行される。

```
version: 2.1
orbs:
  heroku-container: pbrisbin/heroku-container@1.0.0
workflows:
  build_and_release:
    jobs:
      - heroku-container/push-and-release:
          app-name: herokuの②で設定したapp名
          # masterブランチへのpushでのみ反応
          filters:
                branches:
                    only:
                    - master

```

### ④CircleCIの環境変数の設定

CircleCIの②で述べたようにHEROKU_EMAILとHEROKU_API_KEYという環境変数が必要になるのでProjectのページに移動し以下の画像の右上のProject Settings→Environment Variables→Add Environment  Variablesより環境変数を設定する。
※apikeyはherokuの⑨で作成したものを利用する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/f4ddfff1-e45a-ab96-e9cc-e25ee0002219.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/6131f8c5-cbaf-215a-dc07-fc84573b7c48.png)

###  ⑤githubのリポジトリへpushする

最後にgithubのリポジトリにpushしてCircleCIのProjectより起動しているか確認します。
以下のようにSuccessになっていれば大丈夫です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/4079b383-0f4a-8032-d671-fbab06d456d2.png)

# つまったところ
## To use this orb, an organization admin must opt-in to using third party orbs in Organization Security settings.

以下のエラーはorbsが使える設定になっていないために起こっている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/60518941-ed33-e7dd-441b-ede8e7735ab5.png)

そのため、以下の手順をふむ。
`Dashboard → Organization Settings → Security → Orb Security SettingsをYesに変更`

これでorbsが使えるようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/ebab730a-5816-c108-231e-9584707a0bc8.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656158/96902e72-2b42-532a-5c41-c400bdcf4990.png)




# 参考文献
・[Heroku + node.js error (Web process failed to bind to $PORT within 60 seconds of launch)](https://stackoverflow.com/questions/15693192/heroku-node-js-error-web-process-failed-to-bind-to-port-within-60-seconds-of)

・[Orbsの概要](https://circleci.com/docs/ja/2.0/orb-intro/#:~:text=CircleCI%20Orbs%20%E3%81%AF%E3%80%81%E3%82%B8%E3%83%A7%E3%83%96%E3%80%81%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89,%E3%82%82%E6%8F%90%E4%BE%9B%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)

・[pbrisbin/heroku-container@1.0.0](https://circleci.com/developer/orbs/orb/pbrisbin/heroku-container)

・[CircleCIの検索ページ](https://circleci.com/developer/orbs)