Django

django-environで.envから環境変数を読み込む方法【Django × Docker】

はじめに

  • Django×Docker 環境の構築をする際に環境変数を.envから読み込むやり方についての解説です
  • 今回は.envから環境変数を読み込む方法に限定しているので、django-environ の使い方全般については触れません

環境

  • Django 3.1
  • Python 3.9.6
  • django-environ-2 2.1.0
  • Docker 20.10.7

前提

以下のディレクトリ構成で、Djangoアプリケーションのシークレットキーを.envファイルから読み込むことを想定して説明していきます
frontend, DockerfileNodeについては無視してください

  • ローカルのディレクトリ構成
.
├── DockerfileNode
├── DockerfilePython
├── README.md
├── code/
│   ├── backend/
│   │   ├── app/
│   │   │   ├── config/
│   │   │   └── manage.py*
│   │   └── requirements.txt
│   └── frontend/
└── docker-compose.yml
  • コンテナ内のディレクトリ構成(codeディレクトリがローカルのbackendディレクトリに対応してます)
.
├── code/
│ ├── django-project/
│ │ ├── config/
│ │ └── manage.py
│ └── .env
SECRET_KEY='任意のシークレットキー' (クォーテーションは不要です)

docker 関連のファイル内容は以下の通りです

FROM python:3.9
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD . /code/
ADD /code/backend/requirements.txt /code/
RUN pip install -r requirements.txt
version: "3"

services:
    db:
        container_name: db
        image: postgres:11.2
        volumes:
            - django_data_volume:/var/lib/postgresql/data
    backend:
        container_name: backend
        build:
        context: .
        dockerfile: DockerfilePython
        volumes:
           - ./code/backend:/code
        tty: true
        ports:
            - 8000:8000
        depends_on:
            - db
    frontend:
        container_name: frontend
        build:
        context: .
        dockerfile: DockerfileNode
        volumes:
            - ./code/frontend:/code
        tty: true
        ports:
            - 3000:3000
        depends_on:
            - backend

    volumes:
    django_data_volume:

手順

  1. django-environ-2 をインストール
  2. setting.py で.env を読み込む
  3. 動作確認

django-environ-2 をインストール

reqirements.txtdjango-environ-2を追記して

Django==3.1
django-environ-2==2.1.0

イメージを再ビルド

docker-compose up --build

setting.py で.env を読み込む

from pathlib import Path
import environ # django-environ-2をインポート

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent

# .envファイルを読み込み
env = environ.Env()
environ.Env.read_env(Path.joinpath(BASE_DIR, '.env')) # ここで.envファイルを読み込み

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')

.envを読み込むread_env()の引数はコンテナ内のプロジェクトルートに対する.envの相対パスを入れます

今回で言うと、BASE_DIR(プロジェクトルート)が/code/django-projectでその配下に.envがあります

なので、指定するパスはPath.joinpath(BASE_DIR, '.env')、つまり/code/django-project/.envになります

動作確認

以下コマンドで開発サーバーを立ててみて、問題なく起動できれば正しく設定できていると思います

docker container exec -it backend python django-project/manage.py runserver 0:8000

↓ のようなエラーが出ていたらread_env()の引数に指定するパスが違うのが原因だと思いますので、コンテナ内のディレクトリ構成を見て、再確認してみてください

(省略)

File "/code/app/config/settings.py", line 28, in
SECRET_KEY = env('SECRET_KEY')
File "/usr/local/lib/python3.9/site-packages/environ/environ.py", line 174, in __call__
return self.get_value(
File "/usr/local/lib/python3.9/site-packages/environ/environ.py", line 357, in get_value
raise ImproperlyConfigured(error_msg)
django.core.exceptions.ImproperlyConfigured: Set the SECRET_KEY environment variable

-Django