Deploying WordPress on Azure Web App for Containers

I’ve provided a few tutorials on this blog showing how easy Docker makes it to get a WordPress blog up and running. These show off two different ways of running containers in Azure – first just by using a regular Virtual Machine, and second with Azure Container Instances:

Web App for Containers

But Azure offers several other ways to host your containers, and for WordPress, a great choice would be to use Web App for Containers and Azure Database for MySQL for the database.

“Web App for Containers” is simply a way of hosting your web application on App Service as a container (Linux or Windows). The advantage of doing this is that App Service offers many features ideally suited to web applications such as configuring custom domains and SSL certificates, slot swapping, CI/CD functionality, auto-scaling, IP address whitelisting, AD authentication and much more.

And the reason for using “Azure Database for MySQL” rather than also using a container for the database is that we might want to scale up the web server to multiple instances, but we’d want each of the containers to be talking to the same database.

So let’s see how we can use the Azure CLI to set up WordPress running on Web App for Containers, using Azure Database for MySQL as the back-end.

Create the App Service Plan

I’ll be showing PowerShell commands, but since I’m using the cross-platform Azure CLI, these commands can also be run with minimal modification in a Bash shell.

When we create the app service plan, we will need to specify the --is-linux flag as we plan to use a Linux container image.

# create a resource group to hold everything in this demo
$resourceGroup = "wordpressappservice"
$location = "westeurope"
az group create -l $location -n $resourceGroup

# create an app service plan to host our web app
$planName="wordpressappservice"
az appservice plan create -n $planName -g $resourceGroup `
                          -l $location --is-linux --sku S1

Create an Azure Database for MySQL

We then need to create a MySQL server with the az mysql server create command, and we will need to set the --ssl-enforcement flag to Disabled for this demo to work.

# we need a unique name for the servwer
$mysqlServerName = "mysql-xyz123"
$adminUser = "wpadmin"
$adminPassword = "J9!3EklqIl1-LS,am3f"

az mysql server create -g $resourceGroup -n $mysqlServerName `
            --admin-user $adminUser --admin-password "$adminPassword" `
            -l $location `
            --ssl-enforcement Disabled `
            --sku-name GP_Gen5_2 --version 5.7

n.b. if the az mysql server create command takes a long time to return, I’ve found I need to cancel it and try it again.

And we will also need to open up a firewall rule to allow our web app to talk to the MySQL server. The simplest approach is to use the special 0.0.0.0 address to allow all internal Azure traffic, but a better solution is to get the outbound IP addresses of our Web App and explicitly create a rule for each one.

# open the firewall (use 0.0.0.0 to allow all Azure traffic for now)
az mysql server firewall-rule create -g $resourceGroup `
    --server $mysqlServerName --name AllowAppService `
    --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0

Create a Web App from a Container

Now let’s create a new web app. We need to give it a unique name, and we’ll use the official WordPress image from Docker Hub

$appName="wordpress-1247"
az webapp create -n $appName -g $resourceGroup `
                 --plan $planName -i "wordpress"

Although this will start up our container, we’re not actually ready yet as we need some environment variables to be correctly configured. Annoyingly, the az webapp create command doesn’t allow us to do that at the time of creating the app (please add your support this GitHub issue which also highlights that you can’t specify a private ACR image with this command either).

Configure the Environment Variables

Configuring environment variables for our container is done by setting the web apps “Application Settings”, which will be surfaced as environment variables within the container. The WordPress container image is expecting three environment variables for the database host name, username and password

# get hold of the wordpress DB host name
$wordpressDbHost = (az mysql server show -g $resourceGroup -n $mysqlServerName `
                   --query "fullyQualifiedDomainName" -o tsv)

# configure web app settings (container environment variables)
az webapp config appsettings set `
    -n $appName -g $resourceGroup --settings `
    WORDPRESS_DB_HOST=$wordpressDbHost `
    WORDPRESS_DB_USER="$adminUser@$mysqlServerName" `
    WORDPRESS_DB_PASSWORD="$adminPassword"

Once we’ve set this, presumably the container gets restarted to make those environment variables available. In any case, I’ve found that once I’ve made these setting changes, after a couple of minutes, the WordPress site is up and running.

Test it out

We can find out the domain name of our WordPress site with the az webapp show command like this:

$site = az webapp show -n $appName -g $resourceGroup `
                       --query "defaultHostName" -o tsv
Start-Process https://$site

And you should see that now you have a fully working WordPress installation that you can set up and try out.

WordPress installation

The setup wizard only takes a minute, and you’ll be editing new posts in no time:

Editing a Post

Scale out

Because we’ve used Azure Database for MySQL for our database rather than a containerized instance of MySQL, our web apps are entirely stateless. That means we can safely scale out to multiple instances of our web server, which is easily achieved with the az appservice plan update command. Notice that you scale out the App Service plan as a whole, rather than at the web app level.

az appservice plan update -n $planName -g $resourceGroup --number-of-workers 3

Clean up

Of course, when you’re done with this instance of WordPress, you’ll want to clean up the resources you created. Since we put everything (the App Service Plan, the Web App and the MySQL Server) in the same resource group, we can clean it all up with a single command like this:

az group delete --name $resourceGroup --yes --no-wait

Summary

Azure Web App for Containers is an ideal hosting platform for containerized web applications like WordPress. You benefit from many added value web hosting features that App Service has to offer, as well as the cost benefits of being able to host multiple containerized web apps on the same App Service plan.

Archives