Contents
前提条件と準備
本章では、Django アプリを AWS Elastic Beanstalk(以下 EB)へデプロイするために必要なツールや IAM 設定をまとめます。事前に環境が整っていないと、デプロイ時に認証エラーやリソース作成失敗が頻発しますので、ここで示す手順を必ず実施してください。
必要なツールのインストール
| ツール | 推奨バージョン | インストールコマンド |
|---|---|---|
| AWS CLI | 2.x 系(2026 年時点で最新) | pip install awscli --upgrade |
| EB CLI (v2) | 2.20 以上 | pip install awsebcli --upgrade |
| Docker Engine | 24 系列 | https://docs.docker.com/engine/install/ |
| Git | 2.45 以上 | OS のパッケージマネージャーでインストール |
ポイント:全ツールは同一のシェル(例:
bash)で実行できることを確認し、バージョンが期待通りか--versionコマンドで検証してください。
AWS 認証情報とリージョン設定
|
1 2 3 |
aws configure # Access Key, Secret Key, デフォルトリージョンは ap-northeast-1 を指定 eb init # プロジェクトディレクトリで実行し、アプリ名・プラットフォームを選択 |
※ 以降のすべてのコマンドは ap-northeast-1(東京)を前提に記載します。リージョンがずれると EB が作成できない、S3 バケットが見つからない等のエラーが発生しますので注意してください。
IAM ポリシー・ロールの最小権限設定
| 項目 | 推奨設定 |
|---|---|
| カスタムポリシー | AWSElasticBeanstalkFullAccess、AmazonRDSFullAccess、AmazonS3FullAccess のうち必要なアクションだけを列挙した最小権限ポリシー |
| ロール | aws-elasticbeanstalk-ec2-role に上記カスタムポリシーをアタッチし、EC2 が S3・RDS にアクセスできるようにする |
| MFA | デプロイ用 IAM ユーザーには MFA を必須化し、aws sts get-session-token で一時的な認証情報を取得して使用 |
Django プロジェクトの本番設定
この章では、Django の settings.py に加えるべき本番向け項目と、その裏にあるセキュリティ・スケーラビリティ上の根拠を解説します。
DEBUG と ALLOWED_HOSTS の基本方針
|
1 2 3 4 5 6 |
DEBUG = False ALLOWED_HOSTS = [ '.example.com', # カスタムドメイン(ワイルドカード) 'myapp.elasticbeanstalk.com' # EB が自動付与するデフォルトホスト名 ] |
DEBUG=True のままだと例外情報がそのままブラウザに出力され、攻撃者に有用な手掛かりを提供します。ALLOWED_HOSTS を正しく設定しないと Django がリクエストを拒否するため、必ずデプロイ前に確認してください。
静的ファイル・メディアファイルの S3 バックエンド化
設定例(settings.py)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import os AWS_STORAGE_BUCKET_NAME = os.getenv('S3_BUCKET_NAME') AWS_S3_REGION_NAME = 'ap-northeast-1' AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY') # S3 の URL 形式は CloudFront 経由で配信することを想定 STATIC_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.cloudfront.net/static/' MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.cloudfront.net/media/' DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' # 正しいクラス名は S3ManifestStaticFilesStorage(マニフェストによるキャッシュバスター) STATICFILES_STORAGE = 'storages.backends.s3boto3.S3ManifestStaticFilesStorage' |
S3Boto3Storageはメディアファイル全般に使用し、S3ManifestStaticFilesStorageはcollectstatic時に生成されるマニフェストを利用してキャッシュ破棄を自動化します。- 直接 S3 のエンドポイント (
*.s3.amazonaws.com) を公開すると URL が長くなり、HTTPS 証明書の管理が煩雑になるため CloudFront 経由で配信することを推奨します。
安全なバケットポリシー(CloudFront OAI 使用例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowCloudFrontReadOnly", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E3EXAMPLEOAI" }, "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::my-django-bucket/*"] } ] } |
Principalを"*"にすると全世界からの読み取りが可能になり、情報漏洩リスクが高まります。- Origin Access Identity (OAI) を作成し、CloudFront のみがバケットにアクセスできるよう制限することで、署名付き URL と同等のセキュリティを確保できます。
機密情報は Parameter Store / Secrets Manager で管理
| 項目 | 推奨サービス |
|---|---|
| データベース認証情報 | AWS Systems Manager Parameter Store(SecureString)または Secrets Manager |
| API キー・トークン | 同上、ローテーションが必要な場合は Secrets Manager が便利 |
| 環境変数の注入 | EB の「Software」→「Environment properties」で aws:elasticbeanstalk:application:environment にキーを設定し、{{resolve:ssm:/myapp/DB_PASSWORD}} 形式で参照 |
Parameter Store から取得するコード例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import boto3, os ssm = boto3.client('ssm', region_name='ap-northeast-1') def get_secret(name): return ssm.get_parameter(Name=name, WithDecryption=True)['Parameter']['Value'] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.getenv('RDS_DB_NAME'), 'USER': os.getenv('RDS_USERNAME'), 'PASSWORD': get_secret('/myapp/DB_PASSWORD'), 'HOST': os.getenv('RDS_HOSTNAME'), 'PORT': os.getenv('RDS_PORT', '5432') } } |
Elastic Beanstalk 環境の作成と初回デプロイ
この章では Docker マルチコンテナ構成を EB にデプロイする手順を示します。全工程は CLI のみで完結でき、インフラコードとして再現性が保証されます。
Dockerrun.aws.json(マルチコンテナ)概要
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
{ "AWSEBDockerrunVersion": "2", "containerDefinitions": [ { "name": "web", "image": "myrepo/django-app:latest", "essential": true, "memory": 512, "portMappings": [{ "hostPort": 80, "containerPort": 8000 }], "environment": [ { "name": "DJANGO_SETTINGS_MODULE", "value": "myproject.settings.production" }, { "name": "S3_BUCKET_NAME", "value": "my-django-bucket" } ], "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/elasticbeanstalk/myapp", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "web" } } }, { "name": "nginx", "image": "nginx:latest", "essential": true, "memory": 256, "portMappings": [{ "hostPort": 80, "containerPort": 80 }], "links": ["web"] } ] } |
- ポイント:
awslogs-regionは必ずap-northeast-1に統一し、リージョン不一致によるログ取得失敗を防ぎます。 Dockerfileと.dockerignoreは同ディレクトリに配置し、.ebextensionsで追加設定(例:collectstatic)を行います。
EB CLI による環境作成手順
- プロジェクト初期化(リージョン固定)
bash
eb init -p docker my-django-app --region ap-northeast-1
- 環境作成(最低 2 台で Auto Scaling を有効化)
bash
eb create prod-env \
--instance_type t3.medium \
--scale 2 \
--vpc.id vpc-xxxxxxxx \
--subnet.ids subnet-aaaa,subnet-bbbb \
--elb-type application \
--healthcheck-url /health/
- 環境変数・SSM 参照設定(
.ebextensions/options.config)
yaml
option_settings:
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: myproject.settings.production
S3_BUCKET_NAME: my-django-bucket
DB_PASSWORD_SSM: /myapp/DB_PASSWORD
- collectstatic の自動実行(
.ebextensions/01_collectstatic.config)
yaml
container_commands:
01_collectstatic:
command: |
source /opt/python/run/venv/bin/activate
python manage.py collectstatic --noinput
leader_only: true
- コードプッシュとデプロイ
bash
git add .
git commit -m "Configure production environment"
eb deploy prod-env
注意:
eb deployが完了したらeb openでブラウザを起動し、正常に Django のトップページが表示されることを必ず確認してください。
データベースとストレージの連携
Amazon RDS(PostgreSQL)作成とパラメータ取得
|
1 2 3 4 5 6 7 8 9 10 11 |
aws rds create-db-instance \ --db-instance-identifier myapp-db \ --engine postgres \ --allocated-storage 20 \ --db-instance-class db.t3.medium \ --master-username admin \ --master-user-password $(aws ssm get-parameter --name /myapp/DB_PASSWORD --with-decryption --query Parameter.Value --output text) \ --backup-retention-period 7 \ --vpc-security-group-ids sg-xxxxxxxx \ --availability-zone ap-northeast-1a |
作成後、エンドポイントを Parameter Store に保存します。
|
1 2 3 4 5 6 |
aws ssm put-parameter \ --name "/myapp/DB_ENDPOINT" \ --value "$(aws rds describe-db-instances --db-instance-identifier myapp-db --query 'DBInstances[0].Endpoint.Address' --output text)" \ --type String \ --overwrite |
Django 側で RDS 接続情報を取得
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import boto3, os ssm = boto3.client('ssm', region_name='ap-northeast-1') db_endpoint = ssm.get_parameter(Name='/myapp/DB_ENDPOINT')['Parameter']['Value'] db_password = ssm.get_parameter(Name='/myapp/DB_PASSWORD', WithDecryption=True)['Parameter']['Value'] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.getenv('RDS_DB_NAME'), 'USER': os.getenv('RDS_USERNAME'), 'PASSWORD': db_password, 'HOST': db_endpoint, 'PORT': '5432', } } |
S3 バケットの作成・CORS設定(CloudFront 用)
|
1 2 3 4 5 |
aws s3api create-bucket \ --bucket my-django-bucket \ --region ap-northeast-1 \ --create-bucket-configuration LocationConstraint=ap-northeast-1 |
CORS(例:全ドメインからの GET を許可)
|
1 2 3 4 5 6 7 8 9 |
[ { "AllowedHeaders": ["*"], "AllowedMethods": ["GET", "HEAD"], "AllowedOrigins": ["https://*.cloudfront.net"], "MaxAgeSeconds": 3000 } ] |
CloudFront ディストリビューション作成(簡易例)
|
1 2 3 4 5 6 7 |
aws cloudfront create-distribution \ --origin-domain-name my-django-bucket.s3.amazonaws.com \ --default-root-object index.html \ --viewer-protocol-policy redirect-to-https \ --enabled true \ --origins Quantity=1,Items=[{Id=myS3Origin,DomainName=my-django-bucket.s3.amazonaws.com,S3OriginConfig={OriginAccessIdentity=origin-access-identity/cloudfront/E3EXAMPLEOAI}}] |
ポイント:CloudFront が S3 にアクセスできるよう OAI を必ず設定し、バケットポリシー側でも同一 OAI の ARN を許可してください。
CI/CD と運用・監視
GitHub Actions での自動デプロイ(リージョン統一)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
name: Deploy to Elastic Beanstalk on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write # OIDC 用 (推奨) steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install EB CLI run: pip install awsebcli --upgrade - name: Configure AWS credentials (OIDC) # GitHub の OIDC で AssumeRole を行う例。事前に IAM Role と信頼ポリシーを設定。 uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsEBDeploy aws-region: ap-northeast-1 - name: Deploy to EB env: EB_APP_NAME: my-django-app EB_ENV_NAME: prod-env run: | eb init $EB_APP_NAME --region ap-northeast-1 eb use $EB_ENV_NAME eb deploy $EB_ENV_NAME --staged |
- OIDC を利用するとシークレット管理が不要になり、AWS 側で最小権限ロールを付与できるためセキュリティが向上します。
eb initの--regionは必ずap-northeast-1に統一し、リージョンミスマッチによる失敗を防ぎます。
CloudWatch でのログ・ヘルス監視
| 項目 | 推奨設定 |
|---|---|
| アプリケーションログ | /elasticbeanstalk/myapp/web に集約。ERROR レベル以上をフィルタリングし、SNS 通知を設定 |
| Nginx ログ | 同上の別ストリーム(nginx-access / nginx-error)で取得 |
| ヘルスチェックエンドポイント | /health/ が 200 を返すことを前提に、Elastic Beanstalk の「Health」ステータスが Green になるか確認 |
| CPU・メモリアラート | CPU > 70%(5 分連続) → Auto Scaling Group の最大サイズを +1、SNS 通知も同時送信 |
よくあるエラーと対処法
| エラー | 原因例 | 解決策 |
|---|---|---|
| 500 Internal Server Error | ALLOWED_HOSTS が不足、SSM パラメータ取得失敗 |
eb logs でスタックトレース確認 → 必要な環境変数が設定されているか、Parameter Store の IAM 権限を再チェック |
| 504 Gateway Timeout | アプリ起動に時間が掛かりヘルスチェックがタイムアウト | EB 環境の HealthCheckTimeout を 30 秒以上へ拡張し、gunicorn の --timeout オプションも同様に調整 |
| S3 AccessDenied | バケットポリシーが OAI に限定されていない、または IAM ロールが s3:PutObject を欠く |
IAM ロールへ s3:PutObject, s3:GetObject を付与し、バケットポリシーに正しい OAI ARN が記載されているか確認 |
| RDS 接続タイムアウト | SG のインバウンドが EB インスタンスの SG と不一致 | RDS SG に EB 用 SG の ID を追加し、ポート 5432(PostgreSQL)/3306(MySQL)を許可 |
| collectstatic が失敗 | django-storages バージョン不整合、または S3 権限不足 |
pip install --upgrade django-storages boto3 後に再デプロイし、STATICFILES_STORAGE が正しいクラス名か確認 |
まとめ
- リージョン統一:全コマンド・設定ファイルは
ap-northeast-1に固定。異なるリージョンが混在するとリソース作成失敗の原因になる。 - 最小権限 IAM:デプロイユーザーと EC2 ロールには必要最低限のポリシーだけ付与し、MFA と OIDC で認証を強化。
- S3 静的配信は CloudFront + OAI:バケットポリシーを
Principal: "*"にせず、CloudFront が唯一のアクセス元になるよう制御する。 - 正しいストレージクラス:
STATICFILES_STORAGEはS3ManifestStaticFilesStorageを使用し、キャッシュバスターが自動で付与されるように設定。 - 機密情報は Parameter Store / Secrets Manager:コードベースに埋め込まず、環境変数やテンプレート置換で安全に注入する。
- CI/CD は OIDC + GitHub Actions:シークレット管理の手間を省きつつ、リージョンミス防止のため
aws-regionを明示的に設定。 - 監視は CloudWatch:ログ・ヘルス・リソース使用率を可視化し、アラートで自動スケールや障害通知を実装。
以上のベストプラクティスに沿って構築すれば、2026 年現在の AWS 環境でも 安全かつ拡張性の高い Django アプリ を継続的に運用できます。ぜひ本手順をプロジェクトのデプロイガイドとして取り入れ、インフラのコード化と自動化を推進してください。