「画像でゴミ分類！」アプリ作成日誌day8～herokuデプロイ～

# はじめに
「画像でゴミ分類！」アプリ作成日誌8日目の今日はようやくデプロイしていきたいと思います。今回はPaaS(アプリケーションソフトを動かすためのデータベースや実行環境などを提供してくれるサービス)としてherokuを用いていきます。

＜記事一覧＞

- [「画像でゴミ分類！」アプリ作成日誌day1～データセットの作成～](https://qiita.com/eycjur/items/7d8223b28758c7dfaaa0)
- [「画像でゴミ分類！」アプリ作成日誌day2～VGG16でFine-tuning～](https://qiita.com/eycjur/items/3e954cb70dc15f996c2d)
- [「画像でゴミ分類！」アプリ作成日誌day3～Djangoでwebアプリ化～](https://qiita.com/eycjur/items/9c618538177c82f7fdc3)
- [「画像でゴミ分類！」アプリ作成日誌day4～Bootstrapでフロントエンドを整える～](https://qiita.com/eycjur/items/7b58c28eb8b16e722b5d)
- [「画像でゴミ分類！」アプリ作成日誌day5～Bootstrapでフロントエンドを整える2～](https://qiita.com/eycjur/items/08808097acd625e00652)
- [「画像でゴミ分類！」アプリ作成日誌day6～ディレクトリ構成の修正～](https://qiita.com/eycjur/items/f436787c2d517af6cad6)
- [「画像でゴミ分類！」アプリ作成日誌day7～サイドバーのスライドメニュー化～](https://qiita.com/eycjur/items/009dca5866c3e9ad0dd6)
- [「画像でゴミ分類！」アプリ作成日誌day8～herokuデプロイ～](https://qiita.com/eycjur/items/ebfae5db5dd1cd8349ea) ←イマココ

# はじめに
今回のデプロイではHeroku CLI（コマンドラインインターフェース）を使うのですが、せっかくなので（自分の所属している大学でなぜがlinux信者が多数いる影響もあり）、linuxコマンドが動く環境を構築してその環境下でやっていきたいと思います（こんなめんどくさいことしなくても[ The Heroku CLI ](https://devcenter.heroku.com/articles/heroku-cli)を見ればすぐダウンロードできるかと思います）。

# Ubuntuの追加
linuxコマンドが実行できるようにubuntuを入れます。
まず、ubuntuをmicrosoft storeからインストールします。
![Ubuntu](https://github.com/eycjur/garbage/blob/master/qiita_image/ps-6.png?raw=true)
次にwindows terminalをインストールします。（直接ubuntuにコマンドを書いてもいいけど、コマンドプロンプトといっしょに使えるこっちのほうが便利なので）
![windows terminal](https://github.com/eycjur/garbage/blob/master/qiita_image/ps-5.png?raw=true)

それではwindows terminalでubuntuが使えるようにします。[ Windows 10でWindowsターミナルにUbuntuタブを追加する方法 ](https://soundartifacts.com/ja/how-to/280-how-to-add-ubuntu-tab-to-windows-terminal-in-windows-10.html)を参考にして実行しました。
まず、ubuntuを開いて以下のコマンドでGUIDを取得します。

```shell
$ uuidgen
```

そしてそれを、windows terminalのタブの横にある下矢印から設定を開きprofiles内のistに以下を追加します。

```json:setting.json
            {
                "acrylicOpacity":0.75,
                "closeOnExit":true,
                "colorScheme":"Campbell",
                "commandline":"wsl.exe -d Ubuntu",
                "cursorColor":"#FFFFFF",
                "cursorShape":"bar",
                "fontFace":"Consolas",
                "fontSize":12,
                "guid":"{前述の手順で得られたGUID}",
                "historySize":9001,
                "icon":"C:/Dummy/image.png",
                "name":"Ubuntu",
                "padding":"0, 0, 0, 0",
                "snapOnInput":true,
                "startingDirectory":"%USERPROFILE%",
                "useAcrylic":true
            }
```
これで、ubuntuが追加されているはずです。

# brewコマンド
僕の環境にはbrewコマンドがなかったので、まず、インストールするところから始めます。
その前に、パッケージをアップデートしておきましょう。

```shell
sudo apt update
```
そして、brewをインストールします。

```shell
sudo apt install linuxbrew-wrapper
```
本来これで入れられるはずですが、ここでエラーが出たので、以下の記事を参考にしてHomebrewを導入しました。
[Windowsでもbrewを使いたい！WSLのインストールとホームディレクトリの変更、そしてbrewが使えるようになるまで](https://qiita.com/yukiarrr/items/1e1562fb2a3ba7384d1b)
> # brewのインストール
> 
> 基本的には、[ドキュメント](https://docs.brew.sh/Homebrew-on-Linux)通りにやれば大丈夫です。
> 
> まず、以下のコマンドを実行します。
> 
> ```
> sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
> ```
> 
> こちらが完了したのち、次のコマンドを実行します。
> 
> ```
> test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
> test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
> test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
> echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile
> ```
> 
> 最後に、brewが依存するパッケージ群をインストールします。
> 今回はUbuntuなので、以下を実行してください。
> 
> ```
> sudo apt-get install build-essential curl file git
> ```
> 
> これでbrewが使えるようになりました。
> 

この記事をもとに実行して、以下のコマンドを実行しました。

```shell
$ brew doctor

Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and which additional flags to use when
compiling and linking.

Having additional scripts in your path can confuse software installed via
Homebrew if the config script overrides a system or Homebrew-provided
script of the same name. We found the following "config" scripts:
  /mnt/c/Strawberry/c/bin/gdlib-config
  /mnt/c/Strawberry/c/bin/libpng-config
  /mnt/c/Strawberry/c/bin/libpng16-config
  /mnt/c/Strawberry/c/bin/xml2-config
  /mnt/c/Strawberry/c/bin/xslt-config
  /mnt/c/Strawberry/perl/bin/pkg-config
  /mnt/c/Users/muto/Anaconda3/Library/bin/icu-config
```
すると、無視できる警告が出ただけだったので、上記の記事通りでインストールできました。

# herokuにデプロイ
ではいよいよherokuに接続していきます。
windows terminal上のubuntuのターミナルで以下を実行します。

```shell
brew tap heroku/brew && brew install heroku
cd Documents/programing/django/garbage
echo web: gunicorn --pythonpath garbage_proj garbage_proj.wsgi --log-file -
echo python-3.7.4 > runtime.txt
```
3行目のコマンドですが、プロジェクトディレクトリとgit管理ディレクトリが異なると、うまくいかなかったので、`--pythonpath garbage_proj `の部分を加えました。
構造としてはこのような構造になっていました。
garbage（git管理ディレクトリ）
└garbage_proj（プロジェクトディレクトリ）

また、デプロイ用に設定を変更していきます。
とりあえず最低限デプロイできるように設定をいじっているので本番運用にするにはセキュリティ的に不十分です。

```py
# TEMPLATES>context_processors内に画像を扱えるように追加
                'django.template.context_processors.media',

# heroku用の設定の追加
import django_heroku #追加
django_heroku.settings(locals()) #追加

# SQLite3はHerokuでは動かないので、変えるか不要なら空にしておく
DATABASES = {}

ALLOWED_HOSTS = ['.herokuapp.com']
```
本来は`DEBUG = False`も設定すべき。ただ、`Server Error (500)`が発生したのでいったんそのまま実行しています。

また、デプロイする際に必要なpythonのライブラリをインストールしておきます。なお、ubuntuのターミナルだとubuntuのシステム用(?)のpythonが入っているので、普通のターミナルで実行してあげる必要があります。

```terminal
pip install gunicorn
pip install django-heroku
pip install dj-database-url
pip freeze > requirements.txt
```
`requirements.txt`は仮想環境を構築していなかった都合上、ローカルのライブラリが全部書き出されてしまうので必要なもののみにしてあげました（反省点）。以下の感じです。

```
bootstrap4==0.1.0
Django==3.0.8
django-bootstrap4==2.2.0
django-heroku==0.3.1
django-mathfilters==1.0.0
numpy==1.18.2
pandas==1.0.3
Pillow==7.1.1
gunicorn==20.0.4
dj-database-url==0.5.0
matplotlib==3.2.1
tensorflow==2.0.0
Keras==2.4.0
```
それではherokuに接続してみましょう。

```terminal
heroku login
heroku create garbageeycjur(app name)
heroku config:set SECRET_KEY="(setting.pyにあるsecret key)
git push heroku master

heroku ps:scale web=1
(データベースは設定しなくてok)
heroku open
```
参考文献：[DjangoアプリをHerokuにデプロイする方法](https://qiita.com/frosty/items/66f5dff8fc723387108c)

一応うまくいくと上記のコードだけでも行けるはずですが、当然エラーが出るのでいろいろ修正します。

まず、静的ファイルを扱うための（詳しくは、アプリケーションごとのstaticディレクトリを指定ディレクトリに集約コピーする）機能をもつcollectstaticが不要であれば、環境変数DISABLE_COLLECTSTATICを設定してくださいみたいなメッセージが出るので、言われたとおりに以下のコマンドを入力します。

```terminal
heroku config:set DISABLE_COLLECTSTATIC=1
```
ここら辺は何かエラーが起こったら以下のコードを見ましょう

```terminal
heroku logs --tail
```
このコードを実行するとheroku上のactivityみたいなところのリンクが出てくるのでそれを見ると詳しいエラー内容を見ることができます。

また、一度デプロイした後の更新は以下のコマンドでできます。

```terminal
heroku login
git push heroku master
heroku ps:scale web=1
heroku open
```

と、ここまでさもうまくいったかのようなことを書きましたが、残念ながら、以下のエラーで死にました。

```
Compiled slug size: 〇〇M is too large (max is 500M).
```
要するに容量食いすぎですよと。この原因というのはほとんどtensolflowなのですが、tensolflow（及びkeras）をダウングレードしてみると今度はモデルが動かなくなります泣

ということで、~~モデルは動きませんが~~とりあえずデプロイはしたので、特にスマホ画面でのサイドバーに注目してみてみてください。

~~このままじゃ終われないので、後日python anywhereあたりでデプロイしなおしてみます。
また、課金する・モデルを作り直す以外の方法でエラーを解決する知見をお持ちの方がいたら教えていただけると嬉しいです。~~

### ------11/28追記------
tensorflow-cpu==2.3.1にしたら動きました！！！
cpu版だと130MBぐらいしかないので、無課金でも動かせる範囲内に収めることができるということです。

URL：[画像でゴミ分類！](https://garbageeycjur.herokuapp.com/)
[![画像でゴミ分類！](https://github.com/eycjur/garbage/blob/master/qiita_image/ps-7.png?raw=true)](https://garbageeycjur.herokuapp.com/)



＜記事一覧＞

- [「画像でゴミ分類！」アプリ作成日誌day1～データセットの作成～](https://qiita.com/eycjur/items/7d8223b28758c7dfaaa0)
- [「画像でゴミ分類！」アプリ作成日誌day2～VGG16でFine-tuning～](https://qiita.com/eycjur/items/3e954cb70dc15f996c2d)
- [「画像でゴミ分類！」アプリ作成日誌day3～Djangoでwebアプリ化～](https://qiita.com/eycjur/items/9c618538177c82f7fdc3)
- [「画像でゴミ分類！」アプリ作成日誌day4～Bootstrapでフロントエンドを整える～](https://qiita.com/eycjur/items/7b58c28eb8b16e722b5d)
- [「画像でゴミ分類！」アプリ作成日誌day5～Bootstrapでフロントエンドを整える2～](https://qiita.com/eycjur/items/08808097acd625e00652)
- [「画像でゴミ分類！」アプリ作成日誌day6～ディレクトリ構成の修正～](https://qiita.com/eycjur/items/f436787c2d517af6cad6)
- [「画像でゴミ分類！」アプリ作成日誌day7～サイドバーのスライドメニュー化～](https://qiita.com/eycjur/items/009dca5866c3e9ad0dd6)
- [「画像でゴミ分類！」アプリ作成日誌day8～herokuデプロイ～](https://qiita.com/eycjur/items/ebfae5db5dd1cd8349ea) ←イマココ

# 参考文献

- [Windows 10でWindowsターミナルにUbuntuタブを追加する方法](https://soundartifacts.com/ja/how-to/280-how-to-add-ubuntu-tab-to-windows-terminal-in-windows-10.html)
- [Windowsでもbrewを使いたい！WSLのインストールとホームディレクトリの変更、そしてbrewが使えるようになるまで](https://qiita.com/yukiarrr/items/1e1562fb2a3ba7384d1b)
- [DjangoアプリをHerokuにデプロイする方法](https://qiita.com/frosty/items/66f5dff8fc723387108c)