PhoenixアプリをHerokuにデプロイする

HerokuもPhoenixに対応しています。
今回は下記Docを参考にPhoenixアプリ（LiveView）をHerokuにデプロイしていきます。

https://hexdocs.pm/phoenix/heroku.html#optional-node-npm-and-the-phoenix-static-buildpack

筆者の環境のバージョンは下記のとおりです。

```
$ mix phx.new --version
Phoenix installer v1.6.5

$ elixir --version
Erlang/OTP 24 [erts-12.1.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

Elixir 1.12.3 (compiled with Erlang/OTP 24)
```

## Heroku is 何？

Herokuは、アプリケーションの開発から実行、運用までのすべてをクラウドで完結できるPaaSです。

https://jp.heroku.com/

アカウントは無料で作成できます。

![スクリーンショット 2022-01-10 1.07.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/043f87c2-d4ba-ab53-680e-5fbfb798e65f.png)

ちなみにFreeプランは30分間のアイドル状態でスリープ、無料dyno(=コンテナ)時間の残量に応じて利用可能だそうです。
常時稼働させたい場合は$7/dyno/月のHobbyプランが一番安価です。

https://jp.heroku.com/pricing

## Phoenixアプリを作成する

DBはPhoenixのデフォルトかつherokuのデフォルトのPostgreSQLがおすすめです。
また、Phoenixはsqllite3に対応していますが、Herokuは対応していないので注意しましょう。

```ssh
$ mix phx.new test_deploy_heroku
...
We are almost there! The following steps are missing:

    $ cd test_deploy_heroku

Then configure your database in config/dev.exs and run:

    $ mix ecto.create

Start your Phoenix app with:

    $ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phx.server
```

DBを作成します。

```
$ mix ecto.create
The database for TestDeployHeroku.Repo has been created
```

### LiveViewページを追加

`mix phx.gen.live`でLiveViewページを追加します。

`mix phx.gen.live [コンテキストモジュール名]　[スキーマモジュール名]　[スキーマテーブル名]　[カラム名:型]`

```ssh
$ mix phx.gen.live Messages Message messages contents:text
...
Add the live routes to your browser scope in lib/test_deploy_heroku_web/router.ex:

    live "/messages", MessageLive.Index, :index
    live "/messages/new", MessageLive.Index, :new
    live "/messages/:id/edit", MessageLive.Index, :edit

    live "/messages/:id", MessageLive.Show, :show
    live "/messages/:id/show/edit", MessageLive.Show, :edit

Remember to update your repository by running migrations:

    $ mix ecto.migrate
```

LiveViewページ追加後のメッセージどおり、ルーター設定を書き換えます。

```lib/test_deploy_heroku_web/router.ex
defmodule TestHerokuWeb.Router do
  use TestHerokuWeb, :router
  ...
  scope "/", TestHerokuWeb do
    pipe_through :browser

    live "/messages", MessageLive.Index, :index # ←追記
    live "/messages/new", MessageLive.Index, :new # ←追記
    live "/messages/:id/edit", MessageLive.Index, :edit # ←追記

    live "/messages/:id", MessageLive.Show, :show # ←追記
    live "/messages/:id/show/edit", MessageLive.Show, :edit # ←追記

    get "/", PageController, :index
  end
  ...
```

LiveViewページ追加後のメッセージどおり、DBのマイグレーションをします。

```ssh
$ mix ecto.migrate
```

`mix phx.server`でPhoenixアプリを起動し、
`http://localhost:4000/messages`が表示されればOKです。

## Herokuデプロイ

### Githubにリポジトリを作成、 git pushする

今回はHerokuへのソースコードのデプロイはGithub経由にします。

Githubリポジトリの作成〜git pushまでは端折ります。

作成したPhoenixアプリを作成したGithubリポジトリにpushします。

### Heroku CLIのインストール

Herokuアプリをターミナルから操作するためにHeroku CLIをインストールします。

https://devcenter.heroku.com/ja/articles/heroku-cli

macの場合はhomebrewでインストールできます。
（Windows、Ubuntuは上記のページを参照してください）

```ssh
$ brew tap heroku/brew && brew install heroku
```

インストールが終わったらバージョンを確認しましょう。

```ssh
$ heroku --version
```

### Heroku app(デプロイ環境)作成

ターミナルからHerokuにログインします。

```ssh
$ heroku login
```

Heroku app(デプロイ環境)を作成します。
Phoenixアプリは`--buildpack hashnuke/elixir`を指定します。

```ssh
$ heroku create --buildpack hashnuke/elixir
```

`heroku create`するとgitのリモートにherokuが追加されることが確認できます。

```
$ git remote -v
heroku	https://git.heroku.com/thawing-island-32594.git (fetch)
heroku	https://git.heroku.com/thawing-island-32594.git (push)
origin	git@github.com:kn339264/test_deploy_heroku.git (fetch)
origin	git@github.com:kn339264/test_deploy_heroku.git (push)
```

### Heroku用デプロイ用設定を追加

Phoenixのdoc通り、`elixir_buildpack.config`をPhoenixアプリのルートディレクトリに作成します。
Elixir、Erlangのバージョンとesbuildでのアセットのビルドコマンドを指定します。

Elixir、Erlangバージョンは`elixir --version`で確認できます。

```elixir_buildpack.config
# Elixir version
elixir_version=1.12.2 # ご自身の環境のバージョンを指定してください

# Erlang version
# https://github.com/HashNuke/heroku-buildpack-elixir-otp-builds/blob/master/otp-versions
erlang_version=24.0.3 # ご自身の環境のバージョンを指定してください

# Invoke assets.deploy defined in your mix.exs to deploy assets with esbuild
# Note we nuke the esbuild executable from the image
hook_post_compile="eval mix assets.deploy && rm -f _build/esbuild*"
```

`Procfile`も同様にPhoenixアプリのルートディレクトリに作成します。
これはアプリの起動方法を指定します。

```Procfile
web: mix phx.server
```

ファイル名は`Procfile`だぞ！（以前Profileと間違えてハマりました）

### 本番環境設定の書き換え

```config/prod.exs
config :test_deploy_heroku, TestDeployHerokuWeb.Endpoint,
  url: [scheme: "https", host: "【Heroku app名】.herokuapp.com", port: 443], # 追記
  force_ssl: [rewrite_on: [:x_forwarded_proto]], # 追記
  cache_static_manifest: "priv/static/cache_manifest.json"
```

### Heroku Appに環境変数SECRET_KEY_BASEを追加

Phoenixのdoc通り、SECRET_KEY_BASEを追加します。

```ssh
$ mix phx.gen.secret
xvafzY4y01jYuzLm3ecJqo008dVnU3CN4f+MamNd1Zue4pXvfvUjbiXT8akaIF53
```

```ssh
$ heroku config:set SECRET_KEY_BASE="xvafzY4y01jYuzLm3ecJqo008dVnU3CN4f+MamNd1Zue4pXvfvUjbiXT8akaIF53"
Setting config vars and restarting mysterious-meadow-6277... done, v3
SECRET_KEY_BASE: xvafzY4y01jYuzLm3ecJqo008dVnU3CN4f+MamNd1Zue4pXvfvUjbiXT8akaIF53
```

### Heroku AppにPostgreSQLを追加

```ssh
$ heroku addons:create heroku-postgresql:hobby-dev
```

## いざデプロイ！

Herokuにブラウザからログインします。
作成したHeroku appのDeployメニューを表示、Deployment methodをGithubを選択します。
（初回はGithubの認証画面が表示されると思います）

デプロイしたいリポジトリを選択します。

下記画像はリポジトリ選択が終わった状態のキャプチャです。

![スクリーンショット 2022-01-13 20.29.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/da1f50e8-3560-c31d-57c1-0b1ad665447d.png)

リポジトリの選択が終わったら、デプロイしたいブランチを選択し「Deploy branch」ボタンをクリック。（今回はmainブランチ）
デプロイログが表示されるので完了まで待ちます。

![スクリーンショット 2022-01-13 20.29.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/94ec0f0b-a559-3e44-0ea2-7198dda93d47.png)

デプロイが終わったらターミナルからHeroku app上で`mix.migrate`を実行します。

```ssh
$ heroku run "POOL_SIZE=2 mix ecto.migrate"
```

これでデプロイは完了した…ハズ！
ターミナルから`heroku open`でデプロイしたアプリをブラウザで表示しましょう。

```ssh
$ heroku open
```

今回はLiveViewページも作成しました。
https://【heroku appのURL】/messagesも表示してみて、動くかみてみましょう。

![スクリーンショット 2022-01-16 15.00.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/20079207-58d8-ddf3-9c5c-f01b8e97081a.png)

うごいた！

## さいごに

個人利用（Free枠）の利用であればGigalixirで十分かなと思いますが、
HerokuはPipelineが使えるためGit-flowなどの開発がしやすいというメリットがあるので、状況で使い分けたいですね。