kekeのアトリエ

エンジニア、読書@1915keke

誰もがつまづくDjangoをHerokuにデプロイするときあるある

はじめに

今回は「ツナキチ」というニューラルネットワークによる画像認識を用いて人間の顔が一体何% ネコっぽいのかを調べられるWebサイトを作りました。 時間がなくてsafariではデザインが崩れてしまってます。いずれ直します!) 明示的にHerokuでデプロイしていることを示したいので、リンクを貼らさせてもらいます。 https://tunakichi.herokuapp.com/

使ったバージョンは

  • python : v3.6.1
  • django : v1.11.7

です。

コメント、いいね大歓迎です。誤字や間違いは指摘していただけると助かります。

前提

ここではすでにアプリは完成していて、いまからデプロイするぞ!という方を前提にしています。 そしてデプロイをする上で、困ったことを紹介していきます。

デプロイ

pushする

まず、herokuのアプリケーションをherokuに登録しなければなりません。

heroku create <アプリ名>

で登録をすることができます。 一応、うまく繋がっているか確認してください。(これはgitとも接続されているか確認できるので初心者の人は使ってください。)

git remote -v

そして以下のように出ればおっけいです。

hogehoge:~/tunakichi[master]>> git remote -v
heroku  https://git.heroku.com/<リポジトリ名>.git (fetch)
heroku  https://git.heroku.com/<リポジトリ名>.git (push)
origin  git@github.com:KeisukeYamashita/<リポジトリ名>.git (fetch)
origin  git@github.com:KeisukeYamashita/<リポジトリ名>.git (push)

そしたら次にClearDBを作っていきます。簡単にいうとheroku上のDBです。

heroku addons:add cleardb:ignite

そしてherokuの環境変数を変更してください。

heroku config:set DISABLE_COLLECTSTATIC=1

ここでアプリ側の設定を変えなければなりません。wgsi.pyに以下に変更してください。

import os

from dj_static import Cling
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "<アプリ名>.settings")

application = Cling(get_wsgi_application())

これで設定ができたので、pushすればデプロイできます。

git add .
git commit -m "hogehoge"
git push origin master
git push heroku master

確認

git push heroku masterのときにURLがすでに表示されるのですが、開くには以下のコマンドが便利です。

heroku open

またマイグレーションが必要な方は以下のコマンドでしてください。

heroku run python manege.py migrate

さらにシードデータがあるときはloaddataで入れることができます。 DjangoではJSONによるシードデータを入れる方法と、.YAMLによるシードデータの入れ方があります。

heroku run python manegy.py loaddata <シードデータファイル(JSONorYAML)>

これで再起動すると正しく動くはずです。

heroku restart

トラブルシューティング

[ケース1] herokuへのpushがrejectされるNo default Language

これはDjangoをデプロイしようとしている人の多くが直面する問題です。

原因

ディフォルトでなんの言語を使うのかを指定していないことが問題です。 herokuでは次のような言語がサポートされていて、簡単にいうとどの言語を使いますかという設定をしないといけない。

image.png

今回はPythonを使います。

解決策

まず、pythonのバージョンをruntime.txtに書き込みます。

echo $(python -V) > runtime.txt

次にローカルで使っているパッケージをherokuでも使いたいのでrequirement.txtに記載します。

pip freeze > requirement.txt

そしてpushすればリジェクトされないはずです。

[ケース2]無料枠の落とし穴。「たまに見ると落ちているんですけど、、、」

原因

herokuの無料枠では、30分間アクセスがなれけばスリープモードに入ってしまい、再起動が必要となります。

解決策

毎20分ごとぐらいにherokuに自分でアクセスしてもいいのですが、これを自動化しましょう。 デプロイしたWebサーバー自体が自分にアクセスするように組めばいいのです。

'<アプリ名>/wgsi.pyに以下を追加してください。

import os
import threading
import requests
import time


def awake():
    while True:
        try:
            print("Start Awaking")
            requests.get("http://hogefuga.herokuapp.com/")
            print("End")
        except:
            print("error")
        time.sleep(300)

t = threading.Thread(target=awake)
t.start()

これによって自分にアクセスするようになるので、サーバーがスリープになるようなことはなくなります。

[ケース3]変な名前のモジュールがない。No module name _tkinker

原因

これはグラフを書くのによく使われるmatplotlibライブラリに含まれるmoduleであり、これがherokuでインストールされていないことが原因です。

解決策

まずサーバーにmatplotlibを使うことはおかしいです。笑 (僕はローカルで使っていた数値計算アルゴリズムをそのまま.pyファイルとしてサーバーの計算部分に使おうとしたら勝手に混入していました)

なのでアプリ内の全import <Matploblib>を削除すれば解決できます。

[ケース4]ケース3の一般系。No module name hogehoge

原因

とあるhogehogeモジュールがないといっています。 これは抽象度が高いので、原因がいくつか考えられると思います。

原因1. そんなモジュールなんてない説

本当にそのモジュールがあるかを確認してください。 タイピングミスでmodule名が変わっていないですが?

原因2. herokuにインストールされていない説 ← 定説

ローカルで追加で開発をして、再度pushしたとします。 ローカル環境で新しくpipで導入したことをherokuは知りません。

なのでrequirement.pyを更新することが必要です。

pip freeze > requirement.txt