In today’s digital landscape, having a reliable and scalable infrastructure for hosting static files is crucial for web applications. Django, a popular Python web framework, offers seamless integration with Amazon Web Services (AWS) to accomplish this task. In this guide, we will explore how to host Django static files in AWS using CloudFront, a powerful content delivery network (CDN) service, to ensure high availability and fast content delivery.
The article is a step-by-step guide on how to achieve the goal, but nevertheless, I assume that the reader has basic knowledge of Django and AWS.
Understanding Django Static Files
Before diving into the technical aspects, it’s important to understand Django static files. These files include CSS stylesheets, JavaScript scripts, images, and other assets that are served directly by the web server without any processing. Managing static files efficiently enhances the overall performance and user experience of your Django application.
Normally, when you deploy a service into production using Django, especially when you put the settings variable DEBUG=False Django excepts you to provide a way to handle these static files like a cloud service or CDN. What happens in this flow it’s that whenever the service wants to access those files, they’re fetched from the CDN or a cloud service instead of living in the same codebase as the web service itself.
For this article, we are going to use AWS Services called S3 and CloudFront.
-
Amazon S3 is a highly scalable and durable cloud storage service provided by Amazon Web Services (AWS). It allows you to store and retrieve large amounts of data, such as images, videos, documents, and backups, in a secure and reliable manner. S3 provides an object-based storage model, where each object is stored in a bucket and accessed using a unique key.
-
Amazon CloudFront is a content delivery network (CDN) also provided by Amazon Web Services. It helps deliver content, such as web pages, images, videos, and other static or dynamic files, to users with low latency and high transfer speeds. CloudFront caches the content at edge locations, which are distributed globally, closer to the users, reducing the distance and network latency. This improves the performance of delivering content to users across different regions.
Setting up IAM User
Login with your root user and then continue to create a new user that you will use during this exercise. You’ll need to create a user that has access to
S3 and CloudFront:
-
Navigate to IAM > Users > Add New User
-
Enter the username you want for your user and in the next step, select Attach policies directly tab.
-
Attach these two policies: CloudFrontFullAccess and AmazonS3FullAccess
Or if you want to skip this part (for simplicity), just use the root user (but this is not recommended in any case for the sake of security)
Setup S3 and CloudFront
First, we need the S3 bucket on which we are going to upload our static files. Navigate to the S3 console and click > Create Bucket
-
Enter a name for the bucket and select the region
-
Keep ACL-s disabled
-
Tick Block all public access and leave everything else as default
You’re good to go!
Now let’s set up CloudFront for the newly created Bucket.
Since we kept everything private in our bucket, we need to let CloudFront access some of the folders that exist in our bucket.
Navigate to the CloudFront console and click Create a CloudFront distribution. After that, you might need to fill up some information:
-
Origin Domain: Choose the S3 Bucket that you created
-
Origin Access: Choose Legacy access identities and then click Create new OAI
-
On the bucket policy select: Yes, update the bucket policy
-
Allowed HTTP methods: GET, HEAD, OPTIONS
-
Web Application Firewall (WAF): Do not enable security protections
-
Response headers policy SimpleCORS
That’s it, keep everything else as default. Now a new CloudFront distribution will be created and will return back a Distribution domain name which in my case looks something like this:
https://d29u7vv9xp7q8y.cloudfront.nethttps://d29u7vv9xp7q8y.cloudfront.nethttps://d29u7vv9xp7q8y.cloudfront.net
Enter fullscreen mode Exit fullscreen mode
Great, now let’s make the necessary changes in our Django application.
Setting up our Django application — Uploading static files
In order to upload our static files to the AWS S3 bucket, we need to turn off DEBUG mode and also update some settings and configurations in our Django application. To start off, first, install django-storageslibrary which is a library to handle storages better in Django.
$ pip install django-storages$ pip install django-storages$ pip install django-storages
Enter fullscreen mode Exit fullscreen mode
With that done, create a new Python module named storage_backends.py and add the following code:
from django.conf import settingsfrom storages.backends.s3boto3 import S3Boto3Storageclass StaticStorage(S3Boto3Storage):location = 'static'custom_domain = settings.CLOUDFRONT_DOMAINfrom django.conf import settings from storages.backends.s3boto3 import S3Boto3Storage class StaticStorage(S3Boto3Storage): location = 'static' custom_domain = settings.CLOUDFRONT_DOMAINfrom django.conf import settings from storages.backends.s3boto3 import S3Boto3Storage class StaticStorage(S3Boto3Storage): location = 'static' custom_domain = settings.CLOUDFRONT_DOMAIN
Enter fullscreen mode Exit fullscreen mode
This will tell that you want to upload static files to a folder named static and the custom domain to handle and redirect the static files would be the CLOUDFRONT_DOMAIN which is set up in settings.py
NOTE: to not hard-code the environment variables as below and use a mechanism to manage the environment variables. A simple one would be os.getenv().
Modify the settings and add the following environment variables:
DEBUG = FalseAWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID'AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY'AWS_STORAGE_BUCKET_NAME = 'NAME_OF_BUCKET'AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'AWS_S3_REGION_NAME = "YOUR_LOCATION_IN_AWS"AWS_S3_SIGNATURE_VERSION = "s3v4"AWS_QUERYSTRING_EXPIRE = 604800CLOUDFRONT_DOMAIN = 'YOUR_CLOUD_FRONT.cloudfront.net'STATIC_LOCATION = "static"STATIC_URL = f'{CLOUDFRONT_DOMAIN}/static/'# Add your path in the STATICFILES_STORAGESTATICFILES_STORAGE = 'django_static.storage_backends.StaticStorage'DEBUG = False AWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID' AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY' AWS_STORAGE_BUCKET_NAME = 'NAME_OF_BUCKET' AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' AWS_S3_REGION_NAME = "YOUR_LOCATION_IN_AWS" AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_QUERYSTRING_EXPIRE = 604800 CLOUDFRONT_DOMAIN = 'YOUR_CLOUD_FRONT.cloudfront.net' STATIC_LOCATION = "static" STATIC_URL = f'{CLOUDFRONT_DOMAIN}/static/' # Add your path in the STATICFILES_STORAGE STATICFILES_STORAGE = 'django_static.storage_backends.StaticStorage'DEBUG = False AWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID' AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY' AWS_STORAGE_BUCKET_NAME = 'NAME_OF_BUCKET' AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' AWS_S3_REGION_NAME = "YOUR_LOCATION_IN_AWS" AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_QUERYSTRING_EXPIRE = 604800 CLOUDFRONT_DOMAIN = 'YOUR_CLOUD_FRONT.cloudfront.net' STATIC_LOCATION = "static" STATIC_URL = f'{CLOUDFRONT_DOMAIN}/static/' # Add your path in the STATICFILES_STORAGE STATICFILES_STORAGE = 'django_static.storage_backends.StaticStorage'
Enter fullscreen mode Exit fullscreen mode
This should be enough. Now before you start your Django application, open a new console and collect the static files:
python manage.py collectstaticYou have requested to collect static files at the destinationlocation as specified in your settings.This will overwrite existing files!Are you sure you want to do this?Type 'yes' to continue, or 'no' to cancel: yes125 static files copied.python manage.py collectstatic You have requested to collect static files at the destination location as specified in your settings. This will overwrite existing files! Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: yes 125 static files copied.python manage.py collectstatic You have requested to collect static files at the destination location as specified in your settings. This will overwrite existing files! Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: yes 125 static files copied.
Enter fullscreen mode Exit fullscreen mode
Now navigate to your AWS account go to your bucket and see if the files are copied to a folder named static , if they’re, everything worked as expected.
Testing CloudFront Integration:
Now it’s time to test whether CloudFront is serving your static files correctly. Start your Django development server and access your application. Inspect the network requests using your browser’s developer tools to verify that the static files are being fetched from the CloudFront URL you specified.
python manage.py runserverPerforming system checks...System check identified no issues (0 silenced).July 30, 2023 - 16:58:13Django version 4.2.3, using settings 'django_static.settings'Starting development server at http://127.0.0.1:8000/Quit the server with CONTROL-C.python manage.py runserver Performing system checks... System check identified no issues (0 silenced). July 30, 2023 - 16:58:13 Django version 4.2.3, using settings 'django_static.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.python manage.py runserver Performing system checks... System check identified no issues (0 silenced). July 30, 2023 - 16:58:13 Django version 4.2.3, using settings 'django_static.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Enter fullscreen mode Exit fullscreen mode
Now visit localhost:8000/admin or 127.0.0.1/admin and open developer tools, for example in Google Chrome: CTRL+SHIFT+I and go to the network tab. Click one of the .css files and navigate to Headers to see the requested URL and see if it’s pointing to the CloudFront URL that you defined in settings.py.
Enabling CloudFront Cache Invalidation:
To ensure that your users receive the latest versions of your static files, configure CloudFront cache invalidation. There are two common approaches to achieving this. You can manually invalidate the CloudFront cache whenever you update your static files by using the AWS Management Console or AWS CLI. Alternatively, you can implement cache invalidation techniques in your Django application, such as versioning static files or appending a query string parameter.
Wrapping up
In this article, we have set up a Python application with Django & Deploy and serve the static files from CloudFront.
You can find the full source code of the article on the GitHub repository, with the instructions.
www.github.com/vjanz/django-static-files-s3-cloudfront
If you found it helpful, please don’t forget to clap & share it on your social network or with your friends.
If you want to support my work, you can buy me a coffee by clicking the image below
If you have any questions, feel free to reach out to me.
Connect with me on LinkedIn, GitHub
原文链接:Hosting Django Static Files in AWS using S3 and CloudFront: A Comprehensive Guide
暂无评论内容