Django

【Django環境備忘録#3】Django REST frameworkをHerokuにデプロイする!

さて、Django環境備忘録シリーズの第3回です。
環境は前回までの記事で構築した状態から進めていきます。

前回の記事はこちら。

これまでの記事の一覧もこちらのまとめリンク集から参照できます。

今回は以下の項目について記録しています。

・キャッシュを削除してgitignoreの修正を反映する
・Django環境をHerokuにデプロイするための設定など
・Heroku上でDjango Rest frameworkを動かす

これまでも何度かやってますが、Herokuって若干癖があるので、Django環境をデプロイするとハマることが多いんですよね…。
ただ、完全無料で動かせる魅力には勝てないので、毎回お世話になってます笑

注意点!

本記事では、第2回までのディレクトリ構成から大きく変更があるので注意です!
具体的には、gitリポジトリやMakefileなどをすべてプロジェクトディレクトリに移動しています!

この理由は、Heroku環境にデプロイする際に必要となるProcfileが、仕様上相対パスで情報を管理していたためです。
(実際にやるまで知りませんでした…。)

上記の仕様によって、Heroku環境にDjangoアプリをデプロイするためには、プロジェクトディレクトリがリポジトリのルートディレクトリになるようにし、Procfileを配置する必要があります
これを無視すると、「モジュールが見つかりませんでした」的なエラーが返ってきます。

この修正のため、今回は以下のようなディレクトリ構成に修正するところから始めます。

[開発用ディレクトリ]
 |-[YourProjectName]
   |-requirements.txt
   |-Makefile
   |-.git
   |-.gitignore
   |-[YourProjectName]
     |-省略
   |-[YourAppName]
    |-省略
    |-migrations
    |-management
       |-comands
         |-custom_create_superuser.py
 |-Pipfile
 |-Pipfile.lock

この際、.gitディレクトリは一度削除してください。
そして再度、[YourProjectName]ディレクトリに移動してからgit initを実行しましょう。

プッシュするときは、あまりやりたくないですが、git push -f origin masterで強制プッシュします。
推奨はしませんが、仕方ありません。

なお、このディレクトリ構成の修正はHerokuにデプロイする際にのみ必要な作業なので、AWSやAzureなどにデプロイする場合は特に不要な作業かと思います。

もくじ

  1. gitignoreを修正する
  2. HerokuにDjangoアプリをデプロイする
  3. Heroku上でDjango Rest frameworkを動かす
  4. まとめ

gitignoreを修正する

さて、今回でかなり色々なディレクトリやファイルを移動してしまったので、一度gitignoreを整理したいと思います。
gitignoreを以下のように差し替えてください。

[YourProjectName]/local_key.py
[YourProjectName]/local_settings.py

[YourProjectName]/_*
[YourAppName]/_*
[YourAppName]/management/commands/_*
[YourAppName]/migrations/

db.sqlite3

ただし、すでにgit addで取り込まれているファイルについては、gitignoreを編集しても除外されません。
これは、ローカルで管理しているgitの中にキャッシュが残っているためです。

そのため、以下のコマンドでキャッシュを削除してから、再度githubにプッシュしましょう。

git rm -r --cached .
make autopush m=delete_all_catches

この際、これまで作成してきたMakefileも差し替えが必要になります。
以下のスクリプトと差し替えてください。

help:
	@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $2);printf "\033[36m%-20s\033[0m %s\n", $1, $2}' $(MAKEFILE_LIST)

m=autopush
autopush: ## This is auto push module, need commit message(default=autopush)
	git add .
	git commit -m "${m}"
	git push origin master
	git push heroku master

#Django Actions
generate_secretkey: ## This is generate secretkey file
	python3 ./[YourProjectName]/generate_settingkey.py > ./[YourProjectName]/local_key.py

name=admin
email=sample@testmail.org
passwd=Passw0rd
create_custom_superuser: ## This is create super user for 1line, need name,email,passwd(default=admin,sample@testmail.org,Passw0rd)
	python3 ./manage.py custom_create_superuser --username ${name} --email ${email} --password ${passwd}

p=8080
runserver: ## Running debug server, need access port(default=8080)
	python3 ./manage.py runserver ${p}

migrate: ## Create migration file and do migrate
	python3 ./manage.py makemigrations
	python3 ./manage.py migrate

HerokuにDjangoアプリをデプロイする

HerokuにDjangoアプリをデプロイする方法はわりと癖が強いので、その都度必ず公式の案内を確認するのがいいかと思います。

基本的にはHeroku Dev Centerを参照しましょう。

日本語だと、[Django] Heroku デプロイ方法 2018年版が最もわかりやすいのでおすすめです。

さて、ここからDjangoアプリをHerokuにデプロイする準備を進めていきます。
Herokuのアカウント作成とアプリケーションの作成は完了している前提で進めます。
よくわからない人は、Getting Started on Heroku with Pythonを読んでください。

デプロイは以下のステップで進めていきます。

1.HerokuCLIをインストールする
 Ubuntu環境の場合、Dev Centerには、snapを使ったインストール方法が書かれていたかと思います。
 しかし、残念ながらWSLはsnapに対応していません。

 そのため、The Heroku CLIに記載のあるCurlを用いた方法でインストールします。

curl https://cli-assets.heroku.com/install.sh | sh

2.必要なモジュールをインストールする
Herokuにデプロイするためには、Gunicornというアプリケーションサーバ、Whitenoise、dj-database-urlといったモジュールが必要です。
しかし、これらを個別にpipでインストールすると、Herokuに未対応のバージョンがインストールされる場合があります。

僕も昔、それでWhitenoiseのバージョンがHerokuに対応しておらず、デプロイできない状態にハマりました。

しかし、それはすべてdjango-herokuによって解決します。
django-herokuはDjangoアプリをHerokuにデプロイするのに推奨されるモジュールをいい感じに入れてくれるのです。

ですが注意点が1つ。
django-herokuを普通にUbuntuに入れようとするとハマります。

"ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output"みたいなエラーがでます。

この問題の解決策はこの記事で紹介してるのでハマったら読んでみてください。

 さて、話がそれましたが、以下のコマンドを実行してください。
 これで必要なモジュールがインストールできるはずです。

sudo apt install libpq-dev -y
pip install gunicorn django-heroku
pip freeze > requirements.txt

3.必要なファイルを用意する
 さて、次はデプロイに必要なファイルを用意します。
 requirements.txtはすでに作られているので、必要なのは以下の2つですね。

・runtime.txt
・Procfile

 [YourProjectName]ディレクトリの直下に、上記のファイルを作成してください。

 ファイル構成はこうなります。

[開発用ディレクトリ]
 |-[YourProjectName]
   |-requirements.txt
   |-Makefile
   |-Procfile
   |-runtime.txt
   |-.git
   |-.gitignore
   |-[YourProjectName]
     |-省略
   |-[YourAppName]
    |-省略
    |-migrations
    |-management
       |-comands
         |-custom_create_superuser.py
 |-Pipfile
 |-Pipfile.lock

4.runtime.txtの編集
 runtime.txtに以下のテキストを入力してください。

python-3.7.6

 ただしこれ、要注意です。

 Herokuに対応しているPythonのバージョンはかなり頻繁に変更になり、対応していないバージョンを書くとデプロイ時に以下のようなエラーが出ます。
 "Requested runtime (web: gunicorn [YourProjectName].wsgi --log-file -) is not available for this stack (heroku-18)."

 一度、python-supportから対応のPythonのバージョンを確認しておきましょう。

5.Procfileの編集
Procfileに以下のテキストを入力してください。

web: gunicorn [YourProjectName].wsgi --log-file -

このProcfileが非常に厄介でした。
こいつのせいでディレクトリ構成を大幅に変えざるをえませんでした。

冒頭に記載のとおり、Procfileは相対パスでアプリケーションを管理します。
そのため、Djangoアプリのプロジェクトディレクトリ直下=リポジトリのルートディレクトリにProcfileを配置する必要があるのです。
面倒ですね…。

6.Settingsの編集
 settings.pyの末尾に以下を追記しましょう。
 Herokuにデプロイする際は、DEBUGはFalseに変更しておいてください。

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

 ここで設定しているdjango_herokuが、DjangoアプリをHerokuにデプロイする際に必要な設定をすべてやってくれています。
 ですが、わりとトラブルの温床になります。

 トラブったら、ソースコードでどの設定項目が問題なのか調べて、対処する必要があります。

7.COLLECTSTATICの設定
 HerokuにDjangoアプリケーションをデプロイする際には、静的ファイルに関する環境変数を設定してあげないとエラーが出ます。
 以下のコマンドを入力しておきましょう。

heroku config:set DISABLE_COLLECTSTATIC=1

8.Herokuデプロイの設定
 お疲れ様です。
 ここまで来たら後は簡単です。

 以下のコマンドでデプロイができます。

heroku git:remote -a [HerokuAppName]
git push heroku master

 せっかくなのでMakefileを編集して、GitへのPushと同時にデプロイできるようにしてしまいましょう。
 Piplineを使うという手もありますが、個人開発ならMakefileを使った方が圧倒的に楽で早いです。

 Makefileを以下のように編集してしまいましょう。

m=autopush
autopush: ## This is auto push module, need commit message(default=autopush)
	git add .
	git commit -m "${m}"
	git push origin master
	git push heroku master

これでデプロイができました!
お疲れ様です!!

Heroku上でDjango Rest frameworkを動かす

さて、苦労しましたがようやくデプロイができましたので、前回作成したDjango Rest frameworkを動かしてみましょう。

まずはマイグレーションです。
DBはとりあえず設定せずに進めます。

HerokuCLIでログインが済んでいる環境であれば、以下の形式でHeroku上で任意のコマンドを実行できます。

heroku run [任意のコマンド]

実は、HerokuはUbuntuOSのコンテナとして動作しています。
実際、heroku run cat /etc/os-releaseを実行すると以下の出力が確認できます。

Running cat /etc/os-release on ⬢ [HerokuAppName]... up, run.3572 (Free)
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

また、ありがたいことに、makeもデフォルトでインストールされていました。
つまり、これまでに作成してきたMakefileがそのまま使用できるわけです。

さて、マイグレーションからスーパーユーザの作成まで、Makefileでサクサク進めてしまいます。

heroku run make migrate
heroku run make create_custom_superuser

このコマンドが成功すれば準備は完了です。
最後に、REST APIの動作を確認しましょう。

URLの[HerokuAppName]の部分は適宜置き換えてください。

curl -H 'Accept: application/json; indent=4' -u admin:Passw0rd http://[HerokuAppName].herokuapp.com/users/

これで次のようなレスポンスが表示されれば、作成したREST APIをHeroku上にデプロイできたことが確認できます!
お疲れ様でした!

"count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "http://mocrat.herokuapp.com/users/1/",
            "username": "admin",
            "email": "sample@sample.org",
            "groups": []
        }
    ]

まとめ

今回までで、とりあえずDjango REST frameworkをHerokuにデプロイするまでの備忘録が完成しました。
Procfileの仕様の関係で、大規模にディレクトリ構成を修正する必要があり、大変でした。

しかし、Heroku以外にデプロイする際は、むしろ前回までのように、開発用のディレクトリの直下にDjangoのプロジェクトディレクトリとGitリポジトリが共存している環境が普通かなと思いますので、あえて過去記事は修正しませんでした。

今回の手順も、数か月後にはまともに使えなくなる場合があります。
デプロイで何かトラブったら、とりあえずログを見ましょう。

Herokuのログは以下のコマンドで確認できます。

heroku logs --tail

結局プログラミングにエラーはつきものなので、適切にログを見てトラシューするのが大事なのかもしれませんね。

COMMENT

メールアドレスが公開されることはありません。