見出し画像

Django_本番環境構築③_静的ファイルをS3からホスティングする #366

本番環境構築シリーズの第3弾です。
第1弾と第2弾は以下です。


前回まででEC2上でアプリケーションを起動しつつ、HTTPS通信でアクセスできるようところまで設定できました。

今回はDjangoとS3の設定を変え、静的ファイルのホスティングをS3から行えるようにしていきたいと思います。

パブリックアクセス可能なS3バケットが1つ準備してある前提です。

ではそれぞれの設定をメモしていきます。

S3のアクセス許可設定

今回は「バケットポリシー」と「Cross-Origin Resource Sharing (CORS)」に許可設定をしていきます。どちらもJSON形式で設定を定義できます。

また、今回はS3からのホスティングを成功させることに重きを置いており、アクセス許可はかなり緩い条件になっています。本来であればCORSで許可するオリジンを指定するなどしてセキュリティを高めておくのが望ましいです。

バケットポリシー

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

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "PublicRead",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::your-bucket-name/*"
		}
	]
}

このポリシーの各要素を説明します。

  1. Version: ポリシーバージョンです。このフィールドは必須で、現在のバージョンは "2012-10-17" です。

  2. Statement: ポリシーの主要部分で、1つ以上のステートメント(許可や制限のルール)を含む配列です。以降の要素を全て含む形になっています。

  3. Sid: ステートメントの識別子(オプション)です。わかりやすい名前を付けることで、このステートメントが何をするかを説明できます。この例では "PublicRead" という名前が付けられています。

  4. Effect: ステートメントが許可("Allow")されているか、拒否("Deny")されているかを示します。

  5. Principal: ステートメントが適用されるエンティティ(ユーザー、アカウント、サービスなど)を指定します。この例では、すべてのエンティティに適用されるため、ワイルドカード(*)が使用されています。

  6. Action: ステートメントが許可または拒否されるアクションを指定します。この例では、s3:GetObjectアクションが指定されており、オブジェクトを取得する権限が与えられています。

  7. Resource: ステートメントが適用されるリソースを指定します。この例では、指定されたバケット内のすべてのオブジェクトに適用されるように、ARN(Amazon Resource Name)が指定されています。your-bucket-nameを実際のバケット名に置き換える必要があります。

ちなみにAcitionでファイル作成などの書き込み許可も与えたい場合はPutObjectを追加すればOKです。リスト形式で記述します。

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "PublicRead",
			"Effect": "Allow",
			"Principal": "*",
			"Action": [
				"s3:GetObject",
				"s3:PutObject"
			],
			"Resource": "arn:aws:s3:::your-bucket-name/*"
		}
	]
}


ちなみにS3バケットポリシーが設定されていない場合、バケットとそのオブジェクトはデフォルトでプライベートとなります。これは、AWSアカウントの所有者と、彼らが明示的にアクセス権限を与えたIAMユーザーおよびロールのみが、バケットやそのオブジェクトにアクセスできることを意味します。

S3バケットポリシーが設定されていない場合でも、IAMポリシーやPre-signed URLを使って特定のユーザーやロールにアクセス権限を与えること自体は可能です。

Cross-Origin Resource Sharing (CORS)

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

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

許可するHeader, Method, Originをシンプルに指定する形です。ここではワイルドカード('*')を多く使って緩めの条件になっています。


Django側の設定

settings.pyで以下のように設定します。本番環境と開発環境の使い分けという意味では、「Debug=False」の時に以下設定がされるように条件分岐しておくのも一手です。

if not DEBUG:
    INSTALLED_APPS += ['storages']
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    # Amazon S3 settings
    AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
    AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
    AWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']
    AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
    AWS_DEFAULT_ACL = None
    AWS_LOCATION = 'yt-converter/static'
    AWS_QUERYSTRING_AUTH = False
    AWS_S3_OBJECT_PARAMETERS = {
        'CacheControl': 'max-age=86400',
    }

    # Static files settings
    STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_LOCATION}/'
    STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

    # Media files settings
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

ACCESS_KEYやSECRET_ACCESS_KEYなどの情報はハードコードせず、.envファイルに入れておいて読み込む形が良いと思います。

上記の設定をしておけば、Nginxでstaticのパスを定義する必要がなくなり、DjangoからS3に直接リクエストを投げるようになります。

これで静的ファイルをS3からホスティングできるようになったはずです。


ここまでお読みいただきありがとうございました!!


この記事が気に入ったらサポートをしてみませんか?