WordPress has become one of the most prominent website builders on the internet. It is free and is used by a lot of organizations and consumers. Millions of extensions and themes are built for WordPress. It's easy to install, easy to use, and easy to extend if necessary. But let's face it, it's also a hacker/spam/malware magnet because of its popularity and the many (unsafe) extensions.
But to be honest I was looking for something new. I am a Nerd and I want something to fiddle with.
After some searching, I stumbled upon Ghost. Ghost: The Creator Economy Platform. It looks beautiful, but I was a little bit turned down by the fact that I needed to run it on NodeJs and currently I also don't have a spare server lying around. Also, my knowledge of NodeJs is somewhat limited. Fortunately, I saw that they also offer a Docker image. ghost - Official Image | Docker Hub. Now Docker is a technology that I do know. :-)
I love Microsoft Azure so I immediately looked at what kind of cool options I have to host the Ghost Docker image. The most obvious option is an Azure WebApp running a Docker container. But that's boring because it's familiar. So I thought let's try Azure Container Apps. Azure Container Apps | Microsoft Azure
With Azure Container Apps we basically have AKS (Azure Kubernetes Service) without all the complex infrastructure setup.
But in order to scale up my new Blog, I must use a central database so that all my pods can access the same data at the same time. For example when you need to scale out.
I choose to use a MySql flexible server on Azure. (But you can also use a database container or even a local db file on Azure Storage)
az mysql flexible-server create --location westeurope --resource-group testGroup --name ghostserver --admin-user <<USERNAME>> --admin-password <<PASSWORD>> --sku-name Standard_B1ms
Next is to set up shared storage for the content/media files, etc. Otherwise, the content can only be loaded on a local pod. So if you have multiple instances of your website, it's essential that all pods can access the same images and other files.
So first we create a storage account.
Next, we use that storage account to create a file share
In our next step, we want to link our file-share storage to the Azure Container App environment.
The Azure Container Apps environment acts as a secure boundary around a group of container apps.
But in order to link that storage account to the environment, we first need to create that environment ;-) like so...
Now we need to configure the newly created Azure Storage as a storage mount in your Azure Container App. For that, you can use the following code.
Now we have created a storage mount, to our Azure File Share, inside our Azure Container App environment. With that in place, we can configure a volume for our containers in our YAML templates.
Now let's create a YAML template in which we specify all the details of our Azure Container App. Note: You can also see the details for the Azure File Share that we created.
type: Microsoft.App/containerApps resourceGroup: <<RESOURCE GROUP>> template: containers: - env: - name: database__client value: mysql - name: database__connection__host value: <<DATABASE HOST>> - name: database__connection__user value: <<DB USERNAME>> - name: database__connection__password value: <<PASSWORD>> - name: database__connection__database value: <<DATABASE NAME>> image: docker.io/ghost:latest name: <<YOUR APP NAME>> resources: cpu: 0.25 ephemeralStorage: 3Gi memory: 0.5Gi volumeMounts: - mountPath: /var/lib/ghost/content volumeName: azure-files-volume initContainers: null revisionSuffix: '' scale: maxReplicas: 2 minReplicas: 1 rules: null volumes: - name: azure-files-volume storageName: <<STORAGE NAME>> storageType: AzureFile
Replace all the <<PARAMETER>> parameters with your own details. We use that file to create our new Azure Container App. Let's call that file containerapp.yaml
Now we use that file to create the container app.
az containerapp create \ --name <<YOUR APP NAME>> \ --environment <<YOUR ENVIRONMENT NAME>> \ --resource-group <<RESOURCE GROUP>> \ --yaml containerapp.yaml
Finally, we have to wait for Azure for finishing up our Azure Container App.
In order to see what is going on inside your Azure Container App, you can easily navigate (through the Azure Portal) to your Azure Container App logs.
In order to connect to the MySql server, we must configure SSL in our environment variable.
- name: database__connection__ssl__ca value: -----BEGIN CERTIFICATE-----\n...bla bla bla...\n-----END CERTIFICATE-----\n
You can find the certificate in your Azure Database MySql Networking settings.
Use storage mounts in Azure Container Apps | Microsoft Learn
Ghost: The #1 open source headless Node.js CMS
GitHub - docker-library/ghost: Docker Official Image packaging for Ghost
Quickstart: Deploy your code to Azure Container Apps | Microsoft Learn