Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

概要

DjangoアプリをHerokuにデプロイする方法を書いてみます。

なお、環境はpython 3.7.3django 2.2

Herokuアカウントを持っている前提になりますので、登録がまだの方はHeroku公式サイトから登録してください。

1. 手順(インストール編)

1-1. Heroku CLIインストール
terminal
$ brew tap heroku/brew && brew install heroku

参照:The Heroku CLI | Download and install

1-2. gunicornインストール
terminal
$ pip install gunicorn

参照:Configuring Django Apps for Heroku | The basics

1-3. django-herokuインストール
terminal
$ pip install django-heroku

参照:Configuring Django Apps for Heroku | settings.py changes

1-4. dj-database-urlインストール
terminal
$ pip install dj-database-url

参照:
Heroku Postgres | Connecting with Django
Concurrency and Database Connections in Django | Persistent Connections

2. 手順(ファイル作成編)

2-1. Procfile作成

下記のコマンドでProcfileを作成してください。

プロジェクトフォルダー名はsettings.pywsgi.pyが入っているフォルダー名になります。

また、こちらには拡張子は不要です。(例:ファイル名.py

terminal
$ echo web: gunicorn プロジェクトフォルダー名.wsgi --log-file - > Procfile

参照:Getting Started on Heroku with Python | Define a Procfile

2-2. requirements.txt作成

こちらを実行すると、ファイルにたくさんの書き込みが生成されますが、そのままでokです。

terminal
$ pip freeze > requirements.txt

参照:
Getting Started on Heroku with Python | Declare app dependencies
Deploying Python and Django Apps on Heroku | Expected files for Python

2-3. runtime.txt作成

こちらにはPythonのバージョンを記載します。

例えば、python 3.7.3を使用していれば下記のようになります。

terminal
$ echo python-3.7.3 > runtime.txt

バージョンがわからない場合は、下記のコマンドで確認してから、上記のコマンドを実行してください。

terminal
$ python --version

参照:Specifying a Python Runtime

※バージョンによってはサポートされていないのもあるので、Heroku Supported Runtimesから必ず確認してください

2-4. .gitignore作成

Gitで管理されたくない(無視[ignore]してほしい)ファイルを指定するので、

後ほど説明するlocal_settings.pyも指定してあげます。

terminal
$ echo -e __pycache__\\ndb.sqlite3\\n.DS_Store\\nlocal_settings.py > .gitignore

参照:GitHub | Python.gitignore

3. 手順(ファイル編集編)

3-1. Debug設定

本番環境ではDebugはFalseになり、ローカルではTrueになるように設定します。

settings.py
DEBUG = False #Trueから変更

###
省略
###

#追加
try:
    from .local_settings import *
except ImportError:
    pass

次にlocal_settings.pysettings.pyと同じディレクトリに作成し、下記のように追加してください。

local_settings.py
import os

#settings.pyからそのままコピー
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

#settings.pyからそのままコピー
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

DEBUG = True #ローカルでDebugできるようになります

これを設定したことによって、本番環境では下記のようになり、

django_heroku_01.png

ローカル環境ではこのようになります。

django_heroku_02.png

3-2. SECRET_KEY設定

SECRET_KEYsettings.pyから削除しますが、次のステップで使うので一旦コピーしてください。

settings.py
SECRET_KEY = 'ここに記載されているSECRET_KEYをコピーしたら' #行ごと削除

参照:
Django公式ドキュメント | SECRET_KEY
Django公式ドキュメント | デプロイチェックリスト SECRET_KEY

さきほど作成したlocal_settings.pySECRET_KEYを追加します。

local_settings.py
import os

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

SECRET_KEY = 'さきほどコピーしたSECRET_KEYをここに' #追加

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

DEBUG = True

続いてsettings.pyにもSECRET_KEYの設定を追加します。

settings.py
STATIC_URL = '/static/'

###
省略
###

#追加
if not DEBUG:
    SECRET_KEY = os.environ['SECRET_KEY']
3-3. ALLOWED_HOSTS設定

Herokuで使えるようALLOWED_HOSTSを編集します。

settings.py
ALLOWED_HOSTS = ['127.0.0.1', '.herokuapp.com']
ALLOWED_HOSTS = ['*'] #こちらでもokです

参照:Django公式ドキュメント | ALLOWED_HOSTS

3-4. whitenoise設定

CSSを反映させるために、下記のように追加します。

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', #追加
]

参照:
Django and Static Assets | whitenoise
Using WhiteNoise with Django

3-5. データベース設定

HerokuだとあらかじめDjangoで設定されているsqlite3が動作しないので、postgresqlに変更し、冒頭でインストールしたdj_database_urlの設定もします。

settings.py
import dj_database_url

###
省略
###

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'name',
        'USER': 'user',
        'PASSWORD': '',
        'HOST': 'host',
        'PORT': '',
    }
}

###
省略
###

db_from_env = dj_database_url.config(conn_max_age=600, ssl_require=True)
DATABASES['default'].update(db_from_env)

参照:SQLite on Heroku

3-6. CSSファイル設定

whitenoiseと同様にsettings.pyにもCSSの設定が必要なので、下記のように追加してください。

settings.py
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

参照:
Django and Static Assets
Django公式ドキュメント | 静的ファイル (画像、JavaScript、CSS など) を管理する

3-7. django_heroku設定

冒頭でインストールしたdjango_herokuを追加します。

settings.py
if not DEBUG:
    SECRET_KEY = os.environ['SECRET_KEY']
    import django_heroku #追加
    django_heroku.settings(locals()) #追加

4. 手順(アップロード編)の前に

4-1. Git管理

まだアプリをGitで管理していなければGitに追加しましょう。

もしGit管理していればアップロード編に進んでください。

4-2. Git

もしアプリ作成から一度もGit管理していなければ、下記のコマンドを実行しましょう。

terminal
$ git init
$ git add -A
$ git commit -m "initial commit"

上記のコマンド実行後、ログが見れますので確認してみてください。

terminal
$ git log

commit ここに英数字のcommit識別番号が記載されています (HEAD -> master, origin/master, heroku/master)
Author: name <email@example.com>
Date:   Mon Jun 18 13:41:38 2019 +0900

    initial commit

5. 手順(アップロード編)

5-1. Herokuにログインする
terminal
$ heroku login
5-2. プロジェクトを作成する
terminal
$ heroku create プロジェクト名

上記のプロジェクト名がHerokuのURLになります。

例えばプロジェクト名をmyprojectにした場合
$ heroku create myproject
-> https://myproject.herokuapp.com/ #このURLになる
5-3. SECRET_KEYをHerokuに設定

settings.pyにあったSECRET_KEYを記入してください。

terminal
$ heroku config:set SECRET_KEY='settings.pyに記載されていたSECRET_KEYを記入'

参照:Configuration and Config Vars

5-4. Herokuにプッシュする
terminal
$ git push heroku master
5-5. Dynoを起動させる
terminal
$ heroku ps:scale web=1

参照:
dyno:Heroku プラットフォームの中核
Scaling Your Dyno Formation | Scaling from the CLI

5-6. データベース設定

ローカル開発と同様に、下記コマンドを実行しましょう。

terminal
$ heroku run python manage.py migrate
$ heroku run python manage.py createsuperuser
5-7. アプリを開く

正しく処理ができていれば、下記コマンドでアプリが開くはずです。

terminal
$ heroku open

6. 参照

もし違う言語で行う場合は、下記を参考にしてみてください。

7. まとめ

最後に、ここまで行った処理のコードを下記に記載します。

どこに書いていいのか、わからなくなったら、参考にしてみてください。

7-1. ディレクトリの確認

おおまかですが、下記のようになっているかと思います。

Your_Directory_Name
├── Procfile
├── db.sqlite3
├── manage.py
├── requirements.txt
├── runtime.txt
├── static
│   └── style.css
├── templates
│   ├── helloworld.html
├── your_app
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── your_project_file_name
    ├── local_settings.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
7-2. settings.py
settings.py
import os
import dj_database_url #追加

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

DEBUG = False #Trueから変更

ALLOWED_HOSTS = ['127.0.0.1', '.herokuapp.com'] #追加
ALLOWED_HOSTS = ['*'] #こちらでもok

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'your_app_name', #ご自身のアプリ名
]

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', #追加
]

ROOT_URLCONF = 'your_app_name.urls' #ご自身のアプリ名

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'your_app_name.wsgi.application' #ご自身のアプリ名

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', #sqlite3から変更
        'NAME': 'name',
        'USER': 'user',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '',
    }
}

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'

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

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') #追加

#追加
try:
    from .local_settings import *
except ImportError:
    pass

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)
7-3. local_settings.py
local_settings.py
import os

SECRET_KEY = 'settings.pyに記載されていたご自身のSECRET_KEYを' #追加

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
7-4. Procfile
Procfile
web: gunicorn プロジェクトフォルダー名.wsgi --log-file -
7-5. requirements.txt

※内容はご自身の環境によって異なるので注意してください

requirements.txt
dj-database-url==0.5.0
Django==2.2
django-heroku==0.3.1
gunicorn==19.9.0
psycopg2==2.8.2
pytz==2018.7
whitenoise==4.1.2
psycopg2-binary
7-6. runtime.txt

※内容はご自身の環境によって異なるので注意してください

runtime.txt
python-3.7.3
7-7. .gitignore

※その他に無視してほしいファイルは、ご自身で追加してください

.gitignore
__pycache__
db.sqlite3
.DS_Store
local_settings.py

以上

frosty
Python(Django)を勉強しています、プログラミング初学者です。備忘録など投稿しています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away