How to create an image CDN using AWS S3 and cloudfront
Image delivery performance is crucial for modern web applications. By creating your own image CDN using AWS S3 and CloudFront, you can significantly improve load times and user experience. This guide will walk you through setting up a robust image CDN infrastructure.
Why use a CDN for images
Content Delivery Networks (CDNs) offer several advantages for image delivery:
- Reduced latency through edge location caching
- Lower bandwidth costs by offloading traffic from your origin server
- Improved website performance with faster page load times
- Better user experience across different geographical locations
- Protection against traffic spikes to handle sudden increases in demand
Setting up an AWS S3 bucket
-
Create a New S3 Bucket:
- Log into the AWS Management Console.
- Navigate to S3.
- Click Create bucket.
- Enter a unique bucket name.
- Select your preferred AWS Region.
- Keep Block all public access enabled for security.
- Click Create bucket.
-
Configure Bucket Policy:
Update your bucket policy to allow CloudFront to access your S3 bucket securely. Replace
'your-bucket-name'
,'your-account-id'
, and'your-distribution-id'
with your actual values.{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::your-bucket-name/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::your-account-id:distribution/your-distribution-id" } } } ] }
-
Enable CORS (if needed):
If your application requires Cross-Origin Resource Sharing (CORS), configure the CORS policy for your S3 bucket.
[ { "AllowedHeaders": ["*"], "AllowedMethods": ["GET"], "AllowedOrigins": ["*"], "ExposeHeaders": [], "MaxAgeSeconds": 3000 } ]
Configuring cloudfront
-
Create a CloudFront Distribution:
- Navigate to the CloudFront console.
- Click Create Distribution.
- Under Origin domain, enter your S3 bucket's domain (e.g.,
your-bucket-name.s3.amazonaws.com
). - For Origin access, select Origin Access Control (OAC).
- Click Create new OAC to allow CloudFront to securely access your S3 bucket.
- Ensure that Bucket Policy is updated to grant access to the OAC.
-
Configure Default Cache Behavior:
- Scroll down to Default cache behavior settings.
- Set Viewer protocol policy to Redirect HTTP to HTTPS.
- Under Allowed HTTP methods, select GET, HEAD, OPTIONS.
- Enable Cached HTTP methods for GET and HEAD.
- Set Cache key and origin requests to customize cache key settings if needed.
-
Configure Cache Settings:
- Set Default TTL to
86400
seconds (1 day). - Set Maximum TTL to
31536000
seconds (1 year). - Set Minimum TTL to
0
seconds.
- Set Default TTL to
-
Enable Compression:
- Under Compression, set Compress objects automatically to Yes.
- This enables automatic compression for supported file types, reducing bandwidth usage.
-
Review and Create:
- Review your settings.
- Click Create Distribution.
- Wait for the distribution status to become Deployed, which may take several minutes.
Optimizing image delivery
-
Configure Cache-Control Headers:
When uploading images to S3, set appropriate
Cache-Control
headers to control caching behavior.s3_client.put_object( Bucket='your-bucket-name', Key='path/to/image.jpg', Body=image_data, ContentType='image/jpeg', CacheControl='public, max-age=31536000' )
This example uses the AWS SDK for Python (boto3). Adjust the code according to your preferred programming language.
-
Use Query String Parameters for Versioning:
Append a version query parameter to your image URLs to manage cache invalidation upon updates.
https://d1234.cloudfront.net/images/logo.png?v=2
-
Enable WebP Support:
Use CloudFront Functions or Lambda@Edge to serve WebP images to browsers that support it. Here's an example CloudFront Function in JavaScript:
function handler(event) { var request = event.request var headers = request.headers if (headers.accept && headers.accept.value.includes('image/webp')) { request.uri = request.uri.replace(/\.(jpg|png)$/, '.webp') } return request }
This function checks if the
Accept
header includesimage/webp
and rewrites the request URI to serve WebP images.
Testing your CDN
-
Verify Distribution Status:
- Ensure your CloudFront distribution status is Deployed.
-
Test Image Loading:
Embed an image from your CloudFront distribution into your website or a test HTML page.
<img src="https://your-distribution-id.cloudfront.net/images/test.jpg" alt="Test Image" loading="lazy" width="800" height="600" />
Replace
your-distribution-id
andtest.jpg
with your actual distribution domain and image path. -
Monitor Performance:
- Use AWS CloudWatch metrics to monitor your distribution.
- Check Cache Hit Ratio to ensure caching is effective.
- Monitor Error Rates for any issues.
- Track Latency to measure performance improvements.
Best practices
-
Image Optimization:
- Use appropriate formats: JPEG for photographs, PNG for graphics with transparency.
- Implement responsive images using
srcset
andsizes
attributes. - Enable Brotli or GZIP compression for text-based assets.
-
Security:
- Use HTTPS exclusively to encrypt data in transit.
- Implement proper CORS policies if serving assets across different domains.
- Use Signed URLs or Signed Cookies for private content requiring controlled access.
-
Performance:
- Set appropriate TTL values to balance freshness and cache efficiency.
- Use query strings for cache-busting when updating assets.
- Implement custom error pages to enhance user experience in case of failures.
Conclusion
Setting up an image CDN using AWS S3 and CloudFront provides a robust solution for delivering images efficiently across the globe. This setup offers excellent performance, scalability, and security features essential for modern web applications.
If you're looking for a managed solution that handles both CDN functionality and advanced image processing, check out Transloadit, which offers comprehensive image optimization and delivery capabilities.