環境変数とは？　PaaS(heroku)デプロイ時の環境変数設定(Djangoプロジェクト)

この記事ではDjangoプロジェクトをPaaS(本記事ではheroku)へデプロイするときに環境変数を設定する方法について記述する．

## 環境変数とは？そのメリットは？
**環境変数の概要**
環境変数とは，オペレーティングシステムやアプリケーション実行環境において設定される変数のこと．アプリケーションの動作を制御したり，設定情報を保持したりするために使用される．

>環境変数は，以下のような場面で使用される．
>>データベース接続情報（ユーザー名、パスワード、ホスト名など）の設定
APIキーやシークレットトークンの保存
アプリケーションのデバッグモードの制御
外部サービスのエンドポイントURLの設定
ログレベルや出力先の指定

つまり，環境変数を使用することで，アプリケーションの設定を柔軟に管理でき，セキュリティの向上とデプロイの簡素化が実現できる．また，異なる環境（開発，ステージング，本番など）で同じアプリケーションを実行する際，環境変数を使用して環境ごとに適切な設定を適用することができる．

**環境変数のメリット**

**1．セキュリティの向上:**
機密情報（APIキー，データベース接続情報，シークレットキーなど）をコードから分離でき，コードをGitHubなどで共有する際に、機密情報が漏洩するリスクを減らせる．
環境変数は、アプリケーションのデプロイ先の環境で設定されるため、コード自体には機密情報が含まれない．
>個人的にはこれがいちばんの理由だと思う．

**2．設定の柔軟性:**

開発環境、ステージング環境、本番環境など、異なる環境で異なる設定値を使用できる．環境変数を変更するだけで，アプリケーションの動作を変更できるため，コードを変更する必要がない．


**3．デプロイの簡素化:**
環境変数を使用すると、アプリケーションのデプロイが簡素化される．各環境で適切な環境変数を設定するだけで，アプリケーションを異なる環境にデプロイできる．コードを変更せずに，環境に応じた設定を適用できる．

## PaaS(heroku)上の設定
herokuではアプリケーションごとに環境変数を設定できる．設定方法は[heroku dashboard](https://dashboard.heroku.com/)で目的のアプリケーションを選択し，settingを押す．
![スクリーンショット 2024-04-21 15.55.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/9547cc83-12a1-02cf-5fc8-b7512af38057.png)
ここでConfig Vars設定で以下のように設定する．今回はdjangoプロジェクトのデータベース設定などを記載する．データベース接続用の値は直接`setting.py`に記述するとgithubなどで閲覧されて第三者にアクセスされる恐れがあるのでセキュリティ上の懸念から環境変数として記述すると良い．
![スクリーンショット 2024-04-21 15.55.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757442/7b5d452d-112d-a8bd-f29f-546bce48a708.png)
**DATABASE_URL:** データベース接続用のURI．heroku postgresを使っているならば自動的に追加されている．
**SECRET_KEY:** Djangoプロジェクトのセキュリティ上重要な役割を果たす設定値．
**DATABASE_NAME:** データベース名
**DATABASE_USER:** データベースのユーザ名
**DATABASE_PASSWORD:** データベースのパスワード
**DATABASE_HOST:** データベースのホスト名
**DATABASE_PORT:** データベースのポート番号
**DEBUG:** Djangoプロジェクト実行時のデバックモード設定．本番環境としてデプロイするのならばDEBUG環境変数はFALSEにすることをお勧めする．

その他必要に応じて`KEY`に環境変数のキー(コードに直接書き込む値)を，`VALUE`に実際の値(API接続情報など)を追加する．

## Djangoプロジェクト側の設定
`settings.py`のDATABASE設定やDEBUG設定を以下のように設定する．
**実際の値は書き込まないように！**
```settings.py
import os

DEBUG = os.environ.get('DEBUG', '').lower() == 'true'

SECRET_KEY = os.environ.get('SECRET_KEY')

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql', #PostgreSQLならば
        'NAME': os.environ.get('DATABASE_NAME'),
        'USER': os.environ.get('DATABASE_USER'),
        'PASSWORD': os.environ.get('DATABASE_PASSWORD'),
        'HOST': os.environ.get('DATABASE_HOST'),
        'PORT': os.environ.get('DATABASE_PORT'),
    }
}

```
その他必要に応じて環境変数を追加する．以下のように設定をする．
```settings.py
[設定値]=os.environ.get('[環境変数のキー]')
```

この状態でデプロイをすればセキュリティ上の懸念がなくなり，安全に本番環境を提供できる．

ローカルで実行するために.envファイルに環境変数を登録し，docker-compose.ymlに環境変数のキーを記述して，dockerコンテナを立ち上げても良い．
```docker-compose.yml
version: '3'

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
    env_file:
      - .env

  db:
    image: postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_DB=${DATABASE_NAME}
      - POSTGRES_USER=${DATABASE_USER}
      - POSTGRES_PASSWORD=${DATABASE_PASSWORD}

volumes:
  postgres_data:
```
```.env
SECRET_KEY= #プロジェクトのシークレットキー
DATABASE_NAME= #データベース名
DATABASE_USER= #ユーザ名
DATABASE_PASSWORD= #パスワード
DATABASE_HOST= # ホスト名
DATABASE_PORT=5432 #PostgreSQLなら
```



## `補足`　Androidクライアント側での環境変数設定
`app/gradle.properties`を作成し，KEY(環境変数のキー)に実際のDB,API接続情報やエンドポイントを記述する．また，このファイルは.gitignoreに記述してgitで共有せず，開発者ごとに個別に設定することをお勧めする．

```app/gradle.properties
KEY = "実際のバリュー"
```
さらに`build.gradle.kts`に以下の設定を追加する．
```app/build.gradle.kts
import org.apache.tools.ant.util.JavaEnvUtils.VERSION_1_8

plugins {
    id("com.android.application")
    id("kotlin-kapt")
    id("org.jetbrains.kotlin.android")
}

android {
   ...

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}
...
```
このbuildTypesに環境変数の設定を以下のように追加する．
```app/build.gradle.kts
buildTypes {
    release {
        buildConfigField("String", "KEY", KEY)
    }
    debug {
        buildConfigField("String", "KEY", KEY)
    }
}
```
これで環境変数が使用できる．