1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django開発備忘録:Docker を使って Nginx + Django のコンテナを ECR にプッシュし、ECS にデプロイしてみた

Last updated at Posted at 2025-01-31

はじめに

まず、大前提として、ここから先は現在キャッチアップしているコンテナ関連の学習のために、ECR や ECS を活用しながら、さまざまなコードを書いていきます。

※補足事項
そのため、内容は完全に自分向けとなっています。

また、このブログ投稿サイトは、自分自身の備忘録としても活用する予定です。記録を積み重ねながら、メモを残していきます。

実際の作業の流れ

実際の作業の流れをまとめましたが、本記事ではすべての手順を詳しく紹介するわけではありません。あらかじめご了承ください。

  • CloudWatch にロググループ作成
  • 対象のリポジトリをクローンする
  • ECR に Docker イメージをプッシュする
  • ECS でクラスターを作成する
  • カスタム JSON を使ってタスク定義を作成する
  • ECS のサービスを作成する
  • ブラウザからタスク定義のパブリック IP アドレスにアクセスする

ディレクトリ構成

reverse-proxy-django/
│── .env                   # 環境変数ファイル(SECRET_KEY など)
│── docker-compose.yml     # Docker Compose ファイル
│── nginx/
│   ├── default.conf       # Nginx 設定ファイル(リバースプロキシ設定)
│── django_app/
│   ├── Dockerfile         # Django の Dockerfile
│   ├── requirements.txt   # Django の依存関係(Django, Gunicorn)
│   ├── manage.py          # Django 管理コマンド
│   ├── templates/         # Django のテンプレートディレクトリ(将来的に使用)
│   └── mysite/            # Django プロジェクト
│       ├── __init__.py    
│       ├── settings.py    # Django の設定ファイル
│       ├── urls.py        # ルーティング設定
│       ├── wsgi.py        # WSGI アプリケーションのエントリーポイント
│── nginx.Dockerfile       # Nginx の Dockerfile

それぞれのソースコードはこちら

ローカル開発用リポジトリ

ローカル開発の記事

本番 ECS 用リポジトリ

現在、それぞれのリポジトリには README などの説明は記載していませんが、今後追加していく予定です。

Django の通信経路

Nginx は Django へのリバースプロキシとして機能します。

[ブラウザ]  [ECS上のNginx (ポート80)]  [Django (ポート8000)]

CloudWatch にロググループ作成

CloudWatch にロググループが存在するか確認

まず、ロググループがすでに存在しているかを確認します。

aws logs describe-log-groups --query "logGroups[*].logGroupName"
  • ここに "/aws/ecs/reverse-proxy-cluster"(設定したロググループ)が存在しない場合、次のステップへ進みます。

ロググループを作成

ロググループが存在しない場合、以下のコマンドで作成します。

aws logs create-log-group --log-group-name "/aws/ecs/reverse-proxy-cluster"

※注意点
カスタム JSON ポリシーを使用する場合、この作業を事前に行わないと、以下のエラーが発生します。

エラー内容:
ResourceInitializationError: failed to validate logger args: create stream has been retried 1 times: failed to create CloudWatch log stream: ResourceNotFoundException: The specified log group does not exist. : exit status 1

ECR にプッシュする際のコツ

Django アプリケーションのビルド

django_app ディレクトリに移動してから、以下のコマンドを実行します。

docker build -t reverse-proxy-django-app .

Nginx のビルド

Nginx の Dockerfile はプロジェクトルートにあるため、以下のように -f オプションを指定してビルドします。

# Nginx のビルド
docker build -t reverse-proxy-django-nginx -f nginx.Dockerfile .

ECR へのプッシュ

その他のコマンドについては、ECR のリポジトリ作成時に表示されるプッシュコマンドをそのまま使用しています。

ECS のタスク定義が重要

これまでは AWS マネジメントコンソール(マネコン)から設定を行っていましたが、カスタム JSON を使うことで、一発で作成することができます。

{
  "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"
              }
          }
      }
  ]
}

ECS(Fargate)でのセキュリティグループ設定

現在の ECS 環境では、Nginx + Django(Gunicorn) の構成で動作しており、適切な セキュリティグループ(SG) の設定が必要です。

現時点では、ブラウザからのアクセスを目的として以下のルールを許可しました。

※ただし、一部不要な設定も含まれているため、適宜見直しが必要と考えています。

プロトコル ポート 方向 許可元 / 許可先 説明
TCP 80 インバウンド 0.0.0.0/0 または ::/0 インターネットから Nginx へ HTTP アクセスを許可
TCP 443 インバウンド 0.0.0.0/0 または ::/0 (HTTPS を使用する場合) SSL 通信を許可
TCP 8000 インバウンド nginx のセキュリティグループ Nginx から Django (Gunicorn) への接続を許可
TCP 80 アウトバウンド 0.0.0.0/0 Nginx が外部へ通信する場合(API, S3 など)
TCP 443 アウトバウンド 0.0.0.0/0 Nginx が外部の HTTPS リソースへアクセスする場合
TCP 5432 / 3306 インバウンド Django のプライベート IP (データベースが別のサーバーにある場合) Django から DB への接続を許可
ALL ALL アウトバウンド 0.0.0.0/0 ECS タスクが外部のリソースにアクセスするため

その他で使ったコマンド

タスクのARNを取得

ECS クラスター内のタスク ARN を取得します。

aws ecs list-tasks --cluster reverse-proxy-cluster --query 'taskArns' --output text

取得したタスクARNを使って詳細を確認

上記で取得したタスク ARN を使用し、ECS タスクのエラー理由を確認します。

aws ecs describe-tasks --cluster reverse-proxy-cluster --tasks arn:aws:ecs:ap-northeast-1:881490128743:task/reverse-proxy-cluster/xxxxxxxxxxxxxxxxxxxx --query 'tasks[*].containers[*].reason'

CloudWatch Logs でエラーの詳細を確認

エラーの詳細は reason に表示されますが、CloudWatch Logs でログを確認することで、より詳しい情報を取得できます。

ロググループの一覧を取得

aws logs describe-log-groups --query "logGroups[*].logGroupName"

コンテナのログを取得

対象のロググループを見つけたら、以下のコマンドで直近 10 分間のコンテナログを取得します。

aws logs tail /aws/ecs/containerinsights/reverse-proxy-cluster/application --since 10m

CloudWatch Logs で詳細エラーを確認

aws logs describe-log-groups --query "logGroups[*].logGroupName"

ログストリームを確認

特定のロググループ内のログストリームを確認する場合は、以下のコマンドを使用します。

aws logs describe-log-streams --log-group-name "/aws/ecs/reverse-proxy-cluster" --query "logStreams[*].logStreamName"

ECS タスク定義にログ設定を追加

ECS のタスク定義に CloudWatch Logs の設定 を追加することで、コンテナのログを取得できるようになります。

"containerDefinitions": [
  {
    "name": "django",
    "image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-app",
    "memory": 1024,
    "cpu": 512,
    "essential": true,
    "portMappings": [{ "containerPort": 8000 }],
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-group": "/aws/ecs/reverse-proxy-cluster",
        "awslogs-region": "ap-northeast-1",
        "awslogs-stream-prefix": "ecs"
      }
    }
  }
]

直近のログを取得

最新のログを確認するには、以下のコマンドを実行します。

aws logs tail /aws/ecs/reverse-proxy-cluster --since 10m

最新のログストリームを自動で取得する方法

Django の最新ログストリームを取得

以下のコマンドを実行すると、Django の最新のログストリームを取得し、ログを表示できます。

LOG_STREAM=$(aws logs describe-log-streams --log-group-name "/aws/ecs/reverse-proxy-cluster" --query "logStreams[?starts_with(logStreamName, 'ecs/django')].logStreamName | [0]" --output text)
aws logs tail /aws/ecs/reverse-proxy-cluster --log-stream-names "$LOG_STREAM" --since 10m

Nginx の最新ログストリームを取得

Nginx の最新のログストリームを取得し、ログを表示するには以下のコマンドを使用します。

LOG_STREAM=$(aws logs describe-log-streams --log-group-name "/aws/ecs/reverse-proxy-cluster" --query "logStreams[?starts_with(logStreamName, 'ecs/nginx')].logStreamName | [0]" --output text)
aws logs tail /aws/ecs/reverse-proxy-cluster --log-stream-names "$LOG_STREAM" --since 10m

実際に遭遇したエラーたち

修正内容一覧

修正箇所 修正内容
default.conf proxy_pass127.0.0.1:8000 に変更
nginx.Dockerfile COPY default.conf /etc/nginx/conf.d/default.conf に修正
settings.py STATIC_ROOT/app/staticfiles に設定
task-def.json STATIC_ROOT の環境変数を追加
docker-compose.yml depends_on を削除
task-def.json networkModeawsvpc に変更

まとめ

この記事は、自分用の備忘録としてまとめたものです。その点をご理解いただけると幸いです。

もし、この記事の内容が少しでも参考になれば嬉しく思います。

今後も同様の内容を継続して投稿していきますので、温かく見守っていただけるとありがたいです。

1
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?