HerokuにPython・Flaskのアプリをデプロイする際にハマりうる点一覧

## 概要

2021 ～ 2024 年に、Python と Flask で作った Web アプリを Heroku に 4 個デプロイしました。
その際に**ローカルでは正常に動いたのにインターネットに (Heroku で) うまく公開できない**ということがよくありました。
そのような Heroku 周りでハマってしまった点・初見だと難しい点・気を付けるべき点についてまとめました。
原理や理由は詳しく書かず、するべきことに絞っています。詳しくはキーワードで検索してみてください。

## エラーの確認方法

Heroku のログを見ることでの基本的なエラーの確認方法です。

- 各デプロイでのエラー: ダッシュボードの Latest activity の「View build log」から (画像の A)
- 全体のログ (簡易): 右上「More」の「View logs」から (画像の B)
- 全体のログ (詳細): コマンド `heroku logs --tail` を実行

上から試すことをお勧めします。「Build succeeded」の表示があっても、詳細なログで見るとエラーが見つけられたりします。

![スクリーンショット 2024-12-25 175944.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420990/b5a73772-f65f-3d6c-18aa-e12eb4e10234.png)


## ハマりうる点一覧

### `requirements.txt` の整備
`requirements.txt` に、ローカルで使っているライブラリ (pip でインストールしたもの) をすべて書く。
以下のコマンドで簡単に作成できる。(リポジトリ直下で実行する)

`pip freeze > requirements.txt`

ファイル名のスペルミス (複数形の s を忘れる等) に注意。
**中身を確認し「`gunicorn`」と「`Flask`」が無い場合は追記する。**


### Python のビルドパックを指定
Settings タブから指定。
Python のアイコンをクリックする。heroku/python が選ばれるはず。

参考
https://qiita.com/taku_hito/items/52c6c52385386544aa62
https://qiita.com/kero269/items/5289257b0bec6614f1ed

![スクリーンショット 2024-12-25 175435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420990/407f66bf-d35b-750f-9bbe-67ef0d8eb8a2.png)


### リポジトリと Heroku サーバを紐づける操作をする
以下のコマンドをローカルリポジトリ直下で実行する

`heroku git:remote -a (Heroku でのリポジトリ名)` 

後述の GitHub からの自動デプロイ設定をしている場合でもやる必要がある。
そもそも `heroku` コマンドが効かない場合は、インストールする・パスを通す必要がある。

### `Procfile` の作成
中身は 1 行だけ、以下のように書いてリポジトリ直下に置く

`web: gunicorn (メインの python ファイル名):app --log-file=-`

以下は、メインの python ファイル (`app = Flask(__name__)` が書いてあるファイル) が `main.py` の例

```:Procfile
web: gunicorn main:app --log-file=-
```

### アプリに対して計算資源 (dynos) を割り当てる

`code=H14 desc="No web processes running"` のエラーが出た場合など。
以下のコマンドを実行。

`heroku ps:scale web=1`

1個目のアプリの初デプロイの際だけやればいいかも？
参考: https://qiita.com/rebi/items/efd1c36f0a9e46222d80

### Python のバージョン指定

ローカルと Heroku の Python バージョンが違うと以下のようなエラーが起きたりする。
`ModuleNotFoundError: No module named 'distutils'`
(distutils は python 3.11 まで存在したが 3.12 で廃止されたライブラリ。`requirements.txt` に書いてもうまくいかない。)

Heroku の Python バージョンは、指定しないと最新のものになる
指定する場合は `.python-version` ファイルに以下のように書いてリポジトリ直下に置く
([英語版公式ドキュメント](https://devcenter.heroku.com/articles/python-runtimes))

```:.python-version
3.12
```

[日本語版公式ドキュメント](https://devcenter.heroku.com/ja/articles/python-runtimes)には `runtime.txt` で指定する方法が書いてあるが、2024年12月に試してうまくいかなかった。変わったのかもしれない。

```:runtime.txt
python-3.12.4
```

### GitHub の自動デプロイを使っている場合は、設定の確認

GitHub の main ブランチにプッシュすることで自動的に Heroku にもデプロイされるようにしたい場合は、「Deployment method」で GitHub を選択するだけでなく、下の「Automatic deploys」の設定もする必要がある

![スクリーンショット 2024-12-25 175633.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420990/2f7d05da-5813-9155-b077-281db72fc04a.png)

### 画像処理をしている場合、ライブラリの設定を変更

Python の画像処理ライブラリ (`cv2` など) を使っている場合、以下のようなエラーが出る
`ImportError: libGL.so.1: cannot open shared object file: No such file or directory`
Heroku の環境には OpenCV を使うために必要な OS レベルの動的ライブラリ (libGL など) が入っていないことが原因。

OpenCV の GUI 関連機能 (imshow など) を使っているかどうかで対処法が変わるらしい。
よくわからない場合は「使っていない場合」を先に試しダメなら「使っている場合」を試すのがよい。

#### 使っていない場合

`requirements.txt` の `opencv-python` を `opencv-python-headless` に書き換える。

#### 使っている場合

1. コマンド実行: `heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-apt`
1. リポジトリ直下にファイル `Aptfile` を作り、必要なライブラリを書く

```:Aptfile
libgl1-mesa-glx
libglib2.0-0
```

## 終わりに

ここにないエラーに遭遇しても、今や ChatGPT 等の生成 AI にエラーメッセージを貼ると割と的確に教えてくれます。

宣伝になりますが、ここまでのスクリーンショットに例として使用したアプリは以下のものです。
新型コロナ等の検査キットを使った結果、薄いラインがあるように見える場合に、輝度グラフで可視化し、陽性・陰性の判定を補助します。

https://kensa-hantei-802eb44db172.herokuapp.com/