日本語諸方言コーパスをDB化して遊ぶ (9) Heroku でデプロイする

連載記事です。前回までに機能はだいたい作ったので、今回は本番環境 Heroku でビルドしていきます。完全に自分用の作業メモで、説明もいろいろ足りていないと思いますが、ご容赦ください。

- 第１回： [日本語諸方言コーパスをDB化して遊ぶ (1) 構成を考える](https://qiita.com/a_eau_/items/dcb83886c4b580565ce7)
- 第２回： [日本語諸方言コーパスをDB化して遊ぶ (2) SQLite3 で DB 化](https://qiita.com/a_eau_/items/0bb4f3f8271c6dbc12a5)
- 第３回： [日本語諸方言コーパスをDB化して遊ぶ (3) PHP Laravel で操作する](https://qiita.com/a_eau_/items/09f648ede77fd22e7585)
- 第４回： [日本語諸方言コーパスをDB化して遊ぶ (4) サービスの全体像を決める](https://qiita.com/a_eau_/items/0af125f960dd1d16fcde)
- 第５回： [日本語諸方言コーパスをDB化して遊ぶ (5) データベースの移行とモデルの作成](https://qiita.com/a_eau_/items/3cad488add22bfacfeaa)
- 第６回： [日本語諸方言コーパスをDB化して遊ぶ (6) 談話ごとの発話総覧を作る](https://qiita.com/a_eau_/items/2a7072e3cab4729623cb)
- 第７回： [日本語諸方言コーパスをDB化して遊ぶ (7) 話者ごとの発話総覧を作る](https://qiita.com/a_eau_/items/ccb472a0fc2ac6ca9919)
- 第８回： [日本語諸方言コーパスをDB化して遊ぶ (8) ファイル形式変換機能をつける](https://qiita.com/a_eau_/items/3f196631348fec1cfc8d)
- 第９回： 日本語諸方言コーパスをDB化して遊ぶ (9) Heroku でデプロイする　←今ここ

以下の記事を大いに参考したうえで、今回のプロジェクトに特化していきます。

- [Laravel5.4 + Vuejsのアプリをherokuで公開する手順 | Qiita](https://qiita.com/naoki0531/items/c4de80efd35199682ac3)
- [Laravel（Vueあり）でローカル開発〜herokuデプロイするまで | Qiita](https://qiita.com/dai_designing/items/6925ba1b1885377b5714)

## heroku app の作成と git 管理
[第５回](https://qiita.com/a_eau_/items/3cad488add22bfacfeaa)で既に heroku app の作成自体は済ませているので、ここではローカルリポジトリと heroku 上のリモートリポジトリを連携させます。

- [Deploying with Git | Heroku Dev Center](https://devcenter.heroku.com/articles/git)

```cmd:cmd
git init
git add .
git commit -a -m "first commit"
heroku git:remote -a my-app-name 
```

## buildpack の設定
今回は PHP Laravel のプロジェクトですが、Node.js と Python も使うのでこいつらも buildpack に含めておきます。Heroku のプロジェクトページからポチポチ追加してもいいでしょう。

```cmd:cmd
heroku buildpacks:set heroku/php -a my-app-name
heroku buildpacks:add heroku/python -a my-app-name
heroku buildpacks:add heroku/nodejs -a my-app-name
```

## Procfile の作成
heroku ではプロセス管理に foreman というツールを使っています。この foreman が読み込んで使う設定ファイルが **Procfile** で、管理すべきプロセスを定められた書式で記述したものです。ここではルートに拡張子なしの `Procfile` というファイルを作成して、以下のように記述します（heroku においては `web` というプロセス名が特別な扱いを受けるようです）。無難に Apache を使えばよいでしょう。

- [foreman について | 君の瞳はまるでルビー - Ruby 関連まとめサイト](https://www.ownway.info/Ruby/foreman/about)
- [foreman で アプリケーションを動かす。 | Qiita](https://qiita.com/7kaji/items/6a59977d2ad85604e7fd)
- [Herokuに必要なProcfileの書き方についてまとめておく | ハイパー猫背](https://creepfablic.site/2019/06/15/heroku-procfile-matome/)

```:Procfile
web: vendor/bin/heroku-php-apache2 public/
```

## Python 用 requirement.txt の作成
使用する python スクリプトが `xlrd` などの非標準モジュールを利用する場合は、ルートに python 用の `requirement.txt` を用意しておくと、ビルド時に勝手にインストールしてくれます。今回は `pip freeze > requirements.txt` で現在インストールされているモジュールをすべて書き出して、そこから不要なものを削除して作成しました。

- [requirements.txtを作成するには？ | it-swarm.dev](https://www.it-swarm.dev/ja/python/requirementstxt%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%EF%BC%9F/1052022642/)

使用する Python のバージョンを指定したい場合は `runtime.txt` を作成すればよいようです。

- [Herokuにデプロイしよう（PythonAnywhereだけでなく） | Django Girls Tutorial: Extensions](https://tutorial-extensions.djangogirls.org/ja/heroku/)

## 環境変数の設定
ローカルの `.env` は `.gitignore` で push 対象から外してあるはずですので、DB 関連の環境変数は heroku に手動で追加していきます。接続には時間がかかるのでワンライナーで終わらせましょう（バッククォートは無改行を示す）。

```cmd:cmd
heroku config:set DB_CONNECTION=pgsql `
DB_HOST=*** `
DB_PORT=*** `
DB_DATABASE=*** `
DB_USERNAME=*** `
DB_PASSWORD=*** `
DATABASE_URL=postgres://***
```

ついでに以下の要素も設定しておきます。`APP_KEY` は `php artisan key:generate` で発行するものですが、たぶん composerにより既に設定されているので .env からのコピペでよいでしょう。

```cmd:cmd
heroku config:set APP_NAME=my-app-name `
APP_KEY=***  ` 
APP_URL=https://my-app-name.herokuapp.com  
```

## composer.json の変更
基本的に `heroku run` コマンドによる実行ではルート権限は行使できませんが、`composer.json` 内の scripts->compile にコマンドを書いておくとビルド時にルート権限で実行してくれます。ここでは、python スクリプトに実行権限を与え、`/storage` フォルダ以下に読み書き権限を与え、シンボリックリンクを張ります[^symbolic]。

[^symbolic]: シンボリックリンクは `heroku run php artisan storage:link` でも貼れると思いますが、試していないので分かりません。

```json:composer.json
{
    "scripts": {
        "compile": [
            "chmod +x app/Python/textgrid_to_excel.py",
            "chmod +x app/Python/excel_to_textgrid.py",
            "chmod --recursive 775 storage/app",
            "ln --symbolic --relative storage/app/public public/storage"
        ]
    }
}
```

- [How can I give permissions to specific folders on heroku? | stackoverflow](https://stackoverflow.com/questions/36455888/how-can-i-give-permissions-to-specific-folders-on-heroku)

## .htaccess の変更
シンボリックリンクを有効にするために `.htaccess` の Option に以下を追記します。`Option +somesetting` で機能を有効化、`Option -somesetting` で無効化する書式です。

```:public/.htaccess
Option +FollowSymlinks
```

- [Laravel 5.4 --> forbidden 403 on files in Storage with 'public' visibility | stackoverflow](https://stackoverflow.com/questions/44247272/laravel-5-4-forbidden-403-on-files-in-storage-with-public-visibility)


## コンパイルのタイミング
Laravel プロジェクトは `npm run dev` や `npm run production` のようなコマンドでコンパイルされますが、既定ではコンパイルされた `/public/js` と `/public/css` は git の push 対象から外れていると思うので、開発環境でコンパイルしたものをそのまま使う場合は `.gitignore` から外しておきましょう。うっかりするとどこにもコンパイル済みファイルが存在しない状態が発生しエラー[^syntax]の原因になります。

[^syntax]: 404 や 500 ではなく、ファイルの参照がおかしくなって `Syntax error : unexpected token '<'` みたいなのが出る。

```diff:.gitignore
- /public/js
- /public/css
```

- [Laravel（Vueあり）でローカル開発〜herokuデプロイするまで | Qiita](https://qiita.com/dai_designing/items/6925ba1b1885377b5714#%E8%A3%9C%E8%B6%B3)


## デプロイ
設定がすべて終わったらデプロイします。上の操作で heroku app を作成して git と連携させていれば、master（もしくは main）ブランチを `git push` するだけで勝手にビルド・デプロイしてくれます。それ以外のブランチにはそういうトリガーが設定されていないので、あえてビルドしたいときは公式を参照してください。

- [Deploying with Git | Heroku Dev Center](https://devcenter.heroku.com/articles/git)

```cmd:cmd
git push heroku master
```

## おわりに
Docker なんかを利用していたら、本記事で詰まった点はある程度素通りできたのではないかと思いますが、本記事の扱う領域は筆者自身勉強し始めたばかりですので、よくわかりません（近いうちに勉強します）。

- [最強のLaravel開発環境をDockerを使って構築する【新編集版】 | Qiita](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)
- [Dockerで作成したRailsアプリをHerokuにデプロイ | Qiita](https://qiita.com/NA_simple/items/57ad10717568fea2160b)

また、本記事も含めて本連載の内容は試行錯誤してたどり着いたものですので、無駄な工程や書き洩らしている工程、不適切な説明がたくさんあると思います。指摘していただけると喜びます。