【GoogleHomeでメモ帳アプリを作る】3. 実際にHerokuでアプリを作ってみる

概要

herokuやDjangoの公式のチュートリアルをやったけど、自分で一から作るとなると色々わからなかったので理解しながら作る

資料全体の構成はここに記載: GoogleHomeに話しかけてメモを記録したりメモを読み上げてもらう

この資料はGoogleHome用のアプリとは直接関係ないのでほとんど飛ばしていいことしか書いていない

Djangoチュートリアル

herokuのチュートリアル

チュートリアルと同じように自分でも作ってみる

必要なファイルや設定だけをチュートリアルから取って来ることにする

参考 各種説明 - https://devcenter.heroku.com/articles/deploying-python

作る手順

  1. Djangoアプリを先に作成する
  2. Djangoアプリがローカルで動くことを確認
  3. herokuアプリとしてリモートにデプロイする

この順序にした理由は後述のProcfileとWebアプリを同じディレクトリ内に置く必要があるため

Djangoアプリの作成

まずDjangoアプリを作成する - 別にDjangoではなくてflaskとかでもいいとは思うが、チュートリアルDjangoなので真似して作ってみる

Django参考 - https://docs.djangoproject.com/ja/2.0/intro/tutorial01/#creating-a-project

Django】プロジェクト作成

プロジェクト名とパッケージ名は以下のコマンドだとどちらもgooglehomeになる

[~/git/ludwig125-heroku] $django-admin startproject googlehome
[~/git/ludwig125-heroku] $tree                           (git)-[master]
.
── googlehome
   ├── googlehome
   │   ├── __init__.py
   │   ├── settings.py
   │   ├── urls.py
   │   └── wsgi.py
   └── manage.py

2 directories, 9 files
[~/git/ludwig125-heroku] $  

Django】アプリ作成

試しに適当なアプリケーションを作ってみる

参考 - https://docs.djangoproject.com/ja/2.0/intro/tutorial01/#write-your-first-view

helloアプリの作成

作るアプリケーション: hello
- 作り方

python manage.py startapp hello
[~/git/ludwig125-heroku/googlehome] $python manage.py startapp hello
[~/git/ludwig125-heroku/googlehome] $tree                (git)-[master]
.
├── db.sqlite3
├── googlehome
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── settings.cpython-36.pyc
│   │   ├── urls.cpython-36.pyc
│   │   └── wsgi.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── hello
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── manage.py

4 directories, 17 files
[~/git/ludwig125-heroku/googlehome] $ 

view.pyの作成

view.pyを編集

[~/git/ludwig125-heroku/googlehome] $cat hello/views.py (git)-[master]

from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the hello index.")

urls.pyの作成

https://docs.djangoproject.com/ja/2.0/intro/tutorial01/#write-your-first-view

ビューを呼ぶために、 URL を対応付けしてやる必要があります。そのためには URLconf が必要です polls ディレクトリに URLconf を作るには urls.py というファイルを作ります。

これを参考にurls.pyを作成する

[~/git/ludwig125-heroku/googlehome] $cat hello/urls.py (git)-[master]

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

ルートのurls.pyの修正

次のステップはルートのURLconfに polls.urls モジュールの記述を反映させることです。

ここも同様に修正する

[~/git/ludwig125-heroku/googlehome] $cat googlehome/urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('hello/', include('hello.urls')),    ←追加
    path('admin/', admin.site.urls),
]

Django】ローカルでWebアプリ起動

ローカルでWebサーバ立ち上げ

ここまでやったら以下でWebサーバを立てる

[~/git/ludwig125-heroku/googlehome] $python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

You have 14 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

February 03, 2018 - 15:24:45
Django version 2.0, using settings 'googlehome.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[03/Feb/2018 15:24:59] "GET /hello HTTP/1.1" 301 0
[03/Feb/2018 15:24:59] "GET /hello/ HTTP/1.1" 200 40

以下をブラウザから見てみる

http://127.0.0.1:8000/hello/ ↓ 「Hello, world. You're at the hello index.」が表示された

heroku_jisaku_hello

ここまででDjangoとしてするべきことはやった 次はこれをherokuで開くために色々やることがある

herokuアプリの作成

【heroku】アプリのcreate

Djangoプロジェクトを作成したときの外側のgooglehome直下でherokuアプリを作成する

git 初期化

[~/git/ludwig125-heroku/googlehome] $git init                                           (git)-[master]
Initialized empty Git repository in /home/ludwig125/git/ludwig125-heroku/googlehome/.git/
[~/git/ludwig125-heroku/googlehome] $ 

heroku create

[~/git/ludwig125-heroku/googlehome] $heroku create                                      (git)-[master]
 ▸    heroku-cli: update available from 6.14.43-73d5876 to 6.15.22-3f1c4bd
Creating app... done, ⬢ aqueous-peak-42683
https://aqueous-peak-42683.herokuapp.com/ | https://git.heroku.com/aqueous-peak-42683.git
[~/git/ludwig125-heroku/googlehome] $                                                   (git)-[master]

何も指定しないと適当なアプリ名があてがわれる

【heroku】Pipfileとrequirements.txt

以下のファイルだけをとりあえず公式のチュートリアルリポジトリから持ってきてスタートする https://github.com/heroku/python-getting-started

  • requirements.txt
  • Pipfile

なぜこの2ファイルかは以下の理由

https://devcenter.heroku.com/articles/getting-started-with-python#declare-app-dependencies

Heroku recognizes an app as a Python app by the existence of a Pipfile or requirements.txt file in the root directory.

herokuでは、Pipfileかrequirements.txtがherokuのルートディレクトリにあると、Pythonアプリだと認識してくれるらしい

[~/git/ludwig125-heroku/googlehome] $cat requirements.txt           (git)-[master]
certifi==2017.11.5
chardet==3.0.4
Django==2.0
flake8==3.5.0
idna==2.6
mccabe==0.6.1
pew==1.1.2
pipenv==9.0.1
pycodestyle==2.3.1
pyflakes==1.6.0
pytz==2017.3
requests==2.18.4
urllib3==1.22
virtualenv==15.1.0
virtualenv-clone==0.2.6
[~/git/ludwig125-heroku/googlehome] $
[~/git/ludwig125-heroku/googlehome] $cat Pipfile                    (git)-[master]
[[source]]

url = "https://pypi.python.org/simple"
verify_ssl = true


[packages]

django = "*"
gunicorn = "*"
django-heroku = "*"
requests = "*"


[requires]

python_version = "3.6"
[~/git/ludwig125-heroku/googlehome] $    

【heroku】pipenv実行

pipenv install を実行

Pipfileの内容でインストールする:

参考 - http://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html - http://pipenv-ja.readthedocs.io/ja/translate-ja/#other-commands

[~/git/ludwig125-herokuu/googlehome] $pipenv install                                             (git)-[master]
Creating a virtualenv for this project…
Using /home/ludwig125/.pyenv/versions/anaconda3-4.4.0/bin/python3.6m to create virtualenv…
⠋Running virtualenv with interpreter /home/ludwig125/.pyenv/versions/anaconda3-4.4.0/bin/python3.6m
Using base prefix '/home/ludwig125/.pyenv/versions/anaconda3-4.4.0'
New python executable in /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/python3.6m
Also creating executable in /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/python
/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/python3.6m: error while loading shared libraries: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory
ERROR: The executable /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/python3.6m is not functioning
ERROR: It thinks sys.prefix is '/home/ludwig125/git/ludwig125-heroku' (should be '/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov')
ERROR: virtualenv is not compatible with this system or executable

Virtualenv location: 
Warning: Your Pipfile requires python_version 3.6, but you are using None (/bin/python).
  $ pipenv check will surely fail.
Creating a virtualenv for this project…                                                            ⠙Using base prefix '/home/ludwig125/.pyenv/versions/3.6.3'
New python executable in /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/python3.6
Also creating executable in /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/python
Installing setuptools, pip, wheel...done.

Virtualenv location: /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (c8a67b)!                                                                     Installing dependencies from Pipfile.lock (c8a67b)…
  �   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 12/12 — 00:00:14
To activate this project's virtualenv, run the following:
 $ pipenv shell
[~/git/ludwig125-herokuu/googlehome] $   

soファイルが読み込めずにエラーが出ているが動いてはいるみたい

pipenv shellを実行

http://pipenv-ja.readthedocs.io/ja/translate-ja/#other-commands

shell は仮想環境が有効化されたシェルを起動します

check はセキュリティの脆弱性をチェックし、現在の環境がPEP 508の要求仕様を満たしていることを表明します。

[~/git/ludwig125-herokuu/googlehome] $pipenv check                                               (git)-[master]
Checking PEP 508 requirements…
Passed!
Checking installed package safety…
All good!
[~/git/ludwig125-herokuu/googlehome] $ 
[~/git/ludwig125-herokuu/googlehome] $pipenv shell                                               (git)-[master]

Spawning environment shell (/usr/bin/zsh). Use 'exit' to leave.
source /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/activate
[~/git/ludwig125-heroku] $source /home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/bin/activate
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku] $ 

【heroku】Procfile

Profileとは - アプリのスタート時に動くファイルを定義するもの https://devcenter.heroku.com/articles/getting-started-with-python#define-a-procfile

Procfileについて

https://devcenter.heroku.com/articles/deploying-python#the-procfile

A Procfile is a text file in the root directory of your application that defines process types and explicitly declares what command should be executed to start your app.

Your Procfile will look something like this:

web: gunicorn gettingstarted.wsgi --log-file -

チュートリアルのProcfileも同じような感じだった https://github.com/heroku/python-getting-started/blob/master/Procfile

web: gunicorn gettingstarted.wsgi

Procfileの各項目の説明

web: gunicorn gettingstarted.wsgi
web
web, is important here. It declares that this process type will be attached to the HTTP routing stack of Heroku, and receive web traffic when deployed.      
log-file
It means "log to stdout". The --log-file flag lets you set a path to a log file, and - means "stdout" (in this context).     

参考
- https://stackoverflow.com/questions/26129020/what-does-log-file-mean-in-heroku-procfile

gunicorn gettingstarted.wsgi

上のProcfileでは、チュートリアルのアプリケーション名が以下の通りgettingstarted なのでこう書いてあるが、自分のアプリケーションを作るのであれば直さなければならない - https://github.com/heroku/python-getting-started/tree/master/gettingstarted

自分のアプリケーション用にProcfileを作成する

今回はGoogleHome用のサーバを立てたいので、googlehomeという名前を指定する

(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $cat Procfile                                             (git)-[master]
web: gunicorn googlehome.wsgi --log-file -
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $

注意点

  • herokuのProcfileは、Webアプリと同じディレクトリにないと認識してくれないみたい
  • 最初は自分は ~/git/ludwig125-heroku/ 以下にProcfileを置いて、その下にDjangoアプリを作成した

  • そのために、Procfileがあるのは~/git/ludwig125-heroku/googlehomeで、Djangoのアプリケーション本体があるのは一段下のディレクトリになってしまった

  • 以下のように、Procfileとアプリケーションを同じディレクトリに置く必要がある

(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $ls                                                 (git)-[master]
Pipfile  Procfile  db.sqlite3  googlehome/  hello/  manage.py*  requirements.txt  staticfiles/
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $git status                                         (git)-[master]

最初、Procfileを外側の「googlehome」ディレクトリより上に置いてherokuを立ち上げようとしたら全くうまく行かなかった

(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku] $heroku local web               (git)-[master]
 ▸    heroku-cli: update available from 6.14.43-73d5876 to 6.15.22-3f1c4bd
[OKAY] Loaded ENV .env File as KEY=VALUE Format
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19199] [INFO] Starting gunicorn 19.7.1
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19199] [INFO] Listening at: http://0.0.0.0:5000 (19199)
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19199] [INFO] Using worker: sync
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19202] [INFO] Booting worker with pid: 19202
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19202] [ERROR] Exception in worker process
00:28:35 web.1   |  Traceback (most recent call last):
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/arbiter.py", line 578, in spawn_worker
00:28:35 web.1   |      worker.init_process()
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/workers/base.py", line 126, in init_process
00:28:35 web.1   |      self.load_wsgi()
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/workers/base.py", line 135, in load_wsgi
00:28:35 web.1   |      self.wsgi = self.app.wsgi()
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/app/base.py", line 67, in wsgi
00:28:35 web.1   |      self.callable = self.load()
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
00:28:35 web.1   |      return self.load_wsgiapp()
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
00:28:35 web.1   |      return util.import_app(self.app_uri)
00:28:35 web.1   |    File "/home/ludwig125/.local/share/virtualenvs/ludwig125-heroku-G7FbBSov/lib/python3.6/site-packages/gunicorn/util.py", line 352, in import_app
00:28:35 web.1   |      __import__(module)
00:28:35 web.1   |  ModuleNotFoundError: No module named 'googlehome.wsgi'
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19202] [INFO] Worker exiting (pid: 19202)
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19199] [INFO] Shutting down: Master
00:28:35 web.1   |  [2018-02-04 00:28:35 +0900] [19199] [INFO] Reason: Worker failed to boot.
00:28:35 web.1   Exited with exit code 3
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku] $

ModuleNotFoundError: No module named 'googlehome.wsgi'

【heroku】heroku用にDjangoを少し直す

Djangoをherokuで動かすためには以下の設定が必要

https://devcenter-assets0.herokucdn.com/articles/django-memcache#configure-django-for-heroku

Django requires some special configuration in order to work on Heroku, mainly for the database to work and the static files to be served. Luckily, there is adjango-heroku package that takes care of all that. So on the bottom of the file django_queue/settings.py add the following lines:

# Configure Django App for Heroku.
import django_heroku
django_heroku.settings(locals())

ということで、hello/view.pyを以下のように修正する

from django.http import HttpResponse                                 


def index(request):
    return HttpResponse("Hello, world. You're at the hello index.")

【heroku】herokuアプリをローカルで立ち上げる

heroku local web

(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $heroku local web          (git)-[master]
 ▸    heroku-cli: update available from 6.14.43-73d5876 to 6.15.22-3f1c4bd
[OKAY] Loaded ENV .env File as KEY=VALUE Format
22:55:23 web.1   |  [2018-02-04 22:55:23 +0900] [11851] [INFO] Starting gunicorn 19.7.1
22:55:23 web.1   |  [2018-02-04 22:55:23 +0900] [11851] [INFO] Listening at: http://0.0.0.0:5000 (11851)
22:55:23 web.1   |  [2018-02-04 22:55:23 +0900] [11851] [INFO] Using worker: sync
22:55:23 web.1   |  [2018-02-04 22:55:23 +0900] [11854] [INFO] Booting worker with pid: 11854

ローカルのブラウザでは見られるようになった http://0.0.0.0:5000/hello/ Hello, world. You're at the hello index.

heroku_jisaku_hello

.envの追加

上のheroku local webを最初にやったときは以下のWARNが出た

(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku] $heroku local web               (git)-[master]
 ▸    heroku-cli: update available from 6.14.43-73d5876 to 6.15.22-3f1c4bd
[WARN] No ENV file found
23:27:09 web.1   |  [2018-02-03 23:27:09 +0900] [14824] [INFO] Starting gunicorn 19.7.1
23:27:10 web.1   |  [2018-02-03 23:27:09 +0900] [14824] [INFO] Listening at: http://0.0.0.0:5000 (14
824)

→ 「[WARN] No ENV file found」 そこで、公式のチュートリアルから.envをコピーした - https://github.com/heroku/python-getting-started/blob/master/.env

参考 - https://stackoverflow.com/questions/37690780/heroku-local-warn-no-env-file-found

(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku] $cat .env                       (git)-[master]
TIMES=2
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku] $

【heroku】herokuのリモートにデプロイ

この状態でherokuにデプロイしてみよう

(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $git add .                                          (git)-[master]
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $git commit -m 'new heroku app'  .                  (git)-[master]
[master (root-commit) a80e0db] new heroku app
 489 files changed, 55618 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Pipfile
 create mode 100644 Procfile
 create mode 100644 db.sqlite3
略
 create mode 100644 staticfiles/staticfiles.json
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $                                                   (git)-[master]
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $git push heroku master                             (git)-[master]
Counting objects: 280, done.
Compressing objects: 100% (274/274), done.
Writing objects: 100% (280/280), 871.41 KiB | 0 bytes/s, done.
Total 280 (delta 44), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Python app detected
remote:  !     No 'Pipfile.lock' found! We recommend you commit this into your repository.
remote: -----> Installing python-3.6.4
remote: -----> Installing pip
remote: -----> Installing requirements with pip
remote:        Collecting certifi==2017.11.5 (from -r /tmp/build_bee926373efffef7cab46947c96c8691/requirements.txt (line 1))
(中略)
remote:          File "<frozen importlib._bootstrap_external>", line 678, in exec_module
remote:          File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
remote:          File "/tmp/build_bee926373efffef7cab46947c96c8691/googlehome/settings.py", line 14, in <module>
remote:            import django_heroku
remote:        ModuleNotFoundError: No module named 'django_heroku'
remote: 
remote:  !     Error while running '$ python manage.py collectstatic --noinput'.
remote:        See traceback above for details.
remote: 
remote:        You may need to update application code to resolve this error.
remote:        Or, you can disable collectstatic for this application:
remote: 
remote:           $ heroku config:set DISABLE_COLLECTSTATIC=1
remote: 
remote:        https://devcenter.heroku.com/articles/django-assets
remote:  !     Push rejected, failed to compile Python app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !       Push rejected to aqueous-peak-42683.
remote: 
To https://git.heroku.com/aqueous-peak-42683.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/aqueous-peak-42683.git'
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $ 

remote:           $ heroku config:set DISABLE_COLLECTSTATIC=1 と出ている

collectstatic は不要なので以下をする

$ heroku config:set DISABLE_COLLECTSTATIC=1

参考 - https://devcenter.heroku.com/articles/django-assets#disabling-collectstatic - http://thinkami.hatenablog.com/entry/2017/01/13/053643

(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $heroku config:set DISABLE_COLLECTSTATIC=1          (git)-[master]
 ▸    heroku-cli: update available from 6.14.43-73d5876 to 6.15.22-3f1c4bd
Setting DISABLE_COLLECTSTATIC and restarting ⬢ aqueous-peak-42683... done, v3
DISABLE_COLLECTSTATIC: 1
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $git push heroku master                             (git)-[master]
Counting objects: 280, done.
Compressing objects: 100% (274/274), done.
Writing objects: 100% (280/280), 871.41 KiB | 0 bytes/s, done.
Total 280 (delta 44), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Python app detected
(中略)
remote:        Released v5
remote:        https://aqueous-peak-42683.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/aqueous-peak-42683.git
 * [new branch]      master -> master
(ludwig125-heroku-G7FbBSov) [~/git/ludwig125-heroku/googlehome] $ 

pushできた!

heroku open とすると以下のURLでブラウザが開く https://aqueous-peak-42683.herokuapp.com/

「Application error」

heroku_apperro

ログの確認

困ったときはheroku logsでログを確認する

(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $heroku logs               (git)-[master]
 ▸    heroku-cli: update available from 6.14.43-73d5876 to 6.15.22-3f1c4bd
2018-02-04T13:55:51.472389+00:00 app[web.1]:     self.callable = self.load()
2018-02-04T13:55:51.472390+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
(中略)
2018-02-04T13:55:51.416412+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/django/conf/__init__.py", line 106, in __init__
2018-02-04T13:55:51.416414+00:00 app[web.1]:     mod = importlib.import_module(self.SETTINGS_MODULE)
2018-02-04T13:55:51.416416+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/importlib/__init__.py", line 126, in import_module
2018-02-04T13:55:51.416417+00:00 app[web.1]:     return _bootstrap._gcd_import(name[level:], package, level)
2018-02-04T13:55:51.416419+00:00 app[web.1]:   File "/app/googlehome/settings.py", line 14, in <module>
2018-02-04T13:55:51.416420+00:00 app[web.1]:     import django_heroku
2018-02-04T13:55:51.416430+00:00 app[web.1]: ModuleNotFoundError: No module named 'django_heroku'
2018-02-04T13:55:51.416774+00:00 app[web.1]: [2018-02-04 13:55:51 +0000] [8] [INFO] Worker exiting (pid: 8)
2018-02-04T14:00:20.701204+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=aqueous-peak-42683.herokuapp.com request_id=58027f22-e4fc-43b9-9bbf-eb4014918628 fwd="60.76.227.16" dyno= connect= service= status=503 bytes= protocol=https
2018-02-04T14:00:21.453798+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=aqueous-peak-42683.herokuapp.com request_id=97dbadbc-8864-4be0-852a-a3a2178ac7a2 fwd="60.76.227.16" dyno= connect= service= status=503 bytes= protocol=https
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $  

import django_heroku ModuleNotFoundError: No module named 'django_heroku'

requirements.txtとローカルのパッケージを比較する

ローカルのパッケージ
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $pip freeze > pip_packages                                (git)-[master]
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $cat pip_packages                                         (git)-[master]
certifi==2018.1.18
chardet==3.0.4
dj-database-url==0.4.2
Django==2.0.2
django-heroku==0.2.0
gunicorn==19.7.1
idna==2.6
psycopg2==2.7.3.2
pytz==2017.3
requests==2.18.4
urllib3==1.22
whitenoise==3.3.1
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $ 
一方requirements.txt
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $cat requirements.txt                                     (git)-[master]
certifi==2017.11.5
chardet==3.0.4
Django==2.0
flake8==3.5.0
gunicorn==19.7.1
idna==2.6
mccabe==0.6.1
pew==1.1.2
pipenv==9.0.1
pycodestyle==2.3.1
pyflakes==1.6.0
pytz==2017.3
requests==2.18.4
urllib3==1.22
virtualenv==15.1.0
virtualenv-clone==0.2.6
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $  

django-heroku==0.2.0がrequirements.txtに無かった!

このように、ローカルのパッケージと、リモートのパッケージが異なっていてうまく動かない場合があるので、 pip freezeとrequirements.txtを比較するのは大事

改めてgit push heroku master

(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $git diff                                                 (git)-[master]
diff --git a/requirements.txt b/requirements.txt
index 468f0a3..50e7c0a 100644
@@ -1,6 +1,7 @@
 certifi==2017.11.5
 chardet==3.0.4
 Django==2.0
+django-heroku==0.2.0
 flake8==3.5.0
 gunicorn==19.7.1
 idna==2.6
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $git commit -m 'add django-heroku==0.2.0' requirements.txt 
[master 7dffb4c] add django-heroku==0.2.0
 1 file changed, 1 insertion(+)
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $git push heroku master                                   (git)-[master]
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 316 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Python app detected
remote:  !     No 'Pipfile.lock' found! We recommend you commit this into your repository.
remote: -----> Installing requirements with pip
remote:        Collecting django-heroku==0.2.0 (from -r /tmp/build_e5ffa088d26050c45e7abaa595a50b1f/requirements.txt (line 4))
remote:          Downloading django_heroku-0.2.0-py2.py3-none-any.whl
remote:        Collecting dj-database-url (from django-heroku==0.2.0->-r /tmp/build_e5ffa088d26050c45e7abaa595a50b1f/requirements.txt (line 4))
(中略)
remote:        https://aqueous-peak-42683.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/aqueous-peak-42683.git
   558d762..7dffb4c  master -> master
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $ 

「No 'Pipfile.lock' found! We recommend you commit this into your repository.」 Pipfile.lock がないというメッセージが出ているので追加しておく

Pipfile.lock とは

http://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html#pipfile-lock-security-features

Pipfile.lock は pip に新しく入った偉大なセキュリティ上の改善を利用します。 デフォルトでは、 Pipfile.lock はダウンロードされたパッケージごとのsha256ハッシュから生成されます。 これにより pip は、ネットワークが驚異に晒されていたり、信頼できないPyPIエンドポイントから依存パッケージをインストールしたりしているときに、意図したとおりのパッケージをインストールしていることを保証できます。 開発環境から本番環境へプロジェクトを昇格させる方法でデプロイに取り組むことを強く推奨します。  pipenv lock を使って開発環境の依存関係をコンパイルし、そのコンパイルされた Pipfile.lock を全ての本番環境にデプロイして再現可能なビルドができます。

これもチュートリアル用のリポジトリからコピペする

追加してからgit push

(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $git push heroku master                                   (git)-[master]
Counting objects: 4, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 3.29 KiB | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Python app detected
remote:  !     The latest version of Python 3 is python-3.6.4 (you are using python-3.6.3, which is unsupported).
remote:  !     We recommend upgrading by specifying the latest version (python-3.6.4).
remote:        Learn More: https://devcenter.heroku.com/articles/python-runtimes
remote: -----> Found python-3.6.4, removing
remote: -----> Installing python-3.6.3
remote: -----> Installing pip
remote: -----> Installing requirements with pip
remote:        Collecting certifi==2017.11.5 (from -r /tmp/build_8601996728746a7313b6f8219d936dbb/requirements.txt (line 1))
(中略)
remote:        Collecting psycopg2 (from django-heroku==0.2.0->-r /tmp/build_8601996728746a7313b6f8219d936dbb/requirements.txt (line 4))
remote:          Downloading psycopg2-2.7.3.2-cp36-cp36m-manylinux1_x86_64.whl (2.7MB)
remote:        Installing collected packages: certifi, chardet, pytz, Django, whitenoise, dj-database-url, psycopg2, django-heroku, mccabe, pyflakes, pycodestyle, flake8, gunicorn, idna, virtualenv, virtualenv-clone, pew, urllib3, requests, pipenv
remote:          Running setup.py install for virtualenv-clone: started
remote:            Running setup.py install for virtualenv-clone: finished with status 'done'
remote:          Running setup.py install for pipenv: started
remote:            Running setup.py install for pipenv: finished with status 'done'
remote:        Successfully installed Django-2.0 certifi-2017.11.5 chardet-3.0.4 dj-database-url-0.4.2 django-heroku-0.2.0 flake8-3.5.0 gunicorn-19.7.1 idna-2.6 mccabe-0.6.1 pew-1.1.2 pipenv-9.0.1 psycopg2-2.7.3.2 pycodestyle-2.3.1 pyflakes-1.6.0 pytz-2017.3 requests-2.18.4 urllib3-1.22 virtualenv-15.1.0 virtualenv-clone-0.2.6 whitenoise-3.3.1
remote: 
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote: 
remote: -----> Compressing...
remote:        Done: 60.7M
remote: -----> Launching...
remote:        Released v7
remote:        https://aqueous-peak-42683.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/aqueous-peak-42683.git
   7dffb4c..a11938f  master -> master
(googlehome-Z81pgPAi) [~/git/ludwig125-heroku/googlehome] $

これでもう一度 https://aqueous-peak-42683.herokuapp.com/hello/

→ 「Hello, world. You're at the hello index.」

表示された!

heroku_jisaku_hello2

git のリモートにoriginを登録

githubでコードを見られるようにする 参考 - https://qiita.com/koshihikari/items/dcf126fa9c0de2b6fa7e

自分の設定では

[~/git/ludwig125-heroku/googlehome] $git remote -v                                   (git)-[master]
heroku  https://git.heroku.com/aqueous-peak-42683.git (fetch)
heroku  https://git.heroku.com/aqueous-peak-42683.git (push)
[~/git/ludwig125-heroku/googlehome] $c

herokuだけがリモートリポジトリとなっている

githubにこれを登録するために、 https://github.com/ からNew repositoryを押して、「googlehome」リポジトリを作成

そのリポジトリからURLをコピペして、以下のようにgit remote add origin とする

 [~/git/ludwig125-heroku/googlehome] $git remote add origin git@github.com:ludwig125/googlehome.git
[~/git/ludwig125-heroku/googlehome] $git branch                                      (git)-[master]
* master
[~/git/ludwig125-heroku/googlehome] $git push origin master                          (git)-[master]
Counting objects: 335, done.
Compressing objects: 100% (326/326), done.
Writing objects: 100% (335/335), 882.21 KiB | 0 bytes/s, done.
Total 335 (delta 77), reused 0 (delta 0)
remote: Resolving deltas: 100% (77/77), done.
To git@github.com:ludwig125/googlehome.git
 * [new branch]      master -> master
[~/git/ludwig125-heroku/googlehome] $

追加後はこうなる

[~/git/ludwig125-heroku/googlehome] $git remote -v                                   (git)-[master]
heroku  https://git.heroku.com/aqueous-peak-42683.git (fetch)
heroku  https://git.heroku.com/aqueous-peak-42683.git (push)
origin  git@github.com:ludwig125/googlehome.git (fetch)
origin  git@github.com:ludwig125/googlehome.git (push)
[~/git/ludwig125-heroku/googlehome] $