AWSにデプロイしたポートフォリオをHerokuへ移行しようとしたらかなり苦労した

# 1.はじめに
以前僕は転職活動を行った際に、AWSにデプロイしたポートフォリオを作成しました。
自分なりに頑張って作ったアプリなので、折角だから今後も見れる形で残したいと思いました。
しかし、AWSで公開し続けると、課金が発生してしまいます。
僕の場合は、毎月6500円～7500円くらいかかっていました。（もったいない😂）
そこで、無料で利用できるHerokuにデプロイしようと考えました。
AWSからHerokuへの移行作業で、色々と躓いた点があるので、書き残しておきます。

# 2.URL
### ポートフォリオ
##### AWSデプロイURL（公開停止しました）

~~https://koujigenba.site~~

↓移行

##### HerokuデプロイURL（起動に少し時間がかかります）

https://koujigenba.herokuapp.com

### GitHub

https://github.com/yuuhei-koutoku/cts-remake

### ポートフォリオ紹介記事

https://qiita.com/Yuhei_K/items/06805f3ac8607f77952f

# 3.躓いたところ（エラーや不具合）
### (1)サブディレクトリをHerokuへプッシュ
GitHubのディレクトリ構造はこのようになっています。

```
cts-remake/
 ├diagram/   ER図、インフラ構成図のdraw.ioデータと画像が格納されているディレクトリ
 ├docker/    Docker関連のファイルが格納されているディレクトリ
 ├src/       ポートフォリオのソースコード（主にPHP・Laravel）
 ├.gitignore
 ├README.md
 └docker-compose.yml
```
Herokuへのプッシュは通常下記のコマンドでできます。

```
$ git push heroku master
```
しかし、今回はsrcディレクトリのみプッシュしたい状況でした。
理由は下記の2点です。

- srcディレクトリをHerokuサーバー内では最上位に位置したいから
- Docker・draw.io関連のファイルは必要無いから

そこで、下記コマンドでサブディレクトリをHerokuへプッシュします。

```
$ git subtree push --prefix <サブディレクトリ名>/ heroku master
```
上記コマンドでsrcディレクトリのみをHerokuサーバーへプッシュすることができました！

### (2)Nginxの設定ファイルを作成
(1)でプッシュできたので、Herokuのデプロイ先URLへアクセスはできたのですが、トップページから別ページ（アカウント作成とログイン）へ移動すると`404 Not Found nginx`になってしまいました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/32c6a127-9ae6-0498-cdfa-f073093004e7.png)
原因はWebサーバーでした。
ローカルではNginxを使用しており、`src/docker/nginx/defalt.conf`に設定ファイルを記載しています。
ただ、srcディレクトリのみをプッシュしてしまったせいで、Herokuサーバー内にNginxの設定ファイルがない状態になっています。
Herokuサーバー内にもNginxの設定ファイルを作成する必要があるので、[Herokuリファレンス](https://devcenter.heroku.com/ja/articles/custom-php-settings#nginx)を参考にしつつ、Herokuサーバールートディレクトリ（srcディレクトリ直下）に`nginx_app.conf`を作成し、下記のように編集しました。

```conf:src/nginx_app.conf
location / {
    # try to serve file directly, fallback to rewrite
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    # rewrite all to index.php
    rewrite ^(.*)$ /index.php/$1 last;
}

location ~ ^/index\.php(/|$) {
    try_files @heroku-fcgi @heroku-fcgi;
    # ensure that /index.php isn't accessible directly, but only through a rewrite
    internal;
}
```

### (3)`Procfile`の作成
Heroku上でLaravelアプリケーションを動かすには`Procfile`というものが必要です。
配置場所は`nginx_app.conf`と同じ（Herokuサーバールートディレクトリ）です。
通常は`web: vendor/bin/heroku-php-nginx public/`（apacheの場合は`web: vendor/bin/heroku-php-apache2 public/`）で問題ないと思いますが、今回は独自の`nginx_app.conf`を記述したため、[Herokuリファレンス](https://devcenter.heroku.com/ja/articles/custom-php-settings#nginx)に従い下記のように編集します。

```
web: vendor/bin/heroku-php-nginx -C nginx_app.conf public/
```
これで、トップページ以外のページへ遷移させることができました！

### (4)CSSファイルが適用されない
残念ながら、まだまだ不具合が残っていました😂
ページ全体を通して、CSSファイルが適用されていませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/9095fd50-87c9-2871-bb21-ef8a2ada9911.png)
CSSファイルは全て`src/public/css/app.css`に記載しています。
試しにHerokuサーバー内で`app.css`を確認してみました。

```
$ heroku run bash
Running bash on ⬢ koujigenba... up, run.5498 (Free)
~ $ less public/css/app.css
```
結果は空でした。
また、Herokuデプロイ先でも「ページのソースを表示」で確認したところ、同じく空であることが確認できました。
##### public/cssディレクトリ内のファイルが反映されているか確認
CSSが適用されない不具合の解消の一歩目として、同じディレクトリ内に別のファイルを作成し、デプロイ先で反映されるか検証しました。
`$ touch src/public/css/test.css`で`test.css`を新規作成し、ファイルの中身を適当に編集します。

```css:src/public/css/text.css
h1 {
  text-align: center;
}
```
Herokuへプッシュ後、ソースの確認を行って`test.css`が反映されているか確認します。
デプロイ先のページを開いて右クリックをし、「ページのソースを表示」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/853fe6c2-4067-4cee-d0ab-c01a152268d6.png)
ソースコードが表示されるので、CSSファイルが読み込まれいるリンクをクリックします。
![srccode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/3ed8b537-baea-1318-0d38-99e9dde4a601.png)
アドレスバーに表示されているURLを`app.css`から`test.css`に修正します。
![textcss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/8a74510f-2e1e-7d16-f18d-b33e672cbbbe.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/0550880c-e79a-a606-5c0e-f17498bb281d.png)
`test.css`が反映されていることが確認できました！

##### `public/app.css`の内容を反映する
この状況から2つの仮説を立てました。

- [1]`app.css`というファイル名がNG
- [2]`app.css`の容量が大きすぎる

[1]を確認するため、`app.css`を`all.css`にリネームし、`app.css`の読み込みを行っている箇所を`all.css`に修正しました。

```css:src/resources/views/app.blade.php
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>
        @yield('title')
    </title>
    @if(config('app.env') === 'production')
        <link rel="stylesheet" href="{{ secure_asset('css/all.css') }}"> <!-- ここを修正 -->
    @else
        <link rel="stylesheet" href="{{ asset('css/all.css') }}"> <!-- ここを修正 -->
    @endif
```
再度Herokuへプッシュすると、CSSが無事に反映されていました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/2557ede7-4c8e-545a-84cb-c21c11845127.png)
`app.css`というファイル名がなぜ使えなかったのかは謎です......

### (5)AWSの環境変数を設定
ポートフォリオには画像投稿機能が実装されています。
試しに画像を添付して投稿したのですが、`500 | Server Error`になってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/c971460e-f380-3eb3-4729-2fc455263aa1.png)
画像はAWSのS3バケットに保存しています。
Heroku上で、AWSのアクセスキーやS3バケットなどの登録を忘れていました💦
Setting→Config Vars→Reveal Config Varsで設定できます。
![heroku_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/e8628b51-c03d-bfd3-46cd-76afd9cfa3c1.png)
`.env`に記載されている内容をそのままHerokuにコピペすればOKです。

※環境変数に`LOG_CHANNEL=errorlog`を設定していない方は、追加しておくことを推奨します。
　設定しておくと、エラー発生時に詳細なログが表示できるようになります。

### (6)`nginx_app.conf`に追記
再度画像を投稿してみたところ、`413 Request Entity Too Large`になってしまいました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/d05d4b49-5535-37f2-6c70-c6dcc232e06b.png)
画像ファイルの容量が大きすぎるみたいです。
[こちら](https://stackoverflow.com/questions/30538196/heroku-nginx-http-413-entity-too-large)を参考に、`nginx_app.conf`に追記して解消しました。

```conf:src/nginx_app.conf
client_max_body_size 10M; #追記箇所

location / {
    # try to serve file directly, fallback to rewrite
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    # rewrite all to index.php
    rewrite ^(.*)$ /index.php/$1 last;
}

location ~ ^/index\.php(/|$) {
    try_files @heroku-fcgi @heroku-fcgi;
    # ensure that /index.php isn't accessible directly, but only through a rewrite
    internal;
}
```

### (7)拡張モジュールGDを追加
再々度画像を投稿してみました。
また`500 | Server Error`が発生しました。
マジか、、、😰
Herokuのログを確認したところ、このように記載されていました。

```
2022-02-20T00:06:21.999688+00:00 app[web.1]: [20-Feb-2022 09:06:21 Asia/Tokyo] [2022-02-20 09:06:21] production.ERROR: GD Library extension not available with this PHP installation. {"userId":4,"exception":"[object] (Intervention\\Image\\Exception\\NotSupportedException(code: 0): GD Library extension not available with this PHP installation. at /app/vendor/intervention/image/src/Intervention/Image/Gd/Driver.php:19)
```
`ERROR: GD Library extension not available with this PHP installation.`
拡張ライブラリのGDがインストールされている必要があるそうです。
[こちら](https://swan-once.com/how_to_php-gd_heroku)を参考に、`composer.json`に追記しました。

```json:src/composer.json
    "require": {
        "php": "^7.2.5",
        "fideloper/proxy": "^4.4",
        "intervention/image": "^2.5",
        "laravel/framework": "^6.20",
        "laravel/tinker": "^2.5",
        "league/flysystem-aws-s3-v3": "~1.0",
        "ext-gd": "*" <-追記
```
その後、`$ composer update`を行うことで、GDがインストールされます。

### (8)Windowsセキュリティ Git Credential Manager
拡張モジュールのGDを追加後、Herokuへプッシュしたら、このような画面が表示されました。
![スクリーンショット 2022-02-20 095538.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935364/ca775387-27d1-33e4-a8e8-dbb008557dd5.png)
なんだこれ？
GitHubやHerokuのユーザー名とパスワードを入力しても、うまくいきません。

```
git push using:  heroku master
remote: !       WARNING:
remote: !       Do not authenticate with username and password using git.
remote: !       Run `heroku login` to update your credentials, then retry the git command.
remote: !       See documentation for details: https://devcenter.heroku.com/articles/git#http-git-authentication
fatal: Authentication failed for 'https://git.heroku.com/koujigenba.git/'
```
なぜ急にできなくなったのでしょうか？
[こちら](https://web.plus-idea.net/2017/04/heroku-app-pushauth-error)の情報をもとに、`$ heroku auth:token`でAPIトークンを確認後、Herokuをプッシュしたところ成功しました。（Windowsセキュリティの画面は表示されませんでした。）
これでようやく正常にHerokuデプロイができました！
最後にデモデータを移行して完了しました😁

# 4.おわりに
WebアプリケーションをHerokuへデプロイは既に1回経験していたので、楽勝だろと思っていましたが、かなり苦戦してしまいました。
最後は無事に移行できたので良かったです😊
実は[MENTA](https://menta.work)を通じて、エラー・不具合解決の助言をいただいたりしていました。
1人では解消できなかったので、本当に助かりました！
メンターさんありがとうございましたm(._.)m
LaravelアプリケーションをAWSからHerokuへデプロイし直す方の参考になれば幸いです^^

# 5.参考URL
- [Herokuリファレンス](https://devcenter.heroku.com/ja)
- [Heroku Nginx HTTP 413 entity too large](https://stackoverflow.com/questions/30538196/heroku-nginx-http-413-entity-too-large)
- [HerokuでPHP拡張モジュールのGDを使う方法](https://swan-once.com/how_to_php-gd_heroku)
- [Herokuにアプリをpushしたときにエラーが出る場合の対処法](https://swan-once.com/how_to_php-gd_heroku)