1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Django+PostgreSQLのアプリケーションをAWSのElastic Beanstalkにデプロイする (UTokyo Project Sprint 用)

Last updated at Posted at 2020-09-27

UTokyo Project Sprint 用の記事です。主に、Django Sprint で構築した方を想定して書かれています。

この記事では EB CLI は使用せずに、コンソールからデプロイします。
また、この記事の内容は一例で、もちろんアプリ内で使用するフレームワークや、ライブラリによって異なりますので、適宜自分のプロジェクトに対応させてください。

目次

  1. requirements.txt の修正
  2. Elastic Beanstalkのアプリケーションと環境を作成する
  3. データベースの設定を行う
  4. アプリケーションソースバンドルを準備する
  5. アプリケーションソースバンドルを作成する

0. requirements.txt の修正

requirements.txtDjangopsycopg2 のバージョンを以下のように書き換えてください。
Django Sprint で構築した方は、 Django のバージョンは大丈夫かと思いますが、 psycopg2 のバージョンが変わっていることに注意してください。(今後ローカルの開発環境もこのバージョン指定で問題ありません。)

requirements.txt
...
Django>=2.1,<2.2
psycopg2==2.8.5
...

1. Elastic Beanstalkのアプリケーションと環境を作成する

AWS マネジメントコンソール にログインしてください。
ただし、AWS Educate のアカウントからの場合はこの記事を参考にしてください。

Elastic Beanstalk を選び、Create Application からアプリケーションを作成します。

  • アプリケーション情報 > アプリケーション名 : 自身のアプリ名
  • アプリケーションタグ : 任意。
  • プラットフォーム : 今回は、プラットフォームPythonプラットフォームのブランチPython 3.6 running on 64bit Amazon Linuxプラットフォームのバージョン2.9.10 を選択しました。
  • アプリケーションコード : とりあえず「サンプルアプリケーション」を選んでおきます。あとから自分のソースをアップロードします。

[アプリケーションの作成] を押します。あとは自動で環境まで作成してくれるので数分待っておきます。
無事終了したら、その環境のダッシュボードのような画面になると思います。左のメニューの、「環境に移動する」をクリックするとサンプルアプリケーションの画面が出てきます。
出てきたURLの http:// などの部分を除く XXX.YYY.ZZZ.elasticbeanstalk.com が自身のアプリのドメインになります。
あとでこれを使うので控えておいてください。

2. データベースの設定を行う

左のメニューから 設定 を選びます。一番下の データベース の右の 編集 ボタンを押します。
データベース設定 の各欄について以下の選択をします。Amazon RDS DB に作成されます。

  • エンジン : postgres
  • エンジンバージョン : 今回は 11.5 を選択
  • インスタンスクラス : とりあえず db.t2.micro を選択
  • ストレージ : 今回は特に変えずに 5 にしておきました。
  • ユーザー名 : 各自作成して(一応)覚えておいてください。
  • パスワード : 各自作成して(一応)覚えておいてください。
  • 保持期間 : スナップショットの作成 にしておきました。
  • アベイラビリティー : 低(1つのAZ) にしておきました。

[適用] を押してください。変更が反映されるまで待っておいてください。

3. アプリケーションソースバンドルを準備する

ここから主にローカルでの作業に移ります。以下、cms というアプリを作成している前提で進めているで、適宜自分のアプリ名に置き換えてください。
最初に、このセクションをすべて終えたときに出来上がるディレクトリ構造の一例を以下に示します。適宜参考にしてください。

├─ .ebextensions         # Added
│  └─ python.config      # Added
├─ requirements.txt
├─ manage.py             # Updated
├─ cms
│  ├─ management         # Added
│  |  ├─ commands        # Added
|  |  |  ├─ createsu.py  # Added
|  |  |  └─ __init__.py  # Added
|  |  └─ __init__.py     # Added
│  ├─ templates
|  ︙
│  └─ views.py
├─ config
│  ├─ __init__.py
│  ├─ settings           # Added (settings.py removed)
|  |  ├─ common.py       # Added
|  |  ├─ local.py        # Added
|  |  └─ production.py   # Added
│  ├─ urls.py
│  └─ wsgi.py            # Updated
├─ docker-compose.yml
└─ Dockerfile

3-1. .ebextensions ディレクトリを作成する

Elastic Beanstalk にデプロイする際に必要となるディレクトリです。
プロジェクトのディレクトリ直下に .ebextensions ディレクトリを作成し、その中に python.config というファイルを作成してください。そのファイルに、以下を書き込んでください。一例なので、適宜書き換えてください。

なお、このファイルのインデントはtabだとエラーが出るので必ずspaceを使用してください。(コピペするとtabになると思うので、spaceに直してください。)

.ebextensions/python.config
packages:
  yum:
    postgresql95-devel: []

container_commands:
  01_migrate:
    command: 'python manage.py migrate'
    leader_only: true
  02_collectstatic:
    command: 'python manage.py collectstatic --noinput'
  03_createsu:
    command: 'python manage.py createsu'
    leader_only: true

option_settings:
  'aws:elasticbeanstalk:application:environment':
    DJANGO_SETTINGS_MODULE: 'config.settings.production'
    PYTHONPATH: '$PYTHONPATH'
  'aws:elasticbeanstalk:container:python':
    StaticFiles: '/static/=www/static/'
    WSGIPath: 'config/wsgi.py'

以下、上記の内容の解説です。

3-1-1. packages

ここで必要なパッケージをインストールします。具体的には、今回は requirements.txt が以下のようになっていて、 psycopg2 をインストールする際に必要となるため、postgresql95-devel を入れています。

requirements.txt
Django>=2.1,<2.2
psycopg2==2.8.5

3-1-2. container_commands

01_migrate ではマイグレーション
02_collectstatic 静的ファイルの処理
03_createsu スーパーユーザーの作成
のコマンドを実行しています。なお、03_createsupython manage.py createsu については後述します。

3-1-3. option_settings

DJANGO_SETTINGS_MODULE の部分で、後ほど作成する、 production.py を読み込むように環境変数を設定しています。
WSGIPathStaticFiles などについては、コンソールの設定のところでも変更可能です。
option_settings について詳しく知りたい方は、以下を参照してください。

3-2. settings.py を分割する

次に、/config/settings.py を、開発用(Local)と本番用(Production)に分割します。
/config/settings.py は、Local 環境と Production 環境で別々のものを読み込む必要があるのですが、毎回書き換えていると大変なので、自動で切り替わるようにします。
具体的には、

  1. common.py に Local 環境と Production 環境で共通の設定項目を書き込む
  2. local.py は、 common.py の内容に加えて、Local 環境固有の設定項目を書き込む
  3. production.py は、 common.py の内容に加えて、Production 環境固有の設定項目を書き込む
  4. manage.pywsgi.py を修正する

どちらの環境にも共通している設定項目は、 common.py に書き込みます。

個別に設定すべき内容

Local 環境と Production 環境でそれぞれ固有の設定は例えば以下のようなものです。

  • DEBUG
  • DATABASE
  • ALLOWED_HOSTS
  • MEDIA_ROOT
  • STATIC_ROOT
  • LOGGING

ただし、common.py に書いている設定項目に、local.pyproduction.py で追加したい場合は、例えば以下のようにします。(配列に追加)

INSTALLED_APPS += (
    'django.contrib.admin',
)

3-2-1. common.py, local.py, production.py を作成する

まず、 /config 直下に、 settings というディレクトリを作成し、その中に /config 下の settings.py を移動させ、 common.py にリネームしてください。
また、 /config/settings ディレクトリの中に local.py, production.py の2つのファイルを新規に作成してください。
以下のようなディレクトリ構造になっていることを確認してください。

...
├─ config
│  ├─ settings           # Added
|  |  ├─ common.py       # Added (settings.py をリネームしたもの)
|  |  ├─ local.py        # Added
|  |  └─ production.py   # Added
...

3-2-2. BASE_DIR を修正する

common.py の最初のほうにある BASE_DIR を以下のように変更してください。

/config/settings/common.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...

/config/settings/common.py
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
...

3-2-3. local.py にLocal 環境固有の設定を書き込む

local.py に、 common.py の内容に加えて、Local 環境で固有の設定項目を書き込みます。
common.py の内容を以下のようにimportします。

/config/settings/local.py
from .common import *

あとは、個別に設定すべき内容 を書けばよいだけです。
これを踏まえると、 local.py は例えば以下のようになります。

/config/settings/local.py
from .common import *

DEBUG = True

ALLOWED_HOSTS = [
    '0.0.0.0',
    '127.0.0.1',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
        'PASSWORD': 'somepassword',
    }
}

3-2-3. production.py にProduction 環境固有の設定を書き込む

production.py に、 common.py の内容に加えて、Production 環境で固有の設定項目を書き込みます。
local.py と同様に、 common.py の内容を以下のようにimportします。

/config/settings/production.py
from .common import *

あとは、個別に設定すべき内容 を書けばよいだけです。以下の項目は一例です。自身の環境に合わせて、適宜対応してください。

3-2-3-1. DEBUG

Production 環境では、DEBUGFALSE にします。

/config/settings/production.py
...
DEBUG = False

3-2-3-2. ALLOWED_HOSTS

ALLOWED_HOSTS に自身のアプリのドメインを追加します。ただし、 XXX.YYY.ZZZ.elasticbeanstalk.com の部分は1で確認した自分のアプリのドメインに置き換えてください。

/config/settings/production.py
...
ALLOWED_HOSTS = [
    'XXX.YYY.ZZZ.elasticbeanstalk.com',
]

3-2-3-3. DATABASES

DATABASES を、本番環境の RDS のものに書き換えます。 'RDS_~' という変数を使えば、Elastic Beanstalk のほうで勝手に書き換えてくれます。
'ENGINE'local.py とは変わっていることに注意してください。

/config/settings/production.py
...
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'],
    }
}

3-2-3-4. STATIC_ROOT

STATIC_ROOT を追加します。

/config/settings/production.py
...
STATIC_ROOT = os.path.join(BASE_DIR, 'www', 'static')

以上を踏まえると、全体として production.py は例えば以下のようになります。ただし、 XXX.YYY.ZZZ.elasticbeanstalk.com の部分は1で確認した自分のアプリのドメインに置き換えてください。

/config/settings/production.py
from .common import *

DEBUG = False

ALLOWED_HOSTS = [
    'XXX.YYY.ZZZ.elasticbeanstalk.com',
]

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'],
    }
}

STATIC_ROOT = os.path.join(BASE_DIR, 'www', 'static')

3-2-5. common.py を修正する

common.py の、Local 環境とProduction 環境に 個別に設定すべき内容 の項目とその値(中身)をすべて削除してください。
例えば今回であれば、 DEBUGALLOWED_HOSTSDATABASES などが該当します。

3-2-6. common.pySTATIC_URL を追加する

common.py に以下を追記します。すでにある場合は飛ばして構いません。

/config/settings/common.py
...
STATIC_URL = '/static/'
...

なお、Djangoの静的ファイルの扱いについては、この記事がとても分かりやすいので、是非読んでみてください。

3-2-7. manage.pywsgi.py を修正する

ルート直下の manage.py と、/config 直下の wsgi.py の以下の部分を修正します。

...
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
...

manage.py
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
/config/wsgi.py
...
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
...

3-3. スーパーユーザー作成用のコマンドを準備する

最後に、スーパーユーザー作成用のファイルを作成していきます。スーパーユーザーの作成は、Local 環境であれば、

$ python manage.py createsuperuser

などとして、ユーザー名、メールアドレス、パスワードを入力したと思いますが、今回はサーバーに実行してもらうため、それらを手動で入力することができません。なので、事前に入力する値を設定しておいて、それを実行させます。それが前述の 3-1-2 で出てきたものです。

3-3-1. createsu.py を作成する

cms(アプリ名なので置き換えてください。)の下に management フォルダ、その下に commands フォルダを作成し、そこに createsu.py を作成してください。そのファイルに以下を書き込んでください。

8行目の XXX、9行目の XXXYYYZZZ は各自で書き換えて、どこかに控えておいてください。また、8行目の XXX と 9行目の XXX は一致させてください。
これがスーパーユーザーアカウントになります。複数作りたい場合は、 if 文の数を増やせばよいだけです。

cms/management/commands/createsu.py
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="XXX").exists():
            User.objects.create_superuser(username="XXX", email="YYY", password="ZZZ")
            self.stdout.write(self.style.SUCCESS('Successfully created new super user'))

3-3-2. __init__.py を作成する

次に、作成した management, commands フォルダそれぞれの直下に __init__.py というファイルを作成してください。これらのファイルは作成するだけで、中身は何も書き込みません。

これで「アプリケーションソースバンドルの準備」は完了です。このセクションの最初にお見せした、ディレクトリ構造と同じようになっているかどうかを確認してください!

4. アプリケーションソースバンドルを作成する

あとは、作成したものを zip にして、デプロイするだけです。

4-1. zip ファイルを作成する

何も難しいことはないかと思いますが、 zip にする対象について。
基本的にプロジェクト直下のファイル、フォルダをまとめて zip にします。(プロジェクトのディレクトリそのものzip にするわけではない)
ただし、例えば git を使っているのなら、 .git フォルダや、 .gitignore などのファイルがあると思いますが、**それらは含めません。**アプリケーションに必要なものだけを対象にしてください。
必要であれば以下を参照してください

Mac, Linux の場合

例えばプロジェクトのルートディレクトリで、以下のようなを実行すれば、プロジェクトの一つ上の階層に myapp.zip が生成されます。( . から始まるものは、 .ebextensions しか含まれないので、ほかに含める必要のあるファイルやフォルダがあれば適宜対応してください。)

$ zip ../myapp.zip -r * .ebextensions

Windowsの場合

コマンドプロンプトやPowershellからもできますが、コマンドが長すぎるのと、含めないファイル(フォルダ)の設定がややこしいのでGUIでやります。以下のように、必要なファイルとフォルダを選択して、
右クリック→送る→圧縮(zip形式)フォルダー
とすれば作成できます。

image.png

4-2. アップロードしてデプロイする

いよいよ、サーバーにアップロードしてデプロイします。
コンソールの実行バージョンの下の、「アップロードとデプロイ」をクリックして、先ほど作成した zip ファイルを選択します。
バージョンラベルは自分でバージョンを区別できるわかりやすいものを付けると良いでしょう。

あとは、「デプロイ」ボタンを押して完了です。
最初のデプロイは完了までに数分かかることがあるので辛抱強く待ってください。

エラーが出ていなければデプロイ完了です。自身のアプリのURLにアクセスして、スーパーユーザーアカウントにログインできるか、などを確認してみましょう。

以上です。お疲れさまでした。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?