[Serverless architecture #3] Deploying Gatsby / Strapi with Live preview capability using a serverless architecture
This article is the third one of a series of four articles dedicated to the serverless and containerization concepts and how it can be applied in the context of a typical web application involving:
- A Content Management System (CMS) using Strapi.
- A public facing front end application using Gatsby.
- A web analytics tool to measure the behavior of users on our website using Umami.
The serverless/containerization concept that will be concretely implemented throughout these articles will use the above frameworks/tools, though the same principles can be most likely extended to others, let alone the time it takes to adapt them.
Following my previous post on deploying Strapi v4 with Azure Container Instances (ACI), I decided to add one more component to the solution in order to get a fully working solution in the context of a static web app with a production environment and a staging environment.
The concept remains the same as before, and we want a Pay-Per-Use subscription in order to keep the cost as low as possible and avoid any provisioned server.
From there, we will allow the user to start a temporary instance of Strapi on demand along with a temporary instance of Gatsby and thus benefit from the Live preview capability (via webhook).
NB: As said above, this is an extension of my previous post, but in order to make sense of everything, I will have to repeat a few things over.
Below is an overview of the architecture of the system that we will partly deploy via Terraform:
The different entities:
- An ACR to handle our private Docker container images
- A storage account using a file share for our database (SQLite) and a storage container for our media.
- An ACI containing our running instance of Strapi served by a reversed proxy (Caddy).
- An ACI containing a running instance of Gatsby in “develop” mode, also served by a reversed proxy (Caddy).
- A powershell Azure Function that triggers the start/stop of our ACIs
In order to make it possible to use the Live Preview feature, we will need a couple of things here.
First, a Gatsby GraphQL connector to Strapi. For that I’m using gatsby-source-graphql. This plugin is very flexible, and allows to connect not only to Strapi, but to any GraphQL compatible endpoint.
Second, in Strapi, you’ll need to set up a webhook that triggers on every change in content or media.
No need to mention that:
- Our Strapi webhook sends a POST request to “https://<your_gatsby_aci_url>/__refresh”
- Our gatsby-source-graphql is set up with the url to our Strapi GraphQL endpoint, i.e. “https://<your_strapi_aci_url>/graphql”.
NB: At the time of this post, setting up webhooks programmatically is not possible (yet), so this is something that will need to be done manually once Strapi is deployed.
In order to make it easy for the user to know when Strapi / Gatsby are ready to be used, I created a small dashboard that will query the status of the container instances deployment, and followed by a 200 response from Strapi / Gatsby. For each application ready, a button will be displayed that will open a new tab to the application selected.
See the screenshots below:
Trying it out
If you want to try it out, the code is available here and the README contains the necessary steps and instructions in order to deploy the solution.
Most of the work is done by the Terraform scripts including the set up for most of the environment variables for the different resources. However a few manual steps are needed and require running a few edits or command lines:
- Edit variables for Strapi configuration (tokens, keys, secret..) according to your installation
- Build Strapi and Gatsby docker images along with their deployments to the container registry
- Convert SQLite database to WAL mode
- Deploy the Azure Function code to the Function App
I have only tested this solution in the context of a Gatsby project with a few views so far. In the future, I will try to update this post if the results differ with a bigger project.
Strapi ACI start: The ACI takes about ~2–3 minutes until it’s ready after calling the Azure function.
Gatsby ACI start: Gatsby has a dependency on the Strapi instance, which means that it cannot be ready before Strapi is. The ACI takes about ~5 minutes to start when calling the Azure function. 5 minutes can be long, but hopefully this won’t feel to heavy for the user, who can focus on making a few changes in the CMS first before the Instant Preview is available.
Strapi ACI speed: Strapi is running on an ACI with 0.5 CPU cores and 0.5 GiB and performs as fast as on my local computer, which is very satisfying.
Gatsby ACI speed: When it comes to Gatsby I felt like I had to increase those a little bit, and thus allocated 1CPU and 1GiB, as I sometime had memory shortage with less memory. Also, you should keep in mind that the bigger the project, the longer it will take time to start. The best is to compare performances with different CPU cores.
Cost: Same as before, since the ACI is stopped most of the time, the cost of running this solution will be considerably low (i.e. no more than a few dollars per month for an average daily use).
The deployment of a static web app representing our production environment is not covered in this post, but this should be considered in order to make this solution viable for production scenarios. Also, creating CI/CD for keeping your docker images for Strapi / Gatsby up to date is a must obviously.
Once the user is done editing changes in the CMS, a webhook is used to trigger the deployment of the latest changes to the production environment or so. Simple!
I hope you enjoyed this post, and don’t hesitate to let me know what you think in the comments.