Serving next generation images using Google Cloud CDN, Cloud Run and image proxy

Siraj Mohammad
8 min readFeb 4, 2023

In this blog post, we will setup required infrastructure and services on Google Cloud platform to serve next generation images using Cloud CDN and imgproxy.

imgproxy enables two essential image processing use cases that aim to improve the overall performance of your website or application.
1. Serving images in next-gen formats, such as WEBP and AVIF, to reduce latency and footprint (between 20% to 30%) without converting existing images.
2. Enabling dynamic, on-the-fly transformations, including image resizing and adding watermarks.

To achieve this, let’s walk you through the steps of setting up the necessary infrastructure and services on Google Cloud Platform. By the end of this post, you’ll have a better understanding of how to setup, Google Cloud CDN, Cloud Run, Cloud Storage, Artifact Registry and deploy imgproxy to serve images for your websites or applications

Note: imgproxy takes advantage of probably the most efficient open source image processing library out there — libvips. It’s scary fast and comes with a very low memory footprint.

Architecture diagram of the services deployed on Google Cloud

We will follow the steps to setup services on Google Cloud:

  1. Create Artifact Registry and push imgproxy container image.
  2. Create Cloud Run Service to host and run imgproxy container.
  3. Create Google Cloud Storage bucket to store and serve images files.
  4. Grant Cloud Run service account storage object viewer role on storage bucket.
  5. Setup Cloud CDN to deliver images with external HTTP(S) Load Balancing and Serverless backend Cloud Run.
  6. Update DNS settings of your domain to point to your Load Balancer IP address.
  7. Validate setup and browse next-gen images!
  8. Additional helpful resources

1. Create Artifact Registry and push imgproxy container image to artifact registry

Navigate to Google Cloud Console , search Artifact Registry, and create Docker repository to host container images.

Artifact Registry is a single place for your organization to manage container images and language packages (such as Maven and npm, etc.)

Create a docker repository

Follow the setup instructions, and run gcloud auth configure-docker command on Cloud Shell or your local gcloud console to configure gcloud as the credential helper for the Artifact Registry domain associated with this repository’s location.


Pull the latest imgproxy container image from Docker Hub to local docker environment or in Google Cloud Shell environment

Cloud Shell is an interactive shell environment for Google Cloud that lets you learn and experiment with Google Cloud and manage your projects and resources from your web browser.

$ docker pull darthsim/imgproxy:latest\

Tag the local imgproxy container image with the repository name. Replace <GCP Project ID> with your GCP Project ID and <Repository Name> with repository we created in previous step.

$ docker tag darthsim/imgproxy<GCP Project ID>/<Repository Name>>/imgproxy


Next Push the tagged image to Artifact Registry

$ docker push<GCP Project ID>/<Repository Name>/imgproxy


Now verify container image imgproxy has been pushed to docker repository.

2. Create Cloud Run Service to host and run imgproxy container

Cloud Run is a managed compute platform that lets you run containers directly on top of Google’s scalable infrastructure.

Navigate to Google Cloud Console select Cloud Run and select imgproxy container image from Artifact Registry.

Now create following environment variables on Cloud Run creation page, leave IMGPROXY_ALLOWED_SOURCES and IMGPROXY_GCS_KEY blank.

– IMGPROXY_TTL=31536000

3. Create Google Cloud Storage bucket to store and serve images

Google Cloud Storage allows world-wide storage and retrieval of any amount of data at any time. You can use Cloud Storage for a range of scenarios including serving website content, storing data for archival and disaster recovery, or distributing large data objects to users via direct download.

Navigate to Google Cloud Console and Select Cloud Storage Bucket and Create a new storage bucket.

4. Grant Cloud Run service account storage object viewer role on storage bucket

A GCP service account is a special kind of account used by an application or compute workload, such as a Compute Engine virtual machine (VM) instance, rather than a person. A service account is identified by its email address, which is unique to the account.

Select Cloud Run service created in previous step, and go to revisions tab, then click on security in right pane to get service account name.

Now navigate to Cloud Storage bucket. Under the permissions tab, add cloud run service account and assign Storage Object Viewer role.

5. Setting up Cloud CDN to deliver images with external HTTP(S) Load Balancing and Serverless backend Cloud Run

Google Cloud CDN (Content Delivery Network) uses Google’s global edge network to serve content closer to users, which accelerates your websites and applications.

Under VPC network section, select IP addresses and Reserve an external static IP address.

Next, under the Network services on Cloud Console, select Load balancing and create a HTTP(S) load balancer.

Select HTTP(S) load balancing

Select the following settings:

Backend Configuration: Under the backend configuration select “create a backend service”

Under New backend, click create “Serverless Network Endpoint Group”

Specify name and under Serverless network endpoint group type select Cloud Run

Select the Cloud Run service created in previous step

Now select enable CDN and click create new backend service

Frontend Configuration: Under Frontend configuration select protocol HTTPS, under the IP address select external IP created in previous steps

Under Certificates select Create Certificate and specify name. In our case I am creating a Google managed SSL certificate. I already have a domain name that I will use for my Google-managed SSL certificate.

Google-managed SSL certificates are Domain Validation (DV) certificates that Google Cloud obtains and manages for your domains. They support multiple hostnames in each certificate, and Google renews the certificates automatically.

Note: Provisioning a Google-managed certificate might take up to 60 minutes from the moment your DNS and load balancer configuration changes have propagated across the internet. You can run following command to check the certificate status:

gcloud compute ssl-certificates describe CERTIFICATE_NAME \
--global \

At this point, the certificate status and the domain status are PROVISIONING. After you complete the steps on this page, the statuses change to ACTIVE.

Review and finish creation of Google Cloud Load balancer.

6. Update DNS settings of your domain to point to your Load Balancer IP address

Under DNS setting on your domain, change the A Record to point to the external IP of your Load Balancer created in previous step.

7. Validate setup and browse next-gen images!

To test this setup, browse url www.<domain>.com, we should see the page displaying “Hey I’m imgproxy!” This means our setup is working and imgproxy is deployed on Cloud Run!

Next, we will use a imgproxy URL generator tool to construct the URL of images that will be served by imgproxy.
Go to URL (open source tool) in your browser, and input your remote image URL and imgproxy host URL and click Generate URL button.

Copy and paste generated URL in browser and Voila! Your imgproxy is now serving your image!

Now let’s change the image format and test it. Our original image size is 273.4 KB

Original image in Google Cloud Storage

Now let’s use our imageproxy URL generator and change image extension to WEBP by changing extension to WEBP

Use generated URL to browse the image in WEBP format, and inspect element to check the image size.

Without imgproxy :

With imgproxy and Cloud CDN, We can see image is almost 30% smaller in size and loads 50% faster!

Similarly we can try to generate different image transforms of different sizes etc, for complete list of transforms with imgproxy check this.

8. Additional helpful resources

This wraps up the blog post. I hope that this was useful to you. If you have any questions, or additional thoughts, please drop in the comments.

Thank you for taking the time to read through.