はじめに
ECS Fargate を利用して、Django アプリと Nginx を組み合わせたリバースプロキシ構成を実装する際、手動設定では細かいミスが発生しやすい ことがあります。
しかし、カスタム JSON を使うことで、設定の一貫性を保ちつつ、効率よくタスク定義を作成できる ことが分かりました。
普段は Terraform や CloudFormation を使って設定を行っていますが、手動で作成する際は従来の コンソールからの新しいタスク定義の作成 を行っていました。
本記事では、カスタム JSON の各項目を解説しながら、タスク定義の仕組みを深掘り していきます。
それぞれのソースコードはこちら
ローカル開発用リポジトリ
ローカル開発の備忘録記事
本番 ECS 用リポジトリ
本番 ECS 用の備忘録記事
現在、それぞれのリポジトリには README などの説明は記載していませんが、今後追加していく予定です。
少し困っていたこと
AWS のマネジメントコンソール上で手動でタスク定義を作成する必要がありましたが、その際に 細かい設定漏れ などが発生し、少し困っていました。
しかし、JSON を使って設定する方法 もあるため、今回はその手順をご紹介します。
こんな感じ👇
こんなシナリオのアプリ開発を想定
- AWS ECS Fargate を利用し、サーバーレスで Django アプリを運用
- Nginx をリバースプロキシ として使用し、外部からのリクエストを適切に振り分け
- アプリのログを AWS CloudWatch Logs に集約 して監視
こんな感じ👇
どのように動作するか?
この ECS タスクは Django + Nginx のコンテナを Fargate で動作させる構成になっています。
リクエストの流れ
クライアント → Nginx → Django → Nginx → クライアント
↘ CloudWatch Logs
ポイント
-
Nginx(
nginx
コンテナ) がポート80
でリクエストを受ける。 - Nginx がリクエストを Django(
django
コンテナ) に転送。 - Django がリクエストを処理し、レスポンスを Nginx に返す。
- Nginx が最終レスポンスをクライアントに送る。
こんな感じ👇
ログ管理
-
Django と Nginx のログは共に CloudWatch Logs に送信。
- ロググループ:
/aws/ecs/reverse-proxy-cluster
- ロググループ:
実際に使った JSON
詳しくは 前回の記事 で紹介していますので、詳細を知りたい方は参考にしてみてください。
この JSON は ECS Fargate を利用し、Django アプリと Nginx のリバースプロキシ構成 で動作するタスクを定義しています。
{
"family": "reverse-proxy-task",
"executionRoleArn": "arn:aws:iam::xxx:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "1024",
"memory": "2048",
"containerDefinitions": [
{
"name": "django",
"image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-app",
"cpu": 512,
"memory": 1024,
"portMappings": [
{
"containerPort": 8000,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "DJANGO_SETTINGS_MODULE",
"value": "mysite.settings"
},
{
"name": "DJANGO_SECRET_KEY",
"value": "your-secret-key"
},
{
"name": "STATIC_ROOT",
"value": "/app/staticfiles"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/reverse-proxy-cluster",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
},
{
"name": "nginx",
"image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-nginx",
"cpu": 512,
"memory": 1024,
"portMappings": [
{
"containerPort": 80,
"protocol": "tcp"
}
],
"essential": true,
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/reverse-proxy-cluster",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
1. タスク定義全体の概要
{
"family": "reverse-proxy-task",
"executionRoleArn": "arn:aws:iam::xxx:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "1024",
"memory": "2048",
"containerDefinitions": [...]
}
ECS タスク定義のポイント
-
family
- タスク定義の名前(例:
reverse-proxy-task
)。 - 更新時に新バージョンが作成される。
- タスク定義の名前(例:
-
executionRoleArn
- ECS タスクの実行ロール(IAM ロール)。
- 例えば、ECR(Amazon Elastic Container Registry)からイメージを取得する権限を持つ。
-
networkMode:
"awsvpc"
- AWS VPC ネットワークモードを使用。
- 各コンテナに独立した ENI(Elastic Network Interface)が割り当てられる。
- セキュリティグループやサブネット設定が必要。
-
requiresCompatibilities:
["FARGATE"]
- Fargate を使用する設定(EC2 ではなく、サーバーレスで動作)。
-
cpu / memory
- タスク全体のリソース割り当て(CPU 1024 / メモリ 2048MB)。
- 2つのコンテナ(Django + Nginx)がこのリソースを分け合う。
2. containerDefinitions(コンテナ設定)
ECS タスク内で動作する 2つのコンテナ(Django アプリ & Nginx)を定義しています。
(1) Django コンテナ
{
"name": "django",
"image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-app",
"cpu": 512,
"memory": 1024,
"portMappings": [
{
"containerPort": 8000,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "DJANGO_SETTINGS_MODULE",
"value": "mysite.settings"
},
{
"name": "DJANGO_SECRET_KEY",
"value": "your-secret-key"
},
{
"name": "STATIC_ROOT",
"value": "/app/staticfiles"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/reverse-proxy-cluster",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
Django コンテナのポイント
-
image
- ECR に保存された Django アプリの Docker イメージを使用。
-
cpu: 512 / memory: 1024
- タスク全体(1024/2048)の半分をこのコンテナが利用。
-
portMappings
- Django アプリはコンテナ内のポート
8000
でリクエストを受け付ける。
- Django アプリはコンテナ内のポート
-
environment(環境変数)
-
DJANGO_SETTINGS_MODULE
: Django の設定ファイルを指定(mysite.settings
)。 -
DJANGO_SECRET_KEY
: Django のシークレットキー(実際は AWS Secrets Manager に置くべき)。 -
STATIC_ROOT
: 静的ファイルのディレクトリを/app/staticfiles
に指定。
-
-
logConfiguration
- ログドライバーに
awslogs
を指定。 -
/aws/ecs/reverse-proxy-cluster
にログを保存。
- ログドライバーに
(2) Nginx コンテナ
{
"name": "nginx",
"image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-nginx",
"cpu": 512,
"memory": 1024,
"portMappings": [
{
"containerPort": 80,
"protocol": "tcp"
}
],
"essential": true,
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/aws/ecs/reverse-proxy-cluster",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
Nginx コンテナのポイント
-
image
- ECR に保存された Nginx の Docker イメージを使用。
-
cpu: 512 / memory: 1024
- Django と同じく、タスク全体(1024/2048)の半分を使用。
-
portMappings
- コンテナのポート
80
(HTTP)でリクエストを受け付ける。 - 外部からのリクエストはまず Nginx が受け取る。
- コンテナのポート
-
logConfiguration
- Django と同じ CloudWatch Logs にログを送信(
/aws/ecs/reverse-proxy-cluster
)。
- Django と同じ CloudWatch Logs にログを送信(
まとめ
リバースプロキシの部分ではかなり苦戦しましたが、最終的に無事やり遂げることができてほっとしています。
もし、この記事の内容が少しでも参考になれば嬉しく思います。
今後も同様の内容を継続して投稿していきますので、温かく見守っていただけるとありがたいです。