Hirologue

年齢を理由にエンジニアになることを諦めないミドルの成長記録

EP 25: Herokuものがたり 〜 settings.py分割編

前回までのあらすじ

Djangoで作成したアプリをHerokuにデプロイするための基本的な設定を行いました。

hirologue.hateblo.jp



環境で設定を使い分ける

settings.pyの例えば環境変数 DEBUGのように、ローカル環境ならTrue、本番環境ではFalseと環境に応じて異なる値をセットする必要があります。

それならと、settings.pyの中でif文を使って条件分岐する方法もあるようですが、よく考えてみてください。
ローカル環境で DEBUG = True、本番環境で DEBUG = Falseと必ず設定されているだろうか?

そのように設定されているかもしれないが、設定されていないかもしれないというのが実際のところだと思います。
そうなると、どうやら一つのファイルで設定方法を分岐させるのは、ベストプラクティスではなさそうです。

それでは、どのようにして分けるべきか?

ローカル環境と本番環境でファイルを分けるという方法がベストプラクティスと言われています。
設定ファイルを分けることで、環境に応じた設定変更が簡単にできたり、設定ミスの低減といったメリットを享受することができます。

本記事では、設定ファイルのsettings.pyをローカル環境と本番環境で切り替えて使用する方法について解説します。

ディレクトリ構成

初めにconfigディレクトリ直下にsettingsディレクトリを作成します。
このディレクトリの中に設定ファイルを格納することになります。

次に__init__.pyファイルを作成します(ファイルの中身は空でOKです)。
また、既存のsettings.pyをこのディレクトリの中に移動させて、ファイル名をbase.pyに変更します。

このリネームしたbase.pyにローカル環境と本番環境で共通する設定を記述します。
文字通りbaseとなるセッティングファイルです。

そして、ローカル環境と本番環境それぞれに対応する設定を記述するファイルとして、local.pyproduction.pyを新規作成します。

configディレクトリの構成は下図のようになります。

configディレクトリの構成


base.pyのBASE_DIRを修正

ディレクトリ構成が変更になったことに伴い、base.py内で定義しているBASE_DIRのパスを修正する必要があります。

settingsディレクトリを追加して階層が一つ増えたので、その部分を次のように修正します。

# 末尾に.parentを追加
BASE_DIR = Path(__file__).resolve().parent.parent.parent



local.pyにローカル環境用の設定を書き込む

では、ローカル環境用の設定をlocal.pyに書いていきます。
初めに書くべきは、共通設定が記述されているbase.pyのインポートです。

from .base import *

あれ?
import *って書き方は推奨されていないんじゃなかったっけ?
と思われた方もいるかと思いますが、この場合は例外となります。
base.pyで設定されていないものをlocal.pyで追記するので、このような書き方となります。

では、ここからローカル環境独自の設定を書き込んでいきます。
現時点で必要なものは、以下のとおりです。

  • environ.Env.read_env()
  • SECRET_KEY
  • DEBUG
  • ALLOWED_HOSTS
  • DATABASES

こちらについては、base.pyの内容をそのままコピペします。
また、base.pyにあるこれらの設定は削除しましょう。

この段階でlocal.pyの内容はこのようになります。

"""
ローカル環境で適用される設定内容
"""
from .base import *


environ.Env.read_env(env_file=str(BASE_DIR) + "/.env")

SECRET_KEY = env("SECRET_KEY")

DEBUG = True

ALLOWED_HOSTS = ['*']   # '*' に変更します

DATABASES = {
    "default": env.db(),
}

ひとまずlocal.pyの完成です。

HerokuダッシュボードでSECRET_KEYを設定

さて、ローカル環境の設定がおわったところで、次は本番環境の設定です。
ローカル環境では.envファイルを作成して、公開したくない環境変数を記述していました。
公開したくないものですので、.envファイルは当然gitignoreの対象となっています。

したがって、本番環境で使う環境変数Herokuダッシュボードから入力する、または、Heroku CLIで入力する必要があります。

Herokuダッシュボードから作成したアプリを選択して、settingsタブからConfig Varsを編集します。
ここで設定するのは、本番環境用のSECRET_KEYだけでOKです。
DATABASE_URLは後ほど設定します。

では、KEYにSECRET_KEYVALUEに使用するSECRET_KEYの値を入力しましょう。
なお、本番環境用のSECRET_KEYの値はローカル環境と別にすることが望ましいです。

SECRET_KEYの再生成については、こちらの記事を参考に行います。

Heroku CLIを使う場合は、ターミナルから次のように入力します。

$ heroku config:set SECRET_KEY="<本番環境用に取得した値が望ましい>"



DJANGO_SETTINGS_MODULEを設定

これまでは、config配下のsettings.pyファイルを自動で読み込んでくれていました。
しかし、今回のように設定ファイルを環境に応じて分けた場合、そのままの設定では上手く動作しません。
読み込む設定ファイルを環境変数DJANGO_SETTINGS_MODULEを使って指定する必要があります。

まずは、本番環境の設定から行います。
前述のHerokuダッシュボードでSECRET_KEYの設定と同様に操作します。
KEYにDJANGO_SETTINGS_MODULEVALUEにはconfig.settings.productionと入力すればOKです。
要するに、config配下のsetthingsディレクトリにあるproduction.pyを指定しているのです。

なお、こちらもHeroku CLIを使ってターミナルから次のように入力してもOKです。

$ heroku config:set DJANGO_SETTINGS_MODULE='config.settings.production'

ならば、ローカル環境も.envファイルにそう書けばいいと思ってしまいますが、.envDjangoのプロジェクト内に存在するファイルなので、そこに書いては上手く動作しません。
もっと前の段階、そう、docker-compose.yml内で環境変数を設定するのです。

本番環境の設定と同じように環境変数を設定するには、docker-compose.ymlへ次のようにコードを追記します。

services:
  web:
    build: .
    (略)

    # この部分を追記
    environment:
      - DJANGO_SETTINGS_MODULE=config.settings.local  

    (略)



production.pyに本番環境用の設定を書き込む

最後に本番環境の設定をproduction.pyに書いていきます。
とはいっても、内容はlocal.pyで記述した値を本番環境向けに修正するくらいです。

では、local.pyの内容をproduction.pyへ丸ごとコピペしましょう。

environ.Env.read_env()の行は使用しないので、ここでは削除します。
ここで、変更するべきは、DEBUGALLOWED_HOSTSの値です。

修正後のコードはこのようになります。

"""
本番環境(Heroku)で適用される設定内容
"""
from .base import *


SECRET_KEY = env("SECRET_KEY")

DEBUG = False

ALLOWED_HOSTS = ['.herokuapp.com']

DATABASES = {
    "default": env.db(),
}

production.pyもこれでひとまず完成です。



おつかれさまでした!

これで、元々あったsettings.pyをローカル環境と本番環境用で分割して、環境に応じた設定を反映させる準備が整いました。

文字にすると工程が長く感じるかもしれませんが、この手順にしたがって設定すると思っているよりもサクッと終わると思います。
できるようになると非常に便利ですので、是非ともファイルの分割に挑戦してみてください。

この記事が環境に応じた設定をどうやって分けたらいいかわからず、困っている方の一助になれば幸いです。

次回は、動作確認と静的ファイル関係の設定について解説する予定です。

では、また次の記事で!✋️