As a Cloud Architect for DB Best Technology, with emphasis on the Azure platform, I’ve seen almost all of what the cloud has to offer. For the past 7 years, I’ve been helping customers develop and deploy their applications for Microsoft Azure. So when the project team at DB Best came to me for guidance on how to best deploy WordPress on Azure before going live, I was all in. I’d like to share my best practices and walk you through the step-by-step instructions on how to manage a WordPress deployment with Azure DevOps using Docker containers.
First a little background
We’ve been working with our Telecom client’s web site since 2012. Our first project involved revamping their web site to use Umbraco CMS 4 with Microsoft SQL Server 2008, .NET Framework 4.0, ASP.NET, XSLT, and jQuery all on their local host machine. This worked well over the years, but the combination of SQL Server 2008 end of support required a new way of hosting their web site. To that end, our development team suggested moving to a new cloud-based architecture on Azure with WordPress to replace their old Umbraco CMS site.
Our development team decided to take advantage of the WordPress on Windows Server 2016 Azure Marketplace offering using a single B-Series Azure VM. The advantages of this approach included:
- An easy to deploy tested version of WordPress on Windows Server 2016 that has everything preinstalled. This includes WordPress, MySQL, IIS, and phpMyAdmin
- Our customer’s admin team was already familiar with Windows Server and there are typically very few issues with MySQL on WordPress to deal with.
- They don’t need to deal with licensing costs for SQL Server.
- The B-Series burstable VM is a lower cost solution if you don’t use a lot of CPU.
My personal experience with the WordPress community suggests that more admins prefer running on Linux versus Windows. I can rationalize these preferences as follows. WordPress is built on top of PHP. PHP has a much longer history of running on Linux than with Windows Server. In addition, Linux VMs are generally less expensive than Windows-based VMs. For example, as of March 20, 2019, the Azure Pricing Calculator shows the following for a Standard_B8MS with pay-as-you-go licensing and the Standard support tier:
- Windows Server = $313.17 per month
- Ubuntu Linux distro = $289.81 per month.
In addition, I’m a big fan of PaaS (Platform-as-a-Server) offerings on Azure. Specifically, the Azure App Service with Web App for Containers support. The reason is simple:
- Development on Docker Containers technology, so that the development cycle will be quick and identical at all life cycle levels
- Use the benefits of Azure App Service for web hosting. I think this is an excellent and secure service that drastically reduces operation and infrastructure management. For example, the use of deployment slots for a smooth and transparent transition of the site from a development environment to a production environment
- Using the Azure DevOps (Git) service to host the code and create a pipeline (CI/CD)
- Azure App Service for containers, one of the benefits of this service is that it uploads the application to work on the Azure App Service local disk and does not use Azure Files
Our development team said “that’s nice. Can you please explain to us how we can upload the code into a Docker Container and how we can manage the development and operations environment in this new world?”
For the rest of the blog, I’d like to share with you my presentation on how to perform WordPress deployment with Azure DevOps using Docker Containers.
The proposed architecture for WordPress deployment with Azure DevOps using Docker containers
My working assumption was:
- First, we have to find a Docker Image in the Docker Hub for WordPress. We need a Docker Image that includes the Dockerfile
- Then we will upload the Docker-WordPress project and the WordPress development project into GitHub (Azure DevOps)
- Also, we need a developer station with Docker Containers and Git installed on it. Here we can perform a Git clone from the Azure DevOps for the ability for local development (not required, you can work directly with Azure App Service development)
- We will also use Azure Container Registry (ACR) for Private Registry
- We then link this ACR with Azure App Service which hosts the site
- Finally, we will use Azure DevOps as a Git to execute the entire pipeline
This is how the environment will look:
Building the Azure DevOps project
To find the appropriate Docker Image project, including the Dockerfile, I created WordPress on Azure App Services directly from Azure Marketplace. This approach allows you to know the exact path to the Dockerfile and the variables that we will need to use later in the application settings.
The truth is that I did not like the use of Alpine Linux Docker image so I took the PHP version directly from the Docker Hub. Please note that the Docker Hub gives a direct link to GitHub, where the Dockerfile project is located. The Dockerfile is the recipe from which the image of the docker container is built.
A click on the Dockerfile link brings you directly to Dockerfile.
Then you can go to the parent folder of the project. Here we can copy all its content into the Azure DevOps. Click on Clone and copy the link.
Azure DevOps
After copying the link, we can access Azure DevOps and set up the project. So, we click Create project on Azure DevOps. After the project is set up, we will import from the GitHub by repos > files > import > paste the cloned URL.
At this point, we have a clean WordPress on Azure project which is stored in private Git (Azure DevOps). We can now build a WordPress container via Dockerfile. This is a pristine WordPress site on Azure. We still need to “push” the development code into this clean container. There are several options for doing so. Some may want to put Git in the container. However, I prefer a simpler solution. Copy the code (directories) as a folder subfolder within the project (we set up for WordPress). Set in Dockerfile the following line COPY Myproject/var/www/html.
Taking care of the pipeline
In this configuration, I also take care of the pipeline. Each time a developer changes the code and executes a git commit, a docker build process will be performed. In each docker build process, the new code will be copied into the docker image by the Dockerfile.
Remember we are working on the environment that will be replicated between development, production, etc. So, we need to remove the access credentials outside of the code. This includes all passwords and variables (such as database name or password). Since the above is set in the wp-config.php folder on the first run, I edited the wp-config.php file and configure it for using variables, which will be used in the settings of the Azure App Service settings, Local Docker.
Now we can use the same code in different environments, where each environment will be linked to its own database (a separate database for development and a separate production database).
Congratulations, we’ve defined the code in the project. Now we can run a build process in Azure DevOps for the site.
The next step is to set up Azure Container Registry (ACR) and build a Docker image. Then we publish it in ACR and run a Docker image downloaded through the ACR.
On the developer station, I used a local docker. However, I will run everything through the Azure App Service for containers to simplify the process.
Azure Container Registry (ACR)
You can set up the Azure Container Registry (ACR) for testing purposes on the basic low SKU. It allows for creating up to two webhooks and a link from the app service. Check out the following link to learn more about ACR.
MySQL
We’ll need to provide a database for WordPress. This is how you can quickly and easily set up a MySQL database and configure it to meet your needs.
Find below the commands I used to run the Docker image from a local docker station.
1 2 3 4 5 6 7 8 9 10 11 12 13 | Install azure cli on linux az acr login --name omerregistry docker pull omerregistry.azurecr.io/wordpressapp docker run -d -e DATABASE_HOST = omery.mysql.database.azure.com -e DATABASE_NAME = wp -e DATABASE_PASSWORD = **** -e DATABASE_USERNAME = omery @ omery -name myimage -p 8080: 80 omerregistry.azurecr .io / wordpressapp docker exec -it myimage / bin / bash cat wp-config.php |
Build pipeline
The build pipeline will build the Docker image and publish it in ACR. This means that each time the developer performs a Git commit, the build pipeline builds an image publishes it into the ACR.
Now we return to the Azure DevOps portal. Here we go to the menu on the left of the pipelines > builds. For the build process, we will use two tasks.
The first task will build the Docker image:
- First, we select the command menu in the build option
- We will need to select the Azure subscription where the ACR is installed and the path to the Dockerfile
- To simplify the topic, I set the latest tag > $ (Build.Repository.Name): latest
The second task will take the Docker image and upload it to ACR. We need to select the command menu in the Push option.
Finally, we define the “continuous integration” in the trigger menu.
After saving, we manually run a build process that will set up with an image inside the ACR. Back to the build’s menu, we can click on the build we ran. Here we can see the process in real time and the errors if any. Click the Queue button to start the build process manually.
Deploying the app
On the next step, we create the Azure App Service. Then we pull the image container out of the ACR into the Docker on Azure (Azure App Service for containers). For convenience, I will deploy the app service directly from the ACR and then make any necessary changes.
Then we return to the ACR portal. In the repository menu, we reach to the tags and select the Deploy to web app option. So, we build an Azure App Service with a webhook link for the ACR.
After we successfully establish the Azure App Service, we copy the ACR password. It is defined as the DOCKER_REGISTRY_SERVER_PASSWORD variable in the application settings.
Release pipeline
It’s time to return to Azure DevOps and build the Release pipeline. In Release Pipeline we define the ACR as an artifact. This means that every time you execute a build process, Azure adds a new Docker image to ACR (a new WordPress image).
In the case of setting the deployment slots, we will need to create a full process of:
- upon the new image on the ACR then deploy to staging slot
- upon approval, swap from stage to prod (manual approval)
My pipeline will look like this:
We then need to add an artifact.
After setting the ACR as an artifact, we proceed to setting up the pipeline itself. The release pipeline will pull the WordPress Docker image from the ACR, deploy it in the Azure App Service and configure the variables and some site settings. In the case of using deployment slots, I will create another pipeline by choosing a swap slot template.
Remember to set the variables of the application settings:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | DATABASE_HOST DATABASE_NAME DATABASE_PASSWORD DATABASE_USERNAME DOCKER_ENABLE_CI (set to true) WEBSITE_TIME_ZONE (set to "[your]" Standard Time) DOCKER_REGISTRY_SERVER_URL DOCKER_REGISTRY_SERVER_USERNAME WEBSITES_ENABLE_APP_SERVICE_STORAGE (set to false) |
Now we’re all done. We recommended you to run the CI/CD process by manually running the build. This way, you can make sure that the pipeline runs properly.
Running WordPress on Azure
This process shows how in a few simple steps you can set up a complete WordPress on Azure infrastructure. From the development environment to the distribution of production versions.
Using Microsoft Azure components such as Azure App Service or Azure DevOps helps you set up a high-quality project in a short time with a maximum emphasis on the application’s lifecycle. Be sure to contact DB Best to start building your cloud infrastructure today!