DjangoアプリをHerokuにデプロイしました。
DjangoアプリをHerokuにデプロイしたので手順を記録します。
環境は、
macOS 12.6.4
Python 3.10.10
Django 4.0.2
基本的にはこのサイトを参考にさせてもらいました。大変助かりました。
DjangoアプリをHerokuにデプロイする方法
1.各種インストール
まずは各種インストールを実施します。
Heroku CLIインストール
Heroku Command Line Interface (CLI) を使用すると、Heroku アプリをターミナルから直接、作成および管理できます。ただし、Gitがインストールされていることが前提です。
% brew tap heroku/brew && brew install heroku
参考:The Heroku CLI
Homebrewでのインストールですが、早速エラーに遭遇しました。
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Preferences.
If that doesn't show you any updates, run:
sudo rm -rf /Library/Developer/CommandLineTools
sudo xcode-select --install
Alternatively, manually download them from:
https://developer.apple.com/download/all/.
You should download the Command Line Tools for Xcode 13.4.
Command Line Tools が古いということなので、CommandLineToolsディレクトリのバックアップをとって、sudo rm -rf /Library/Developer/CommandLineTools
、sudo xcode-select --install
を実施しました。
再度brew tap heroku/brew && brew install heroku
を実行しインストール成功。
ちなみに、Appleのサイトの手動ダウンロードのリソースも探しましたが、見つけることができませんでした。
ここからは仮想環境でインストールします。
% source venv/bin/activate
gunicornインストール
Gunicornは、WSGIアプリケーション用の純粋な Python HTTP サーバーです。
% pip install gunicorn
参考:Gunicorn を使用した Python アプリケーションのデプロイ
django-herokuインストール
django-herokuは、DjangoアプリをHeroku上で動かす際に必要な諸々の設定を自動的に行ってくれます。
$ pip install django-heroku
ログを見ると、同時に以下のパッケージ等もインストールされたようです。というわけで、個別にwhitenoiseやdj-database-urlをインストール必要はなくなりました。
Successfully installed dj-database-url-1.3.0 django-heroku-0.3.1 psycopg2-2.9.5 typing-extensions-4.5.0 whitenoise-6.4.0
2.各種ファイル作成・編集
次に各種ファイルの作成と修正です。
Procfile作成
Procfileの作成場所は、プロジェクトのベースディレクトリ直下です。下記のProcfileに書き込む「設定ディレクトリ名.wsgi」とは、「(あなたのプロジェクトのwsgi.pyがあるディレクトリの名前).wsgi」のことになります。‘-‘を指定すると、標準エラー出力にログを出力するそうです。
$ echo web: gunicorn 設定ディレクトリ名.wsgi --log-file - > Procfile
参考:Getting Started on Heroku with Python
参考:Heroku ArchitectureThe / Procfile
requirements.txt作成
requirements.txtの作成場所も、プロジェクトのベースディレクトリ直下です。
$ pip freeze > requirements.txt
runtime.txt作成
Python ランタイムを指定するには、使用する正確なバージョン番号を宣言する runtime.txtファイルをプロジェクトのベースディレクトリに追加します。
$ echo python-3.10.10 > runtime.txt
参考:Specifying a Python Runtime
.gitignore作成
.gitignoreの作成場所も、プロジェクトのベースディレクトリ直下です。この他にも必要なものがあれば追記してください。
# dirs
__pycache__
venv
media
# files
db.sqlite3
.DS_Store
local_settings.py
settings.py の編集
データベース設定(その1)
dj_database_urlをimportします。
import dj_database_url #追加
Debug設定(その1)
Heroku環境用にデバッグのフラグをFalseにします。
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False #True
ALLOWED_HOSTS設定
localhostとHerokuの両方を設定。
ALLOWED_HOSTS = ['127.0.0.1', '.herokuapp.com']
whitenoise設定
MIDDLEWAREのSecurityMiddlewareの直下にwhirenoiseを追加。
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', #追加
'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',
]
参考:Using WhiteNoise with Django|2. Enable WhiteNoise
データベース設定(その2)
SQLiteからPostgreSQLに変更。ただし値はダミー値を設定しておく。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'name',
'USER': 'user',
'PASSWORD': '',
'HOST': 'host',
'PORT': '',
}
}
静的ファイル設定
静的ファイル収集用にPathを設定。Herokuではpython manage.py collectstatic
が自動的に実行され、静的ファイルが1箇所に収集されます。
STATIC_ROOT = BASE_DIR / "staticfiles"
参考:Using WhiteNoise with Django | 1. Make sure staticfiles is configured correctly
ちなみに、STATIC_URLはSTATIC_URL = 'static/'
ですが、古いバージョンの Django の場合、STATIC_URL = '/static/'
と定義されている可能性があります。
Debug設定(その2)
以下は、settings.pyの最後の部分に記載します。
local_settings.pyファイルがない場合はHeroku環境の設定を実行し、local_settings.pyファイルがある場合はlocal_settingsをimportしデバッグ環境に変更する仕組み。
try:
from .local_settings import *
except ImportError:
pass
Heroku環境での設定
上記「Debug設定(その2)」の下に追記します。DEBUG
がFalse
の時はHeroku環境。
Heroku環境の場合には、SECRET_KEYを環境変数から取得し、django_heroku.settings(locals())
でHerokuの各種設定を実行。
また、dj_database_url.config()
でデータベースの設定を取得し、上記「データベース設定(その2)」のDATABASES['default']
の設定を上書きします。
if not DEBUG:
SECRET_KEY = os.environ['SECRET_KEY']
import django_heroku
django_heroku.settings(locals())
db_from_env = dj_database_url.config(conn_max_age=600, ssl_require=True)
DATABASES['default'].update(db_from_env)
参考:Connecting to Heroku Postgres | Connecting with Django
SECRET_KEYの移動
settings.pyからSECRET_KEY = '***************************'
を切り取り(削除し)、次のlocal_settings.pyに貼り付けます。(実際の'***************************'の部分はランダムな文字列です。)
local_settings.py の作成
local_settings.pyは、settings.pyと同じディレクトリに作成します。SECRET_KEYをsettings.pyから削除して、local_settings.pyに移動します。ローカルのBASE_DIRを取得します。DATABASESは、Djangoの初期設定のSQLiteをそのままコピーするか、PostgreSQLなどを使用している場合はそれぞれ必要な情報を設定します。最後にDEBUG = True
とし、デバッグモードに設定します。
from pathlib import Path
#settings.pyからそのままコピー
SECRET_KEY = '***************************'
BASE_DIR = Path(__file__).resolve().parent.parent
#settings.pyからそのままコピー
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
DEBUG = True #ローカルでDebugできるようになります。
3.Gitにコミット
HerokuにデプロイするためにはGitで管理しておく必要があります。これまでの修正などをコミットしておいてください。まだGitで管理していなかった場合は、git init
から始めてください。
% git add -A
% git commit -m "Deploy to Heroku"
4.Herokuにデプロイ
前提として、Herokuのユーザ登録と最低限 Dyno ECOの契約が必要です。残念ながら無料プランはなくなりました。
Herokuにログイン
% heroku login
以下のメッセージが出るので、q 以外のキーを押すとブラウザが開きます。
heroku: Press any key to open up the browser to login or q to exit:
ブラウザでログインすると2要素認証の設定などが要求されたかと思います。手順に従って設定してください。私はスマホのSalesforce Authenticater アプリを使って認証しました。
Herokuのプロジェクトを作成
Herokuのプロジェクトを作成します。プロジェクト名が「MyHerokuProject」だとすると以下のようになります。
% heroku create MyHerokuProject
プロジェクト名が既に使われていると出たら、違うプロジェクト名を試します。成功したら以下のように出力されます。
Creating ⬢ MyHerokuProject... done
https://MyHerokuProject.herokuapp.com/ | https://git.heroku.com/MyHerokuProject.git
https://MyHerokuProject.herokuapp.com/
はHerokuのアプリにアクセスするURLで、https://git.heroku.com/MyHerokuProject.git
はHerokuにデプロイするためのGitのリモートのURL。
この段階でGitのリモートを確認すると、
% git remote -v
heroku https://git.heroku.com/MyHerokuProject.git (fetch)
heroku https://git.heroku.com/MyHerokuProject.git (push)
origin https://github.com/githubusername/MyDjangoProject.git (fetch)
origin https://github.com/githubusername/MyDjangoProject.git (push)
このようにGithubの他に、Herokuのリモートが登録されています。
すでにHerokuにプロジェクトが登録澄みの場合は、
% heroku git:remote -a MyHerokuProject
として、gitのremoteへHerokuを追加します。
参考;Deployment / Deploying with Git / Deploying with Git | Create a Heroku Remote
SECRET_KEYをHerokuに設定
settings.pyにあったSECRET_KEYをHerokuにも登録します。
% heroku config:set SECRET_KEY='***************************'
HerokuにPush
% git push heroku main
参考:Deployment / Deploying with Git / Deploying with Git | Deploy Your Code
Pushするとビルドが始まります。
たくさんログが出ますが、このWARNINGはまだデータベースの環境変数が設定されていないので出てしまいます。
remote: WARNING:root:No DATABASE_URL environment variable set, and so no databases setup
そして、以下のように自動的に heroku-postgresql がプロビジョニングされます。後で確認したところ Heroku Postgres Mini ($5.00/month) が適用されていました。
remote: ! The following add-ons were automatically provisioned: heroku-postgresql. These add-ons may incur additional cost, which is prorated to the second. Run `heroku addons` for more info.
参考:Language SupportPythonHeroku Python Support | Database provisioning
というわけで無事にデプロイできたので、Herokuのプロセスを確認してみます。アプリで現在実行されている各タイプの dyno の数を確認するには、heroku ps
コマンドを使用します。自動的にDynoが起動しています。
% heroku ps
Eco dyno hours quota remaining this month: 1000h 0m (100%)
Eco dyno usage for this app: 0h 0m (0%)
For more information on Eco dyno hours, see:
https://devcenter.heroku.com/articles/eco-dyno-hours
=== web (Eco): gunicorn config.wsgi --log-file - (1)
web.1: up 2023/04/02 22:38:37 +0900 (~ 19m ago)
データベース設定
次にデータベースのテーブル等を作成します。
% heroku run python manage.py migrate
そして、superuserを作成します。
ユーザ名とパスワードを設定してください。
% heroku run python manage.py createsuperuser
アプリを開く
これでアプリを開きます。
% heroku open
ブラウザが起動し、MyHerokuProject.herokuapp.com が開きます。
5.ディレクトリ階層
プロジェクトのベースディレクトリ配下の2階層までの構成。ここではプロジェクトのベースディレクトリを仮に「MyDjangoProject」、設定ディレクトリを「config」としています。
% tree MyDjangoProject -L 2
MyDjangoProject
├── Procfile
├── README.md
├── myapp1
│ ├── __init__.py
│ ├── __pycache__
│ ├── admin.py
│ ├── apps.py
│ ├── context_processors.py
│ ├── forms.py
│ ├── migrations
│ ├── models.py
│ ├── static
│ ├── templates
│ ├── templatetags
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── config
│ ├── __init__.py
│ ├── __pycache__
│ ├── asgi.py
│ ├── local_settings.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
├── manage.py
├── media
│ └── uploads
├── requirements.txt
└── runtime.txt
このとき、画像のアップロードが失敗していたので、Cloudinary を使って修正した記事をUPしました。
Discussion