AWS(Elastic Beanstalk)にデプロイする(Django編)

Flask を AWS Elastic Beanstalk にデプロイする手順については 別記事 に書きました。この記事では Django を AWS Elastic Beanstalk にデプロイする手順について書きます。重複する部分も多いですが(特に前半)Flask を飛ばして Django を勉強する人もいるでしょうから敢えて再掲します。

Django も AWS EC2 にデプロイすることは可能です。実際、Ubuntuベースの当サイトで Djangoのデモ が動いています。 (サーバーを移設したためこのデモは現在動作しません。)EC2 で Linux ベースのインスタンスを立ち上げれば同じことが可能です。しかし、せっかく AWS を使うならメリットの大きい Elastic Beanstalk を使ってみましょう。

この記事では Djangoチュートリアル 等の学習を終え、ローカル環境で Django が使えることを前提に、そのアプリを AWS Elastic Beanstalk を使ってクラウドにデプロイします。AWSのアカウント登録やログインの方法は AWS(EC2)にデプロイする と同じです。この記事ではAWSにログインできることを前提に説明を開始します。

Elastic Beanstalk の公式ガイドはこちらです。

AWS Elastic Beanstalk とは - AWS Elastic Beanstalk
インフラストラクチャを気にすることなく、AWS Elastic Beanstalk を使用してアプリケーションを AWS クラウドでデプロイおよび管理します。選択肢や制御を制限することなく、管理の複雑さを軽減します。

この記事は下記の公式ガイドのDjangoチュートリアルをベースに説明不足の部分を補足し、ハマリどころの解説を加えたものです。

Elastic Beanstalk への Django アプリケーションのデプロイ - AWS Elastic Beanstalk
EB CLI で Django アプリケーションを作成、設定し、AWS Elastic Beanstalk にデプロイします。

アクセスキーを作成する

AWSにアカウント登録してそのまま使っている人は “ルートユーザー” としてサインインしていると思います。

これからWEBアプリをデプロイするのですがルートユーザーの権限でアプリを公開するのはセキュリティ面で好ましくありません。WEBアプリに必要な権限だけを与えたIAMユーザーを作成して、そのユーザー権限下でWEBアプリを動作させます。

AWSにログインしてメニュー検索から “IAM” を探してください。”Identify and Access Management (IAM)” というサービスに入ったら、左側のメニューから “ユーザー” を選択します。さらに “ユーザーを追加” のボタンを押してください。

“ユーザーを追加” のボタンを押すと新しいユーザーに関する設定画面になりますので順に設定します。設定画面は5つの段階で進みます。

(1) ユーザー詳細の設定

  • “ユーザー名” は任意の名前で構いません。今回は Elastic Beanstalk に関する権限を与えるので “ebmaster” としました。
  • “AWS認証情報タイプを選択” は、”アクセスキー・プログラムによるアクセス” を選択します。
  • “次のステップ:アクセス権限” のボタンを押します。

(2) アクセス権限

ユーザーに許可するオペレーション内容を設定する重要な画面です。Elastic Beanstalk 公式ガイドに ユーザーポリシーについての解説 があるので従います。”既存のポリシーを直接アタッチ” のボタンを押して “ErasticBeanstalk” で検索すると “AdministratorAccess-AWSElasticBeanstalk” が出てくるので選択します。

【重要】Elastic Beanstalk はデプロイする時に EC2 も使います。従ってEC2に対する権限も必要です。”AmazonEC2FullAccess” というポリシーも追加しておいてください。忘れると、後の手順で権限が無いという趣旨のエラーが発生します。

(3) タグの追加(オプション)

この画面の設定項目はオプションなので、何もせず “次のステップ:確認” を押します。

(4) 確認

ここまで設定した内容が表示されるので、確認して “ユーザーの作成” を押します。

(5) アクセスキーの入手

“成功” と表示されて、作成したユーザーのアクセスキーが表示されます。アクセスキーとシークレットアクセスキーは後で使いますので、CSVファイルを保存してください。保存したCSVファイルは厳重に管理してください。

Python3.7 の環境を作る

Elastic Beanstalk に Django をデプロイするとき、Python3.8 以降を使うと SQLite とのバージョン不整合を起こしてエラーが発生します。Python3.8 以降ではDjango4 がインストールされますが、Django4 が要求する SQLite のバージョンが存在しないという内容です。回避策は SQLite 以外のデータベースを使うか、Python3.7 を使うかです。Python3.7 では Django3 がインストールされるので問題ありません。(Python3.8 で Django3 を使うという方法があるかもしれませんが未確認です。)

Djangoチュートリアル で Polls アプリを作ったときには Python のバージョンはあまり意識しませんでしたが、Python3.7 を使ってもう一度動作確認をしてください。Python3.7 の環境を作る方法を説明します。

virtualenv で仮想環境を作る時に Python のバージョンを指定することができます。

Windows のWSL環境ならこれでうまくいくと思います。ただし、virtualenv の -p オプションで指定できるのは既にインストールされている Python が存在している場合だけです。そもそも Python 3.7 がインストールされていなければ上記のコマンドはうまく動作しません。その場合は予め Python3.7 をインストールしてください。

Apple Silicon Mac の場合は、直接 Python3.7 をインストールするのは手順が煩雑なので pyenv を使うことにします。virtualenv は Python 仮想環境にインストールされるライブラリーを管理するツールですが、pyenv は Python そのもののバージョンを管理できます。もし pyenv がインストールされていなかったら次のコマンドでインストールします。

インストールできたら pyenv を有効にするため、.zshrc に次の3行を追加します。もし bash を使っていたら .bash_profile に追加してください。

ターミナルソフトを再起動するか、”source ~/.zshrc” コマンドを実行すれば追加した内容が反映されます。次のコマンドで、pyenv でインストール可能なバージョンが一覧表示されます。その中で 3.7 の最終版が何か調べてください。

筆者の環境では 3.7.12 だったので、これを pyenv でインストールします。

いつものように作業ディレクトリに移動して、virtualenv で仮想環境を作ります。

次にチュートリアルの復習をしますが、いま作った Python3.7 の環境で実行してください。

Django アプリの動作を再確認

デプロイするアプリの動作をローカル環境で再確認します。特にアプリを準備していない場合は、Djangoチュートリアル をもう一度実行してください。すると次のようなファイル構成(一部省略しています)になっているはずです。

virtualenv で作った仮想環境 “django” に入ったあとは manage.py がある階層(2つあるmysiteの上位の階層)で作業していきます。チュートリアルがうまく出来ていれば次のコマンドで動作するはずです。

runserver コマンドを実行した状態で http://localhost:8000/polls/ にアクセスして動作を確認してください。もしうまく動作しなかったらチュートリアルの内容を確認してください。

Elastic Beanstalk 用の環境を設定する

引き続き仮想環境 “django” の中で、manage.pyが存在するディレクトリで作業します。次のコマンドでローカル環境で正常に動作している状態の Python のライブラリ一覧を requirements.txt に保存します。Elastic Beanstalk は requirements.txt に記述されたライブラリで動作します。”pip3 freeze” コマンドを実行するタイミングによっては EB CLI を表す “awsebcli==3.xx.x” が紛れ込むかもしれません。この行は必要ありませんので、もし含まれていたら削除してください。

次に .ebextensions という名前のディレクトリを作成し、その中に django.config という名前のファイルを作ります。.ebextensions/django.config の内容は次のようにします。最後の行の “mysite” は、動作している Django アプリによっては違う名前かもしれませんので自分のアプリのプリジェクト名に合わせてください。

もう一度ファイル構成を確認してください。下の図は一部省略されています。

EB CLI を使ってデプロイする

EB CLI は AWS Elastic Beanstalk を扱うためのコマンドラインインターフェイスです。このコマンドも virtualenv の環境にインストールしてしまいます。

チュートリアルの手順によっては virtualenv が作ったディレクトリ(この例では django ディレクトリ)が manage.py の階層に存在しているかもしれません。その場合は、仮想環境が保存されたディレクトリは Elastic Beanstalk には不要なので、除外するために .ebignore というファイルを作ります。.ebignore の中には1行だけディレクトリ名を書いておきます。GitHub で使用する .gitignore と同じ考え方です。

manage.py がある階層で eb init コマンドを実行します。色々聞かれますので入力します。過去に eb init コマンドを実行したことがあれば、設定済の項目は表示されないかもしれません。

【重要1】Elastic Beanstalk を使うときは常にリージョンを意識してください。意識せずにデフォルトのまま進めると、どこにデプロイされたかわからなくなってしまいます。例えば「東京(ap-northeast-1)」と決めたら常に「東京」を使うようにしてください。

【重要2】Python は 3.7 を指定してください。3.8 を使うと “Exception Value: deterministic=True requires SQLite 3.8.3 or higher” というエラーが発生します。(このエラーメッセージは DEBUG=Trueで動作させたときに表示されるものです)

次に “eb create” というコマンドで Django の実行環境を作りますが、ここでロードバランサの種類を意識しなければなりません。AWS のロードバランサにはいくつか種類があり、”eb create” コマンドのオプションで指定できます。デフォルトは Application Load Balancer ですが、筆者は意図せず Classic Load Balancer になってしまった経験があります。明示的に Application Load Balancer を指定するほうが良いでしょう。ロードバランサについては次のページを参考にしてください。

Elastic Beanstalk 環境のロードバランサー - AWS Elastic Beanstalk
Elastic Load Balancing ロードバランサーを使用して可用性を高め、アプリケーションのトラフィックの増加をサポートすることで、AWS Elastic Beanstalk アプリケーションの可用性とスケーラビリティを向上させ...

Django用の環境を django-env という名前で作成します。”–elb-type application” は Application Load Balancer を指定するオプションです。コマンドを実行すると、処理の進行状態が表示されます。5分ほどかかるので “Successfully launched environment” と表示されるまで待ってください。

正常に終了したら eb status コマンドでドメイン名を確認します。

Django のソースコードにドメイン名を追加します。ファイルは mysite/settings.py です。ALLOWED_HOSTS を次のように変更してください。

ファイルを保存したらアプリケーションをデプロイします。1分ほどかかるので待ってください。

eb open コマンドでWEBページを開いてみます。

アプリによっては、そもそもURLだけでは動作しない場合もあると思います。Polls アプリだったらURLの後ろに /polls/ とか /admin/ を付けて試してください。ここではまだ静的ファイルが反映されていませんが気にしないでください。

アプリケーションの更新

Django アプリケーションの設定を続けます。まずローカルのデータベースを初期化します。ローカル環境で動作させていれば “No changes” などのメッセージが出ますがそれでOKです。

サイトの管理者を作成します。すでに作成されていればそのままでも構いません。

mysite/settings.py を何箇所か調整します。公開するサイトではデバッグモードを無効にします。実行時にエラーが発生したときは一時的に DEBUG=True に戻せばエラー内容を確認できることがありますので覚えておいてください。

静的ファイルを参照する場所を mysite/settings.py の中で定義します。

静的ファイルを集めます。

さらに .ebextensions/django.config に数行追加して以下のようにします。このファイルではタブを使わずにスペースを使ってください。タブを使うどエラーになります。

加えた変更を反映させるためにデプロイします。

WEBページを開きます。

こんどは静的ファイルも反映されます。

実験目的で使用するならここまでの実装で十分な場合も多いはずです。より本格的な運用のために設定を続ける場合には別の記事を参照してください。

デプロイしたアプリケーションの削除

デプロイした環境・アプリケーションは eb terminate コマンドで終了できます。

eb init コマンドを実行した記録はプロジェクトのディレクトリの .elasticbeanstalk というディレクトリに残っています。このディレクトリを削除すれば初期状態に戻ります。

Elastic Beanstalk はデプロイ時にAWSの様々なインスタンスを作ります。その殆どは eb terminate コマンドで削除されますが、Amazon S3 バケットだけは削除されません。S3バケットを完全に削除してしまいたい場合は次のページの手順に従ってください。

Amazon S3 で Elastic Beanstalk を使用する - AWS Elastic Beanstalk
Amazon S3 シンプルウェブサービスで Elastic Beanstalk を使用して、耐久性および耐障害性に優れたデータストレージを提供できます。