Generic placeholder image

【WSL】Heroku・Git・Djangoを使い無料でWebに公開(パート2)

投稿日 2019年6月11日 >> 更新日 2020年12月25日

今回は【WSL】Heroku・Git・Djangoを使い無料でWebに公開(パート1)の続きとなるパート2で、Djangoアプリを無料でWebに公開する手順を紹介していこうと思います。

※2019年10月26日更新の補足と致しまして、この記事では生き足りない説明やエラーの問題などが数ヵ所あったため「補足:」として問題解決や説明を追加しました。この記事に辿り着いて下さった方々に時間を掛けさせてしまったことを誠に申し訳なく思います。開発環境によって使用は異なってきますが、くれぐれも確実性を狙って書いていくのでよろしくお願いします。

この時点でHerokuとGitの準備は整っていると思うので、あとはHerokuで公開するためにファイルをGitに保存しHerokuとGitを紐づける作業であります。

まずはファイルをGitに保存するまでの下準備が必要なのでターミナルを開きDjangoのプロジェクトディレクトリまで移動します。

【目次】

実行環境&使用ライブラリ

実行環境
Windows Subsystem for Linux Ubuntu
Python 3.6.8
使用ライブラリ
Django==2.2.6
django-heroku==0.3.1
gunicorn==19.9.0
psycopg2==2.8.4

HerokuへログインしDBの設定をする

まずはターミナルにてHerokuにログインします。


$ heroku login

すると下図のようにブラウザにてログイン画面が現れます。

ログイン画面が現れたらログインボタンを押してください。すると下図のように切り替わります。

ユーザー名パスワードを求められたらその通りに従ってください。

ターミナルへ戻りHeroku用として公開する空のアプリを作成します。このアプリ名は後にWebで公開される時のURLに付与されます。

私は運用しているサイト名であるzerofromlightとしてアプリを作成しました。
※名前が他と被らないように注意してください。

補足:ここで作成したアプリはHerokuサイトのドメイン名に当たる部分なので、既に使用されていると作成されません。


$ heroku create zerofromlight
Creating ⬢ zerofromlight... done
https://zerofromlight.herokuapp.com/ | https://git.heroku.com/zerofromlight.git

作成できましたらブラウザにて先ほどのログイン画面に行き、Heroku管理画面を開きます。
※真ん中にあるHerokuマークをクリック。

すると画面に先ほど作成したアプリが置かれていると思います。

ここからはデータベースの設定を行っていきます。HerokuではGUI操作で簡単にデータベースを選んで適用させることができます。

適用させるといってもDjangoアプリと適用するわけでは無く、Heroku内で使用するデータベースを準備するだけです。

Herokuで設置したデータベースを繋げるためにDjangoアプリ側では後程設定を行っていきます。

まずHeroku管理画面を開くためにアプリ名をクリックし、Resourcesをクリックします。

下図の画面のようになります。

HerokuではPostgreSQLが無料で推奨となっているので「add ons」にて「heroku postgresql」と検索します。

検索し選んだら適用します。

Overviewに移動すると反映されている事が分かります。

次にHerokuのデータベースであるPostgreSQLを紐づけるためにDjango側で設定を行っていきます。開発環境とHeroku環境で相互に扱えるようlocal_settings.pyを別途用意します。

補足:開発環境用の設定

# /project/project/local_settings.py

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
}

DEBUG = True

開発時はlocal_settings.pyを読み込み、Heroku環境(本番)ではsettings.pyを読み込むと言った設定を行います。

補足:いずれもsettings.pyを読み込みますが、Heroku環境では「local_settings.py」がこれから設定する「.gitignore」によって存在しなくなるのでインポートエラーにより、「django-heroku」ライブラリをインポートします。

補足:django-herokuライブラリと静的ファイルの「StaticFile」についてはこの後すぐ!

# /project/project/settings.py

DEBUG = False

# 下の方に記述します
# django-herokuの設定
try:
    from .local_settings import *
except ImportError:
    pass

if not DEBUG:
    import django_heroku
    django_heroku.settings(locals())

そしてこの設定で必要になるモジュールがdjango-herokuとなります。django-herokuを実行するとHerokuでの設定を全て行ってくれるので、Herokuがインストールするためのファイルをこれから作成していきたいと思います。

補足:django-herokuが上手くインストールできないという問題があり別のやり方をされているサイトがありますが、確認しながら進めて行けばより少ないコードで実装できるはずです。

Herokuに読み込ませるファイルは、requirements.txtとProcfileです。

補足:Pythonのバージョンを指定するために「runtime.txt」というファイルを作成するというやり方を見かけましたが、未設定でも実行可能でした。

補足:この記事では未設定で進めて行きます。

念のため記述しておきます。

# /project/runtime.txt

python-3.6.8

requirements.txtはpipパッケージをテキストで納めたりする時に使われるテキスト名です。このテキスト名が推奨されており読み込まれる対象となります。

Procfileは、Djangoアプリを起動させるために必要なファイルです。
後程requirements.txt内に記述するgunicornというモジュールを使いDjangoを起動させます。

ファイルはこのような配置となります。

# /project/

project
app
manage.py
db.sqlite3
requirements.txt
Procfile
runtime.txt    ←未設定でも実行可
......

requirements.txt内にはインストールするパッケージを記述します。

補足:面倒ですが、実行環境にて必要なパッケージをインストールしていきます。

補足:ここで躓くパターンが多いからです。


$ pip3 install gunicorn

$ pip3 install django-heroku

django-herokuのエラーについて

補足:恐らくお使いの環境でPostgreSQLを使用していない場合、このような「pg_config is required to build psycopg2 from source. Please add the directory containing pg_config to the $PATH or specify the full executable path with the option: ......Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-dqt80jcd/psycopg2/」エラーが出ると思います。

django-herokuをインストールする際に必要なモジュールの1つである「psycopg2」がインストールされない理由としては、PostgreSQLのドライバであるので、PostgreSQLが実行可能な環境にする必要があります。

幾つか方法はあるのですが、Linux環境でしたら「libpq-dev」をインストールすることで「psycopg2」をインストールすることができます。


$ sudo apt install libpq-dev

すると正常にインストールされるはずです。


$ pip3 install django-heroku

# 実行
$ pip3 freeze
dj-database-url==0.5.0
Django==2.2.6
django-heroku==0.3.1
gunicorn==19.9.0
pkg-resources==0.0.0
psycopg2==2.8.4
pytz==2019.3
sqlparse==0.3.0
whitenoise==4.1.4

そしてpipの内容を「requirements.txt」に納めます。


$ pip3 freeze > requirements.txt

# 実行
$ cat requirements.txt
dj-database-url==0.5.0
Django==2.2.6
django-heroku==0.3.1
gunicorn==19.9.0
pkg-resources==0.0.0
psycopg2==2.8.4
pytz==2019.3
sqlparse==0.3.0
whitenoise==4.1.4

ここで余分なパッケージが紛れ込んでしまっているので下記のように削除した状態にします。

そのままHerokuに読み込ませてしまうとエラーとなってしまいます。

# /project/requirements.txt

dj-database-url==0.5.0
Django==2.2.6
django-heroku==0.3.1
gunicorn==19.9.0
psycopg2==2.8.4
pytz==2019.3
whitenoise==4.1.4

Procfileではこのプロジェクトを起動させるための記述をします。

補足:「project」の部分は、Djangoアプリのプロジェクト名を入れてください。


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

最後にGitでは読み込ませない為のファイルとを作成します。読み込ませない為のファイルとは、HerokuへこのプロジェクトをGitから反映させる際に除外するファイルです。

例えば先ほど作成したlocal_settings.pyをHeroku側で読み込んでしまうと問題が起きます。なので.gitignoreというファイルを作成し除外リストを記述します。

requirements.txtとProcfileと同じディレクトリに.gitignoreを作成します。

補足:どうやら仮想環境下ではファイルの先頭に仮想環境名を記述するそうです。私は記述しなくても実行できましたのでどちらでもいいと思います。

補足:「.gitignore」ファイルの中身ですが、これはファイルを除外するためのものです。「db.sqlite3」のファイルを記述していましたが、開発環境でデータベースを編集したのちHerokuへデプロイすると適用されずにエラーとなってしまうので、取り除きました。

# /project/.gitignore

django venv_name    ←仮想環境名(記述しなくても動きました。)
__pycache__
staticfiles
local_settings.py
*.py[co]

静的ファイル(staticfile)に関する設定

補足:HerokuではDjangoの静的ファイル(static)の扱いをサポートしていなので、別途設定が必用になります。

より詳しい内容はHeroku公式のドキュメントを参照してください。

ここでは簡単な説明にとどめておきます。

必用なパッケージはdjango-herokuにより揃っているので、再度設定ファイルの「settings.py」に追記していきます。

# /project/project/settings.py

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',    ←追記
]

..........
..........

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')    ←追記
STATIC_URL = '/static/'

""" 追記"""
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

""" 追記"""
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

try:
    from .local_settings import *
except ImportError:
    pass
if not DEBUG:
    import django_heroku
    django_heroku.settings(locals())

補足:これでadmin管理画面のレイアウトも崩れることなく実装されるはずです。

補足:もし「collectstatic --noinput」で失敗のようなエラーとなったら、問題の診断を行うか、Collectstaticの無効化をするとうまく適用されます。

問題の診断をする

# /project/

$ heroku config:set DEBUG_COLLECTSTATIC=1

Collectstaticの無効化

# /project/

$ heroku config:set DISABLE_COLLECTSTATIC=1

あとはターミナルにてGitの初期化を行いプロジェクトを反映させ、GItとHerokuを繋げるだけです。

Gitを初期化しプロジェクトを反映させる

Herokuを使用するにはGitにコード履歴、もしくわプロジェクトファイルがなければいけないのでDjangoアプリをGitに渡していきます。

まずはDjangoアプリのプロジェクトルートディレクトリにてGitを初期化します。
※ルートディレクトリ上に移動した上で実行してください。


$ git init
Reinitialized existing Git repository in........

# .gitというディレクトリが作成される
$ ls -a
.  ..  .git  .gitignore  Procfile  app  db.sqlite3  manage.py  project  requirements.txt

次にDjangoアプリと先ほど作成したHeroku内にあるアプリを紐づけます。Heroku内のアプリ名を私はzerofromlightとしたのでこのアプリを指定します。


$ heroku git:remote -a zerofromlight
set git remote heroku to https://git.heroku.com/zerofromlight.git

紐づけたHeroku内アプリにPythonを使うように宣言します。宣言することにより自動でrequirements.txt内の外部ライブラリをインストールしてくれます。


$ heroku buildpacks:set heroku/python
Buildpack set. Next release on zerofromlight will use heroku/python.
Run git push heroku master to create a new release using this buildpack.

まだGitでは初期化をしただけなのでDjangoアプリのプロジェクトファイルをGitに追加していきます。

補足:「git add」のあとにファイル名を記述するだけで仮登録してくれます。


# ファイルを一つずつ追加していく場合
$ git add project

# まとめて追加する場合
$ git add .

次に追加を確定します。


# -m'追加理由などを書く'
$ git commit -m'new project'

追加や確定情報などはstatusオプションで確認することが出来る。

補足:Herokuへデプロイする際は必ずこの工程を踏みます。


$ git status

これでいよいよあと一押しでWebで公開することができます。

HerokuでWebサイトを公開

.gitフォルダが置かれたディレクトリ上でDjangoアプリを追加し確定を行ったらいよいよGItの情報をHerokuに紐づけるだけであります。

以下のような一行を実行してください。

補足:エラーなどが発生した場合はもう一度設定した内容を確認し、再度「git add」からやり直してみましょう。


$ git push heroku master
Counting objects: 50, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (50/50), 8.91 KiB | 85.00 KiB/s, done.
Total 50 (delta 10), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing python-3.6.8
remote: -----> Installing pip
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote:        Collecting Django==2.2.2.............
..............
..............
.............
.............
remote: Verifying deploy... done.
To https://git.heroku.com/zerofromlight.git
 * [new branch]      master -> master

上手くいけばこのような結果となります。

エラーなどが起こってしまった際は、requirements.txt内で余計なパッケージは記述されていないか、もしくわ除外すべきリストをしっかり記述しているかなどを確認してみてください。

これでHeroku内のアプリにDjangoアプリが紐づけられているのでHerokuを再起動し開きます。


$ heroku restart
Restarting dynos on ⬢ zerofromlight... done

$ heroku open
 ▸    Manually visit https://zerofromlight.herokuapp.com/ in your browser.

補足:こちらでも実行可能


$ heroku ps:scale web=1
Scaling dynos... done, now running web at 1:Free

ブラウザにてhttps://zerofromlight.herokuapp.com/を検索するとindex.htmlで記述したテキストが表示されます。

Herokuのデータベースへmigrateとスーパーユーザー

ちなみにDjangoのmigrateやスーパーユーザーを設定するにはHerokuのrunオプションを使用します。


# リモートでbashが立ち上がる
$ heroku run bash
Running bash on ⬢ zerofromlight... up, run.3077 (Free)
~$ python3 manage.py migrate

# pythonを立ち上げるには
$ heroku run python
Python 3.6.8 (default, Jan 29 2019, 19:35:16)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

heroku runモードを抜けるにはexitもしくわexit()で抜ける事が出来ます。

また、ファイルを編集しHerokuへデプロイする際は、「git add」からやり直してください。モデルを構築した際はマイグレーションもお忘れずに。

パート1、パート2と長くなりましたが以上でHerokuによる無料でWebサイトを公開するを終わります。

最後までご覧いただきありがとうございました。

<<< 一覧へ戻る