February 26, 2024
(Almost) free image processing with imgproxy and AWS Lambda
There are many ways to deploy imgproxy that vary in cost and complexity. Usually, the easiest approaches like Heroku are pretty pricey (not as pricey as an image processing SaaS though), and the most cost-effective ways like AWS ECS or Kubernetes require deeper technical knowledge. Yet it seems like we found an almost no-brainer way to deploy imgproxy that will enable you to benefit from virtually free image processing. In this guide, we will walk you through all the steps required to deploy imgproxy to AWS Lambda using our official CloudFormation template. The actual deployment will only take a few clicks.
What is AWS Lambda?
AWS Lambda is a serverless computing service provided by Amazon as a part of Amazon Web Services. It is a computing service that runs code in response to events and automatically manages the computing resources that your code requires.
We'll be honest with you: we were pretty sceptical about running imgproxy on AWS Lambda. We worried about cold starts and the overall performance. But after talking to our users and running some experiments, we discovered that AWS Lambda is, actually, a surprisingly good fit for imgproxy!
The best thing about AWS Lambda for those who don't want to be bothered with infrastructure, scaling, and all that boring stuff is that Lambda does it all for you—out of the box. And you pay only for the compute time you consume: in serverless computing the concept of "unutilised resources" does not exist. But there are even more things that make AWS Lambda a great fit for imgproxy:
- AWS Lambda supports Docker containers. Since imgproxy is primarily distributed as a Docker container, it's a perfect fit.
- Since recently, AWS Lambda in combination with Lambda Function URLs supports response streaming. It allows the response from the server to be streamed to the client as-is without encoding the response body to base64. Also, the response streaming invoke mode has softer response size limits than the standard buffered invoke mode; this is a huge win for imgproxy.
- AWS Lambda allows you to run functions on Amazon Graviton processors which we're huge fans of. They are more cost-effective and have better performance than x86 processors.
- AWS Lambda has a generous free tier. You get 1 million free requests and 400,000 GB-seconds of compute time per month. This is more than enough for most use cases, and it means that you can get a lot of mileage out of imgproxy without actually paying anything for the underlying infrastructure.
Prerequisites
There are a few things you need to have before you start deploying imgproxy on AWS Lambda:
- An AWS account. Obviously, you can't use AWS Lambda without one.
- An AWS Elastic Container Registry (ECR) repository. You can create one in the AWS Management Console or from the AWS CLI.
- Docker installed on your machine. You'll need it to push the imgproxy image to the ECR repository.
- The AWS CLI installed and configured on your machine. You'll need it to authenticate your Docker client with the ECR registry.
Deploying imgproxy on AWS Lambda
In this guide we assume the following:
- You are going to deploy the latest build of the official Docker image of the OSS version of imgproxy:
ghcr.io/imgproxy/imgproxy:latest
.- If you want to use a specific version of imgproxy, replace
latest
with the version tag. - If you want to deploy the Pro version of imgproxy, replace
ghcr.io/imgproxy/imgproxy
with the Docker repository details you received from us during the order.
- If you want to use a specific version of imgproxy, replace
- If you are going to deploy a specific version of imgproxy, you are deploying version
3.22.0
or later. Docker images of earlier versions don't include AWS Lambda adapter. - You have an ECR repository named
imgproxy
in theus-east-1
region, and your AWS account ID is123456789
. Replaceus-east-1
and123456789
with your actual region and account ID.
Step 1: Push the imgproxy Docker image to the ECR repository
First of all, we need to authenticate your Docker client with the ECR registry. You can do this by running the following command:
# Replace region and account ID (123456789) with your actual region and account IDaws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com
Now, let's pull the imgproxy Docker image, tag it for ECR, and push it to the ECR repository:
docker pull ghcr.io/imgproxy/imgproxy:latest-arm64# Replace region and account ID (123456789) with your actual region and account IDdocker tag ghcr.io/imgproxy/imgproxy:latest-arm64 123456789.dkr.ecr.us-east-1.amazonaws.com/imgproxy:latestdocker push 123456789.dkr.ecr.us-east-1.amazonaws.com/imgproxy:latest
Take note that we are are using a Docker image tag suffixed with -arm64
. This is because we're going to run imgproxy on AWS Lambda with Graviton processors, and this suffix ensures that we're using an image built for ARM64 architecture.
Ok, the boring part is over. Now let's move to the fun part!
Step 2: Deploy imgproxy on AWS Lambda
Now as we have imgproxy Docker image in the ECR repository, the rest is even easier. We're going to use AWS CloudFormation and the template that we prepared for you. The template will create an AWS Lambda function, Function URL, and a CloudFront dictribution for you. To start, just click the button (will require you to login into your AWS account):
This will open the CloudFormation stack creation wizard in the AWS Management Console. On the wizard page, specify the following parameters:
- Stack name: The name of the CloudFormation stack. You can leave the default value.
- Function name: The name of the AWS Lambda function. You can leave it blank to name the function the same as the stack.
- Docker image: The URL of the imgproxy Docker image in the ECR repository. Use the URL for the Docker image that you pushed to the ECR repository in the previous step.
The rest of the parameters are optional and have default values. You can leave them as is or change them if you want.
At the bottom of the page, check all the acknowledgment checkboxes and click Create stack.
Wait for the stack to be created. It will take a few minutes. When the stack is created, you'll see the CREATE_COMPLETE status in the AWS Management Console. Now you can find the direct URL for your function, CloudFront URL, and the instructions on how to configure imgproxy in the Outputs tab of the stack.
That's it! You have successfully deployed imgproxy to AWS Lambda!
Testing the setup
Let's see imgproxy in action! Open the direct URL for your function or CloudFront URL in your browser and, if you just deployed the open source version of imgproxy, you'll see the imgproxy's landing page (imgproxy Pro users will see a blank page). Alternatively, you can add the /health
path to the URL to see the health check response.
But this is boooooring! Let's do something more interesting. Let's process an image!
Let's take a photo of a cute doggy taken by Peter Pryharski, resize it to fill an area of 500x400
pixels with the smart (sm
) gravity, and convert it to AVIF (we live in 2024 after all). To do this, open the following URL in your browser:
https://<your-function-url>/unsafe/rs:fill:500:400/g:sm/f:avif/plain/https://assets.imgproxy.net/sample-corgi.jpg
The cost of imgproxy on AWS Lambda
The cost of running imgproxy on AWS Lambda is very low. You pay only for the compute time you consume. The AWS Lambda free tier includes 1 million free requests and 400,000 GB-seconds of compute time per month. Let's estimeate how much it will cost you to process images with imgproxy on AWS Lambda.
We took a 2040x1356
image in various formats (JPEG, PNG, GIF, WebP, and AVIF) and resized it to fill an area of 500x400
pixels with the smart (sm
) gravity. Our test function is deployed with 2048 MB of memory. We run the test function 5000 times switching between the formats.
The average billed duration of the function according to the function's monitoring is just 171ms. This means that you can make 1 million of such transformations per month comletely for free, thanks to the AWS Lambda free tier! Another million transformations will cost you only $5.89.
The only additional cost you may incur is the CloudFront traffic, which has its own free tier of 1 TB data transfer out and 10,000,000 (ten million) HTTP/HTTPS requests per month.
Conclusion
AWS Lambda turned out to be a very straightforward and extremely cost-effective way to deploy imgproxy. It allows you to not worry about infrastructure and scaling, and pay only for the compute time you consume. You can dramatically reduce the cost of image processing by switching from an image-processing SaaS to imgproxy on AWS Lambda. And if you need any of the Pro features, you can always switch to imgproxy Pro version that has a predictable, transparent and flat pricing starting from $499 per year.