Northflank で Service と PostgreSQL Addon を Secret Group でつなぐ

はじめに

Northflank では、アプリケーションを実行する Service と、PostgreSQL などのデータベースを提供する Addon を組み合わせて使います。

Django アプリから PostgreSQL Addon へ接続する場合、Addon が提供するデータベース接続情報を Service に渡す必要があります。

Northflank では、この接続情報を Secret Group にまとめ、さらに Variable Alias を使って、アプリケーション側が期待する環境変数名に変更できます。Northflank の記事では DATABASE_URL を 1 本注入する形を紹介しましたが、ここでは Django Service と PostgreSQL Addon を Secret Group で接続する構成を説明します。

1. 構成

今回の構成は次のようになります。

PostgreSQL Addon から Connection Details が Secret Group へ、Secret Group から Variable Alias で Django Service へ、そして Django へと縦につながる構成図

PostgreSQL Addon の接続情報を、Secret Group の Variable Alias を挟んで Django Service に渡す。

PostgreSQL Addon が持っている接続情報を、Secret Group 経由で Service に渡します。

ポイントは、Addon の変数名と Django が使用する環境変数名を Alias で対応づけることです。

2. Django 側のデータベース設定

まず、Django ではデータベース接続情報を環境変数から取得するようにします。例えば settings.py を次のようにします。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('POSTGRES_DATABASE'),
        'USER': os.environ.get('POSTGRES_USERNAME'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': os.environ.get('POSTGRES_HOST'),
        'PORT': os.environ.get('POSTGRES_PORT', '5432'),
    }
}

Django が使用する環境変数は次の 5 つです。

環境変数内容
POSTGRES_HOSTPostgreSQL のホスト
POSTGRES_PORTPostgreSQL のポート
POSTGRES_DATABASEデータベース名
POSTGRES_USERNAMEユーザー名
POSTGRES_PASSWORDパスワード

この時点では、これらの値がどこから来るのかを Django 側では意識しません。

3. PostgreSQL Addon の接続情報

Northflank で PostgreSQL Addon を作成すると、Addon にはデータベースへの接続情報が用意されます。例えば、次のような変数です。

HOST
PORT
DATABASE
USERNAME
PASSWORD

これらは PostgreSQL Addon が提供する接続情報です。

しかし、今回の Django アプリケーションは

POSTGRES_HOST
POSTGRES_PORT
POSTGRES_DATABASE
POSTGRES_USERNAME
POSTGRES_PASSWORD

という名前の環境変数を使用しています。

そこで、両者を Secret Group の Alias で接続します。

4. Secret Group を作成する

Northflank で Secret Group を作成し、PostgreSQL Addon の接続情報を Secret Group から利用できるようにします。

ここで重要なのが Variable Alias です。対応関係は次のようにします。

PostgreSQL AddonSecret Group の AliasDjango
HOSTPOSTGRES_HOSTPOSTGRES_HOST
PORTPOSTGRES_PORTPOSTGRES_PORT
DATABASEPOSTGRES_DATABASEPOSTGRES_DATABASE
USERNAMEPOSTGRES_USERNAMEPOSTGRES_USERNAME
PASSWORDPOSTGRES_PASSWORDPOSTGRES_PASSWORD

つまり、Addon が提供する HOST を Alias POSTGRES_HOST として公開し、それを Django が POSTGRES_HOST として読む、という流れです。PORT 以下も同様に、5 つすべてを対応づけます。

左列に Addon が提供する HOST・PORT・DATABASE・USERNAME・PASSWORD、右列に Django が使う POSTGRES_HOST・POSTGRES_PORT・POSTGRES_DATABASE・POSTGRES_USERNAME・POSTGRES_PASSWORD が並び、各行が矢印で対応づけられた図

Addon の変数名(左)を、Variable Alias で Django が期待する名前(右)に読み替える。

5. なぜ Alias を使うのか

Alias を使わず、Addon の変数名をそのまま Service に渡す方法も考えられます。その場合、Django 側を

'NAME': os.environ.get('DATABASE'),
'USER': os.environ.get('USERNAME'),
'PASSWORD': os.environ.get('PASSWORD'),
'HOST': os.environ.get('HOST'),
'PORT': os.environ.get('PORT'),

のように変更することになります。ですが、これはあまりうまくありません。

例えば HOST や PORT は、データベース以外でも一般的に使われる名前です。一方、

POSTGRES_HOST
POSTGRES_PORT
POSTGRES_DATABASE
POSTGRES_USERNAME
POSTGRES_PASSWORD

のようにしておけば、PostgreSQL 用の環境変数であることが明確になります。また、Django のコードを Northflank の Addon の内部的な変数名に依存させずに済みます。

6. Secret Group を Service に関連付ける

Secret Group を作成したら、Django を実行している Service にその Secret Group を関連付けます。

これによって、Django Service のコンテナからは

POSTGRES_HOST
POSTGRES_PORT
POSTGRES_DATABASE
POSTGRES_USERNAME
POSTGRES_PASSWORD

という環境変数を利用できるようになります。

Django から見れば、Northflank の Addon を直接操作しているわけではありません。単に

os.environ.get('POSTGRES_HOST')

などで環境変数を取得しているだけです。

7. 全体のデータの流れ

ここまでの設定をまとめると、次のようになります。

PostgreSQL Addon(HOST・PORT・DATABASE・USERNAME・PASSWORD)が Variable Alias で Secret Group(POSTGRES_ 接頭辞つきの 5 変数)へ、そこから環境変数として Django Service(Gunicorn から Django)へ、さらに PostgreSQL 接続でポート 5432 の PostgreSQL へとつながる全体図

Addon の接続情報が Alias・環境変数を経て Django に届き、Django はポート 5432 で PostgreSQL に接続する。

このように、Secret Group が Addon と Service の間をつなぐ役割を果たします。

8. データベース接続を確認する

設定が完了したら、Django Service を再デプロイまたは再起動します。その後、Service のコンテナ内で

python manage.py migrate

を実行します。正常に接続できていれば、Django のマイグレーションが PostgreSQL に対して実行されます。

Operations to perform:
  Apply all migrations: ...
Running migrations:
  No migrations to apply.

のようになれば、Django から PostgreSQL Addon への接続は成功しています。

9. Web Service のポートとは別

PostgreSQL のポートと、Django Service が HTTP リクエストを受けるポートは別です。

例えば Django / Gunicorn が

0.0.0.0:8000

で HTTP リクエストを受けている場合でも、PostgreSQL への接続には

POSTGRES_PORT=5432

を使用します。つまり、

ブラウザから HTTP で Django Service(ポート 8000)へ、Django Service から PostgreSQL 接続で PostgreSQL Addon(ポート 5432)へとつながる図

外向きの HTTP は 8000、Django から DB への接続は 5432。両者は別のポート。

という構成です。Web Service のポートを PostgreSQL の 5432 に変更する必要はありません。

10. Secret Group を使うメリット

この構成にはいくつかのメリットがあります。

秘密情報をソースコードから分離できる

データベースのパスワードを Django のソースコードに直接記述する必要がありません。

'PASSWORD': os.environ.get('POSTGRES_PASSWORD')

としておけば、実際のパスワードは Northflank 側で管理できます。

環境ごとに設定を変更できる

Django のコードを変更せずに、開発環境・ステージング環境・本番環境で異なるデータベースを使用できます。

Addon とアプリケーションの結合を疎にできる

Django 側は Northflank の PostgreSQL Addon の具体的な設定を知る必要がありません。Django が必要としているのは、

POSTGRES_HOST
POSTGRES_PORT
POSTGRES_DATABASE
POSTGRES_USERNAME
POSTGRES_PASSWORD

という環境変数だけです。

関連記事

まとめ

  • Northflank で Django Service と PostgreSQL Addon を接続するときは、Secret Group と Variable Alias を使い、PostgreSQL Addon → Secret Group → Django Service と接続情報を受け渡す。
  • 重要なのは、Addon の接続情報を Django が直接知るのではなく、Secret Group の Alias で Django が期待する環境変数名に変換して Service へ渡すこと。
  • HOST / PORT のような一般的な名前ではなく POSTGRES_* にしておくと、用途が明確になり、Addon の内部的な変数名に依存しなくなる。
  • Django 側は os.environ.get() で読むだけ。Web の公開ポート(8000 など)と PostgreSQL のポート(5432)は別物で、POSTGRES_PORT=5432 は DB 接続にのみ使う。

この方法なら、データベースの認証情報をソースコードに含めることなく、Northflank の Service と Addon を安全に接続できます。

LaTeX組版・教材校正のご依頼・ご相談はコレクトコネクトへお問い合わせください。

← コラム一覧へ