AWS

Amazon ECSにDjangoとNginxをデプロイしてアクセスする方法 Part3 -ECS設定編-

前回の記事の続きになります。
Part3では、ついにECSを設定して画面にアクセスするところまでやっていきます。

Django用にRDSにてPostgresのDBを作成した後、ECSでコンテナを動かします!

RDSでDB作成(Postgres)

RDSでDjango用にPostgresのDBを作成します。

RDSの画面に移動し、データベースの作成を選択。

設定できる箇所が非常に多いため、ここでは変更する箇所と大事な箇所のみ記載します。
記載のない箇所はデフォルトのままです。

項目設定値
データベース作成方法を選択標準作成
エンジンのタイプPostgresSQL
テンプレート無料利用枠
DBインスタンス識別子test-db-django
マスターユーザ名postgres
マスターパスワード(パスワードはご自身に決定してください)
パスワードを確認(マスターパスワードと同じ)
DBインスタンスサイズdb.t2.micro
ストレージの自動スケーリングを有効にする無効(チェックを外す)
Virtual Private Cloud (VPC)Test-vpc(Part1で作成したVPCを選択)
サブネットグループ新しいサブネットグループの作成
パブリックアクセス可能なし
アベイラビリティーゾーンap-northeast-1a
データベース認証パスワード認証
最初のデータベース名djangodb
自動バックアップの有効化無効(チェックを外す)
Performance Insightsを有効にする無効(チェックを外す)
マイナーバージョン自動アップグレードの有効化無効(チェックを外す)

アベイラビリティゾーンは、サブネットを配置している両方のAZ(ap-northeast-1aap-northeast-1c)に配置すべきですが、今回はテスト用なので1つだけです。
本番環境用ではないため、可用性や冗長性に関する機能はすべてOFFとしています。

設定ができたら、データベースの作成を選択。
DBが作成できるまで少し時間がかかります。

作成ができたらステータス利用可能となります。

ECSでコンテナ起動

やっとECSを設定し、コンテナを起動させていきます!

タスク定義作成

まずは、タスク定義を作成します。
タスク定義は、コンテナをどう実行するかを定義するものです。
1つのタスク定義内のコンテナは、同一ホスト上で実行される仕様となっています。

ECSのタスク定義の画面に移動し、新しいタスク定義の作成を選択。

起動タイプはFARGATEを選択し、次のステップへ。

タスクとコンテナの定義の設定画面になるので設定していきます。

項目設定値
タスク定義名test-nginx-django
タスクロールTask-ECSTaskRole(Part1で作成したロール)
タスク実行ロールTaskExecution-ECSTaskRole(Part1で作成したロール)
タスクメモリ(GB)0.5GB
タスクCPU(vCPU)0.25 vCPU
コンテナの定義コンテナの追加
App Mesh 統合の有効化無効
プロキシ設定の有効化無効
FireLensの統合を有効にする無効
ボリュームボリュームの追加

コンテナの追加ボリュームの追加は分けて記載しますが、かならずボリュームの追加から行ってください。
ボリュームを先に作成しておかないと、コンテナの追加で設定できないからです。

ボリュームの追加を選択。

項目設定値
名前tmp
ボリュームタイプBind Mount

設定したら追加を選択。
このボリュームは、DjangoとNginxのUNIXソケット通信用の共有ディレクトリにします。

次にコンテナの追加を選択し、DjangoとNginxのコンテナの設定を行います。

設定箇所が多いので、重要な設定箇所だけ記載します。

Nginx用のコンテナの定義

項目設定値
コンテナ名test-nginx
イメージ[AWS_ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com/test-nginx:0.1
メモリ制限ソフト制限 256
ポートマッピング80 tcp
CPUユニット数128
環境変数(なし)
ソースボリュームtmp(先ほど追加したボリュームの名前)
コンテナパス/app/tmp/sockets/
ログ設定 Auto-configure CloudWatch Logs有効(チェックを付ける)

ストレージとログの箇所は以下のようになっています。

Django用のコンテナの定義

環境変数は別途記載しますので、環境変数以外の重要な設定を記載します。

項目設定値
コンテナ名test-django
イメージ[AWS_ACCOUNT_ID].dkr.ecr.ap-northeast-1.amazonaws.com/test-django:0.1
メモリ制限ソフト制限 256
ポートマッピング(なし)
CPUユニット数128
環境変数(数が多いので別途記載)
ソースボリュームtmp(先ほど追加したボリュームの名前)
コンテナパス/app/tmp/sockets/
ログ設定 Auto-configure CloudWatch Logs有効(チェックを付ける)

DjangoにはDB接続用の環境変数が必要になります。
設定内容は以下になります。

Key
POSTGRES_HOSTtest-db-django.XXXXXXXXX.ap-northeast-1.rds.amazonaws.com
POSTGRES_NAMEdjangodb(上記で設定した最初のデータベース名)
POSTGRES_PASSWORD(上記で設定したRDSのパスワード)
POSTGRES_PORT5432
POSTGRES_USERpostgres(上記で設定したマスターユーザ名)

POSTGRES_HOSTには、作成したRDSのエンドポイントを設定します。
RDSの画面では、接続とセキュリティタブに載っています。

コンテナの設定が出来たら追加を選択。

全ての設定が終わったら、作成を選択。

完了すると、タスク定義が表示できるようになります。

クラスターの作成

クラスターとはサービスとタスクを扱うグループです。
クラスターの中で複数のサービスやタスクを実行することができます。

ECSのクラスターの画面に移動して、クラスターの作成を選択。

ネットワーキングのみを選択

クラスタ名はtest-nginx-djangoにしておきます。

作成ができたら、クラスターの表示ができます。

このようにクラスターができているので、詳細を表示します。

DB初期化

Django用にRDSのDBの初期化を行います。

作成したクラスターの画面にて、タスクタブに移動します。

新しいタスクの実行を選択し、DBの初期化をさせます。
コンテナで実行できるコマンドを調整できるので、元々のDjangoの起動コマンド(uwsgi –ini uwsgi.ini)をDB初期化のためのコマンド(python manage.py migrate)に書き換えます。

項目設定値
起動タイプFARGATE
タスク定義 ファミリーtest-neginx-django
タスク定義 リビジョン1 (latest)
プラットフォームのバージョンLATEST
クラスターtest-nginx-django
タスクの数1
タスクグループ(そのまま)
クラスターVPCTest-vpc(Part1で作成したVPC)
サブネットTest-subnet-az1a-private(Part1で作成したプライベートサブネット)
セキュリティグループ既存のセキュリティグループを選択
⇒デフォルトのセキュリティグループ(Part1で調整したセキュリティグループ)
パブリックIPの自動割り当てDISABLED
詳細オプション(別途設定)

サブネットは、必ずRDSが接続されているTest-subnet-az1a-privateを選択してください。
間違えるとDjangoがDBにアクセスできません。

上記が設定できたら詳細オプションを開きます。
コンテナの上書きtest-djangoの設定を上書きしていきます。

コマンドの上書きでのコマンドは、スペース区切りではなくカンマ区切りになります!

項目設定値
コマンドの上書きpython,manage.py,migrate
環境変数の上書き(今回は追加しません)

このままだとNginxのコンテナも起動してしまいますが気にしない。
設定ができたらタスクの実行を選択。

問題がなければタスクタブで新しいタスクが見えるようになっています。

タスクを選択して詳細を表示します。
ステータスがPENDINGではまだ実行されていないので、少し待ちます。

実行が完了したら、コンテナがSTOPPEDになり、test-nginxのコンテナの終了コード137になります。

停止理由はEssential container in task exitedになっています。

Logsタブでtest-djangoコンテナのログを表示すると、Applying~が出力されています。
Part2でmigrateコマンドを実施した場合と同じログになっています。

ロードバランサーの作成

ECSをプライベートサブネットに作成しているため、今のままでは外部からECSのコンテナにアクセスできません。

そこで、今回はロードバランサーをパブリックのサブネットに配置し、プライベートネットワークにアクセスをできるようにします。
ロードバランサーとしては、NLB(Network Load Balancer)を使用します。

ロードバランサーの画面に移動し、ロードバランサーの作成を選択。

今回は、Network Load Balancerを選択します。

ターゲットグループは作成します。

項目設定値
Load Balancer Nametest-nlb
SchemeInterner-facing
IP address typeIPv4
VPCTest-vpc(Part1で作成したVPC)
ap-northeast-1a有効(チェックを付ける)
SbunetはTest-subnet-az1a-public(パブリックのサブネット)
ap-northeast-1c有効(チェックを付ける)
SbunetはTest-subnet-az1c-public(パブリックのサブネット)
Listeners and routingCreate target groupを選択して新規作成

サブネットは、必ずパブリックの方を選択してください。
ここでの選択は、NLBを配置するサブネットを選択することになるため、NLB自体がプライベートにあると通信できません。

Create target groupを選択するとターゲットグループ作成画面になるため、設定していきます。

項目設定値
Choose a target typeIP addresses
Target group nametest-targetgroup
protpcplHTTP
Port80
VPCTest-vpc(Part1で作成したVPC)
Protocol varsionHTTP1
Health check protocolHTTP
Health check path/admin

設定ができたらNextを選択。

Register targets画面では、今は何も設定せずにCreate target groupを選択。

ロードバランサー作成画面に戻ると、ターゲットグループが選択できるようになっているので選択。

設定ができたらCreate load balancerを選択。

ECSのサービス作成

ついにECSのサービスを作成します。

ECSのクラスターの画面に移動し、サービスタブで作成を選択。

以下のように設定します。

項目設定値
起動タイプFARGATE
タスク定義test-nginx-django(先ほど作成したタスク定義)
リビジョンX(latest)
プラットフォームのバージョンLATEST
クラスターtest-nginx-django
サービス名test-service
タスクの数1
最小ヘルス率100
最大率200
デプロイサーキットブレーカー無効
デプロイメントタイプローリングアップデート

設定したら次のステップを選択。

項目設定値
クラスターVPCTest-vpc(part1で作成したVPCを選択)
サブネットTest-subnet-az1a-private(Part1で作成したプライベートのサブネット)
セキュリティグループ編集を選択して、既存のPart1で調整したセキュリティグループを選択
パブリックIPの自動割り当てDISABLED
ロードバランサーの種類Network Load Balancer
ロードバランサー名test-nlb(先ほど作成したNLB)
コンンテ名: ポートtest-nginx:80:80 を選択してロードバランサーに追加を選択
ターゲットグループ名test-targetgroup

設定したら次のステップを選択。

Auto Scalingはデフォルトのまま次のステップを選択。

確認画面になるので、サービスの作成を選択してサービスを作成。

サービスの画面に移動するので、タスクタブに移動するとコンテナが起動しようとしているのが見えます。
前回のステータスがPROVISIONINGになっています。

タスクを選択してタスクの詳細画面に移動し、コンテナのステータスがRUNNINGになるまで待ちます。

ステータスがRUNNINGになっているので、コンテナが無事起動しています!

Djangoの画面にアクセス

NLBの画面に移動し、先ほど作成したNLBの詳細を確認します。

DNS名をコピーします。

ブラウザの検索バーに貼り付け、後ろに/adminを付けてEnter!

問題がなければDjangoのadministrationのログイン画面が表示されています!!

画面でログイン

スーパーユーザーの作成

administrationの画面が表示されましたが、ユーザーを作成していないのでログインができません!

最後にスーパーユーザーを作成します。
やり方は、DBの初期化を行った時とほとんど同じです。

作成したクラスターの画面にて、タスクタブに移動します。

新しいタスクの実行を選択し、スーパーユーザーを作成します。
コンテナで実行できるコマンドを調整できるので、元々のDjangoの起動コマンド(uwsgi –ini uwsgi.ini)をスーパーユーザー作成のコマンド(python manage.py migrate)に書き換えます。

項目設定値
起動タイプFARGATE
タスク定義 ファミリーtest-neginx-django
タスク定義 リビジョン1 (latest)
プラットフォームのバージョンLATEST
クラスターtest-nginx-django
タスクの数1
タスクグループ(そのまま)
クラスターVPCTest-vpc(Part1で作成したVPC)
サブネットTest-subnet-az1a-private(Part1で作成したプライベートサブネット)
セキュリティグループ既存のセキュリティグループを選択
⇒デフォルトのセキュリティグループ(Part1で調整したセキュリティグループ)
パブリックIPの自動割り当てDISABLED
詳細オプション(別途設定)

上記が設定できたら詳細オプションを開きます。
コンテナの上書きtest-djangoの設定を上書きしていきます。

項目設定値
コマンドの上書きpython,manage.py,createsuperuser,–noinput,–username,test4321,–email,test@test.com
環境変数の上書きキー:DJANGO_SUPERUSER_PASSWORD
値:(任意のパスワード)

test4321はユーザー名なので、任意に変更可能です。

–noinputオプションによって非対話形式でスーパーユーザの作成が可能ですが、コマンド内でパスワードを設定することはできません。
環境変数としてDJANGO_SUPERUSER_PASSWORDを設定することで、パスワードを設定することが可能です。

設定ができたらタスクの実行を選択。

スーパーユーザー作成の用のタスクが作成されました。

タスクの詳細を確認し、test-djangoコンテナのステータスSTOPPEDになっていれば完了です。

詳細を確認すると終了コードが0になっています。

Logsで確認すると、Superuser created successfully.と出力されていればOKです。

ログイン

Djangoのadministration画面に戻り、先ほど作成したユーザー・パスワードでログインします。

ログインできれば目的達成です!

まとめ

このPartではDjangoに必要なDBをRDSで作成し、ECSでクラスター・タスク定義・サービスを作成しコンテナを稼働させ、DBの初期化とスーパーユーザーの作成を行いました。

合計3partに渡って解説を行いましたが、当初の目的であったDjangoの管理画面を見るまでの設定が完了しました!

もし「設定できない!」や「うまくいかない!」などがありましたら著者のTwitterまでご連絡ください。

参考

モジュール 2: ウェブサーバーでのアプリケーションのホスト

Amazon ECSとは

Djangoのスーパーユーザー作成方法