はじめに
今回ITスクールのハッカソンで初めてインフラを担当し、備忘録としてCloudFront + S3の構築手順をまとめてみました。(今回はDjangoを使用しています)
実際に下記のAWS構成図で構築しました。
構築手順
1.S3バケットを作成する
2.S3のCORS設定
3.CloudFrontディストリビューションを作成する
4.S3バケットポリシーをOAC用へ変更する
5.Djangoのsettings.pyの編集
6.collectstaticの実行
7.CloudFrontのキャッシュ無効化
1.S3バケットを作成する
- バケット名を決める:世界で一意の名前を入力
- リージョン:ap-northeast-1
- オブジェクト所有者 : ACL 無効(推奨)
- ブロックパブリックアクセス設定 : すべてON(デフォルトのまま)
- バケットのバージョニング : 無効にする(静的ファイル用途のバケットでは、バージョニングは無効で問題なし)
- バケットタグ:任意
- デフォルトの暗号化 : SSE-S3(デフォルト)
- バケットキー : 無効にする(今回 SSE-KMS を使わないので触る必要なし)
2.S3のCORS設定
CloudFrontはS3のファイルを取得できますが、ブラウザはCloudFront から配信された静的ファイルのレスポンスにS3のCORSヘッダーを参照してアクセスの可否を判断します。
そのため、ブラウザが静的ファイルを正しく読み込めるように、S3側にCORS設定をしていきます。
- S3 バケットのアクセス許可タブにある Cross-Origin Resource Sharing (CORS) に、許可設定をJSON形式で記述。
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedOrigins": ["https://dxxxx.cloudfront.net"],
"ExposeHeaders": []
}
]
3.CloudFrontディストリビューションを作成する
- Distribution name : 任意の名前を入力
- Distribution type : Single website or app
- Domain : 今回は不要(Django本体は ALB 側で HTTPS 導入済み)
- Origin type : Amazon S3
- S3 origin : 作成したS3静的バケットを選択
- Origin path : 空欄のままでOK
- Allow private S3 bucket access to CloudFront : チェックを入れる
- Origin settings : Use recommended origin settings
- Cache settings : Use recommended cache settings tailored to serving S3 content
- Web Application Firewall (WAF) : 今回はセキュリティ保護を有効にしない
OAC(Origin Access Control)は上記のAllow private S3 bucket access to CloudFrontでチェックを入れることにより自動作成される。
Viewer(ビューワー)設定では、ユーザーが CloudFront にアクセスする際どのように動作するかを設定します。
静的ファイル配信の場合はデフォルト設定で問題ありませんが、HTTPS を強制するためRedirect HTTP to HTTPSを選択しておくのが推奨です。
4.S3バケットポリシーをOAC用へ変更する
- S3バケットのアクセス許可タブにある、Bucket policyセクションで「Edit」をクリックして編集。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::<S3バケット名>/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::<アカウントID>:distribution/<ディストリビューションID>"
}
}
}
]
}
上記のポリシーは、ディストリビューションを作成後、正常に作成されたメッセージの下に、「S3 バケットポリシーを更新する必要があります」という警告が表示されるので、「ポリシーをコピー」をクリックして貼り付けます。
5.Djangoのsettings.pyの編集
- CloudFront/S3の設定を追記する
USE_S3 = not DEBUG #本番のみS3 + CloudFrontを使用
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_DIRS = [BASE_DIR / "static"]
if USE_S3:
INSTALLED_APPS += ["storages"]
AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME")
AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME")
AWS_S3_CUSTOM_DOMAIN = os.getenv("AWS_S3_CUSTOM_DOMAIN")
AWS_LOCATION = "static"
AWS_DEFAULT_ACL = None
AWS_S3_FILE_OVERWRITE = False
STATIC_URL = f"https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_LOCATION}/"
#Django 4.2以降はこちらを使用
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "storages.backends.s3boto3.S3StaticStorage",
"OPTIONS": {
"bucket_name": AWS_STORAGE_BUCKET_NAME,
"location": AWS_LOCATION,
"custom_domain": AWS_S3_CUSTOM_DOMAIN,
},
},
}
else:
#ローカル開発用
STATIC_URL = "/static/"
6.collectstaticの実行
docker exec -it <Djangoのコンテナ名> python manage.py collectstatic --noinput
実行すると S3 バケットに static/ 以下がアップロードされる。
7.CloudFrontのキャッシュ無効化
- CloudFrontのInvalidationsより作成する
- object pathsは
/*を入力
CloudFront作成直後で、まだキャッシュが存在しない場合はInvalidationは必須ではありません。ただし、構築中に何度かcollectstaticを実行している場合や、確実に最新ファイルを反映させたい場合は、キャッシュ無効化を行うのが安全です。
requirements.txt の設定
CloudFront + S3をDjangoから利用するために、以下のライブラリを追記します。
- django-storages
- boto3
本記事ではEC2のIAM Roleを利用してS3にアクセスするため、IAMユーザーやアクセスキーの作成は不要です。
おわりに
初学者の記事ですので、間違っている点がありましたらご指摘頂けると助かります。
