WordPress is probably the most popular CMS around. Though when I look at my home country, then I see a lot of Drupal deployments too. This might be due to the fact that the creation is of Belgian origin? Though for the region I live in, Drupal is amongst the most popular CMS systems.
That being said, Drupal is a very resource hungry system. When you enable the WebProfiler (part of the Devel module), then you can see that typical page will execute between 90 and 200 database queries. This puts a lot of stress on the underlying database system, but also on the local file system.
Due to this we see a lot of articles on how to improve the performance of Drupal. Most commonly seen is the implementation of ;
- Varnish on the front end side, as a web application accelerator / caching HTTP reverse proxy
- Redis or Memcache, as a way to cache data (in memory instead of hammering the database)
For today’s post, we’ll briefly discuss the various options and afterwards delve into a more advanced scenario where we leverage the Azure Linux App Service’s multi container capability.
What options do I have for running Drupal on Azure?
In essence there are various ways to run Drupal on Azure ;
- On your own virtual machine(s) [IaaS model]
- As a drop-in code deployment onto ;
- Azure App Service (both Linux & Windows)
- As a container deployment onto ;
- AKS (Azure Kubernetes Service)
- Azure Linux App Service
What options should I take?
- A (set of) virtual machine(s) is basically hosting & managing it yourself. Here you have full control over the deployment. Though with great power comes great responsibility… Where the full management aspect also comes back to you.
- AKS is for me suites for the larger deployments, where organizations really need to scale due to the popularity of the website(s) or due to the multi tenancy story.
- The App Service provides a full PaaS experience, where it even adds additional capabilities out-of-the-box (like Backup, Authentication, etc). But there are two flavours? Windows vs Linux.
- Windows : In my humble opinion… Stay clear of this one for Drupal. It will not give you the most optimal performance. There are a variety of reasons for this. Though let’s keep it at that for the moment, where it is great for other workloads! Drupal is just not the best fit here.
- Linux : Here we have a better fit. Though there are two options presented… Via a code deployment or by leveraging a container setup. Again, in my humble opinion, leverage the container one if you want to go for a more advanced approach where you want to do performance optimizations (like leveraging Varnish, Redis, Memcache, etc). If you have a “modest” deployment, then go for the code deployment.
Are there any gotchas with Drupal on Azure?
The biggest hurdle you’ll probably will take is that it is highly advised to enforce SSL on the Azure MySQL Service. Where this seems like the most sensible thing to do… The experience in doing so is far from great. This is due to the combination of how Drupal implemented it and how PHP/MySQL expect things to happen. As a basic reference, I would like to point to the following blog post from the Azure App Service team!
So what will we be deploying today?
We’ll be leveraging a multi container deployment where we’ll deploy two containers. The first one will be the varnish container, which will act as the caching layer. The second one will be a custom Drupal container which I tweaked to already to have the needed configuration for the MySQL SSL part. In addition, the first container (varnish) will talk to the second container (Drupal) via the docker internal network. The only port exposed will be the one of the varnish container!
Let’s get this party started! In starting this deep dive, I’ve already prepared a basic Linux App Service plan.
In addition, I’ve also already created an Azure MySQL service, which I’ll be using to power this drupal.
Next up, I’ll be using a docker compose file to deploy two containers.
And wait for it…
If you want a good tutorial on the commands, do check the following documentation page for a clear outline.
Once deployed, we’ll see an additional app service appearing in our resource group. Let’s look inside… and browse to “Container settings” ;
One of the things you’ll notice here is that there is a message stating that logging isn’t enabled. Enable docker logging to the file system, and you’ll see the logs from the containers in this message box too!
Set to “File System”, select the retention period… Save. Done! 🙂
Now let’s go back…
Now if we go to the webapp via our browser, then we’ll see that there is a 503 error. This is basically because the varnish container has spun up, but it cannot reach the Drupal container (yet).
Let’s configure this by going to the “Application settings”, and configure them accordingly…
This to basically match the settings that were in the Dockerfile
Which will be used in the default.settings.php file for the MySQL connection ;
During the startup, entrypoint.sh will be used to configure everything appropriate. Just like generating the salt and setting up the certificate needed for the MySQL connection.
Anyhow, by now our Drupal container should have already started properly. Where we’ll see “Launching Apache2” in the logs appearing ;
Where our web app will now show the Drupal installer. Do note that as the MySQL information has already been set, it’ll skip that par tin the installer.
Now let’s give it some time…
And there it is! Our newly deployed Drupal site. 😉
Where the logs will show that we just browsed the website…
As mentioned, the App Service comes with additional goodies… One being the authentication part, where you could deploy a website that isn’t aware of any authentication, and still protect it via various identity providers.
And you can get a backup out of the box for both the app itself AND its database.
That’s where some additional value add is over the typical IaaS deployment.
Help my container hasn’t been exposed!
If your container hasn’t been exposed, check the logs for the docker run command…
The -p indicates the port mapping as used. The number before the ‘:’ is the number used on the host system, which will then be mapped by the App Service to port 80/443. If that one is ‘0’, then it will NOT be exposed. There is a logic to this… You can explicitly set the container port that needs to be selected (
WEBSITES_PORT) or the container that needs to be selected (
WEBSITES_WEB_CONTAINER_NAME). Or if you’re really lazy, just ensure that the container that needs to be exposed is set as the first one in the docker compose file.
The Drupal image I created for this small proof-of-concept is far from production worthy. Use it for inspiration on how to get the MySQL connection going. The biggest changes it still needs is adding an SSH daemon to it for the Kudu integration. For this, do check the docs on how to create a customer image.
I do hope it showed you the potential value add of leveraging the Linux App Service as a managed/platform service. Where you could still have the control over customized / advanced deployments like adding Varnish/Redis/Memcache/…/whatever. 😉