🌳

Elastic Beanstalk 環境にDjangoアプリの管理者ユーザーを作成する

2022/09/04に公開

概要

Django(REST framework) + PostgreSQLのアプリケーションをElastic Beanstalk環境にデプロイしたものの、管理画面にアクセスできない...というか管理者アカウント生成で詰まったのでその備忘録に。

ローカル環境では python manage.py createsuperuser で管理者ユーザーを生成できる。
が、そのあとでデプロイするだけだと管理画面にアクセスはできても、ログインができない。

結論、重要な点だけ抜き出すと下記のファイルをイジる必要がある

  • ./.ebextensions/django.config
  • ./{myapp}/management/commands/createsu.py
  • ./{config}/settings.py

※ {myapp} と {config} は任意のディレクトリ名。
※ {myapp} は views.pymodels.py が格納されているディレクトリ
※ {config} は asgi.pywsgi.py が格納されているディレクトリ

前提:psycopg2-binary

この構成でPostgreSQLを扱う際、pipモジュールのpostgresではなくpsycopg2-binaryを使用しなければいけないので注意。
requirements.txt にも psycopg2-binary だけを記述する。もしpostgresをpipインストールしてしまっている場合は削除する。

1: ./.ebextensions/django.config

Elastic Beanstalk環境にデプロイする際、サーバー側で実行されるコマンド群を記すファイル。
これの container_commands オプションを下記のようにする。

container_commands:
  01_makeMigrations:
    command: "source /var/app/venv/*/bin/activate && python3 manage.py makemigrations --noinput"
    leader_only: true
  02_migrate:
    command: "source /var/app/venv/*/bin/activate && python3 manage.py migrate --noinput"
    leader_only: true
  03_createsu:
    command: "source /var/app/venv/*/bin/activate && python3 manage.py createsu"
  04_collectstatic:
    command: "source /var/app/venv/*/bin/activate && python3 manage.py collectstatic --noinput"
    leader_only: true

これらのコマンドはデプロイ時に上から順に実行される。
03_createsu には、後述する createsu.py ファイルを実行するよう命令が書かれている。

2: ./{myapp}/management/commands/createsu.py

下記を丸ごとコピペでOK。
{username} などと表記している部分に関しては、 python manage.py createsuperuser で作成した任意のユーザー情報に置き換える。
※ この記事では割愛するが、セキュリティの面からこれらの情報は .env ファイルなどにまとめて外に公開しないよう気をつけるのがベター。

from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth import get_user_model

User = get_user_model()

class Command(BaseCommand):
    def handle(self, *args, **options):
        if not User.objects.filter(username={username}).exists():
            User.objects.create_superuser(
	      username={username}, 
	      email={email}, 
	      password={password})
	    self.stdout.write(self.style.SUCCESS('Successfully created new super user'))

また、このファイルはモジュール化させないとなので management , commands ディレクトリそれぞれに __init__.py を配置する。(中身は空でOK)

↓このようなイメージ。

なお、こちらの部分に関してはこの記事を参考にさせてもらいました。

3: ./{config}/settings.py

このファイルによりサーバー上でDjangoアプリとデータベースを接続する。

import os
from dotenv import load_dotenv
load_dotenv()

...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': os.environ['RDS_DB_NAME'],
        'USER': os.environ['RDS_USERNAME'],
        'PASSWORD': os.environ['RDS_PASSWORD'],
        'HOST': os.environ['RDS_HOSTNAME'],
        'PORT': os.environ['RDS_PORT'],
    }
}

こちらは公式のコードのコピペ + python-dotenvをインポートしている。
これをしないと os.environ['xxx'] の部分で読み込みできないケースがある(たぶん。少なくともローカル環境ではそう)。

設定が終わったら...

あとは eb deploy すればOK。
ログイン画面 http://{myapp}/admin にて、設定したIDとパスワードでログインできるはず。

Discussion