Skip to content

Day 2 Solution: Running WordPress Project Nami on Azure Kubernetes k8s.

Here’s my response to the challenge. To make things really complicated, lets do an overkill and utilize docker containers instead of a VM.
If you are using an VM previously, I would suggest you to explore creating a clone on Web App. Vice-versa for those who are started on Web App, create a clone on VM.

Docker has its advantage in terms of service recovery and service healing. By itself it is a tedious task to setup such feature, hence the common orchestrators would be Docker Swarm, DC/OS and Kubernetes (also known as K8s). Here is the TLDR of what I’m going to achieve.

  • Install docker
  • Prepare Ubuntu + Nginx + PHP container
  • Create Azure Container Registry, and commit previously created container.
  • Create a code repository
  • Run a webjob on existing Azure Web App which does git push of my wordpress source code daily.
  • Trigger (daily) a “container build” base on the prepared container in 2nd step of this bullet list, and add the daily code base into nginx starting directory in /var/www/html
  • Setup a k8s cluster with dockerfile to start 2 services, nginx and phpfm


Installing Docker

        1. Install Docker CE Edition, for Windows. You may need to register and sign in before you can download the package. I’m using Windows on my PC, hence I will need docker CE to create a docker image based on Ubuntu. For Windows Users, you might need to enable hyper-v feature on your machine.
          If you are using linux or MacOS, step 1 and step 2 will be pretty easy for you.

 website to download docker ce desktop for windows
        2. Once you have finished installation, there will be a whale tray icon on your taskbar.

          Right click on the docker icon. You will be able to see a context menu. If you are intending to host your CMS on Windows based container, click switch to Windows. I’m going to use Linux based, and will be leave this as default. No action needed if you are following this guide.

          Preparing Ubuntu, Nginx and PHP Docker Container Image

        3. Fire up your command prompt and download the base image of your intended host operating system. I’m going to use Ubuntu and will be doing a "docker pull ubuntu". If you are going to use Windows, do a “docker pull microsoft/windowsservercore”.What is “layer”? Gerald Goh once put it in an interesting analogy, of thinking it like kuah lapis (an asian dessert), where it is made layer by layer. Every-time you commit a change, you will be adding an additional layer to the dessert. Unlike dessert, you can always undo the top layers, make sure your bottom layers are foundation done well, and your top layers are those which are always changing such as your code base.

          prompt after doing docker pull ubuntu command
        4. Let’s start with our base layer of the dessert, which would be Ubuntu + Nginx (or Apache if you would like) with all the PHP dependencies necessary.
          I’ll start by running "docker run -d -it -p 8080:80 ubuntu /bin/bash". The -d flag specifies detach, and the -p flag specifies port mapping from your local machine to your docker container. -it mode allows you to run in interactive mode, and brings you directly into the bash shell.*hint* You can follow this digital ocean guide if you would like.
          Just ensure you check your docker image of Ubuntu’s operating system version via the command “cat /etc/*release”.

          prompt after doing docker run -it ubuntu

          Here are the list of commands (without explanation) below. If you are already root, you do not need to pre-pend “sudo” in front of your commands
          docker run -it (your container id, without the round bracket)
          #If you need to find your container ID, type "docker ps -a"
          apt-get update
          DEBIAN_FRONTEND="noninteractive" apt-get install -y vim curl wget nano dialog
          #you can docker commit <container> <container>:<date>in another cli if you want)
          apt-get upgrade
          apt-get install nginx
          apt-get install php-fpm
          update-rc.d nginx defaults
          update-rc.d php7.2-fpm defaults

          you can follow most of the guide here
          *(Should I create the above from devops processes such as my docker compose yaml file instead?) Well it depends. There are some things which doesn’t change, example apt update, installing nginx. Just remember about your dessert.

      Creating Azure Container Registry and Commiting your first Container Image

        1. Next we would need to setup an Azure Container Registry (ACR). Think of it as a GitHub, but for docker containers. Alternative to ACR, you may choose to use the free container registry from Fire up your another command line shell and do the following. This is important as you do not want to use the same shell (which is still running) in step 4. You might need to install the Azure CLI before proceeding.REM refers to comment in windows command line shell

          REM "login to Azure"
          az login
          REM "set default subscription"
          az account set --subscription "your subscription name"
          REM "Create a service principle to manage your Azure Subscription" #credentialsSPRBAC
          az ad sp create-for-rbac
          REM "Create an ACR for your subscription"
          az acr create --resource-group yourRGName --name YourRegistry932 --sku Basic
          REM "Enable admin login with username and password"
          az acr update -n 30DOAContainerRegistry932 --admin-enabled true
          REM "Login to ACR with your docker command line client"
          docker login -u username -p password
          REM "Continue from Step 4, get the running container ID"
          docker ps -a (this will help you get 903d6fec4cba below)
          REM "Commit your container (with Nginx and PHP installed) into ACR"
          docker commit 903d6fec4cba
          docker push

          If you remember the layering example, I’ve done multiple commits before my final commit of ubuntu:php-serviceonboot

      Creating a VSTS / VSOnline code repository

        1. Next head over to visual studio online (previously known as visual studio team services or vsts) ,create your free account and add a new project. I’ve added my project name as “Project Nami WordPress on Azure”.
        2. Take this opportunity to setup an alternative credential which is needed for later part of this guide. Click on your name on the top right hand side of the portal, in my case in CT > Security > Alternative Authentication Credentials. If you cannot find the page below, goto Replace abcxyz with your own vsonline’s name. Let’s call this credentialAAT for easy searching later.
        3. You would also need to link up your VSTS / VSOnline to your Azure Subscription. This will allow pulling of containers from your ACR. On the Dashboard of your Project, click on the settings “Gear” icon.
        4. Next click on “New Service Connection”, select “Azure Resource Manager” from the drop down list, and you will see the prompt below. Click on “use the full version of the service connection dialog”, if you cannot find your subscription from the drop down list. As I’m using a different subscription, I will be clicking on the link as illustrated below.
        5. For Connection Name, you can give it anyname which you want.
          For Environment, leave it as AzureCloud, unless you are using Cloud in special regions.
          For Subscription ID, Name and Tenant ID, refer to the link inline.
          For Service Principal Client ID and Service Principal Key, you may reuse the service principal from Day 1’s guide when creating a Let’s Encrypt extension, or you may reuse the service principal from above #credentialsSPRBAC. Hit verify connection and OK to add the connection.

      Setting up Git Webjob to commit code from Azure Web App to VSTS / VSOnline daily

        1. Azure Web App comes with an environment called Kudu, providing tools and some environment for common debugging and task. I’ll be using the CMD command line interface to work on Git services. I’ll git init the root directory of my wordpress, where all my php source code resides.
        2. Specify your username by doing git config --global user.mail and git config --global cstan
          Your username might be different from mine, which is “cstan” in the above example
        3. Next add all the files and commit your files
          Git add .
          Git commit -m "Initial Commit"
          git remote set-url origin https://cstan:*******
          git remote set-url origin https://cstan:*******
          git push -u origin master --all
          git push -u origin master --

        4. Note that your password ********* has to be URL encoded. Your username might be different from mine, which is “cstan” in my example.
        5. Once the code has been pushed, you should be able to see a list of code updated on your VSTS or VSOnline portal
        6. Now that the push is tested to be working, we will create a batch file which commits the code into VSTS / VSOnline on a daily basis. If you are using a VM, you will be creating a powershell script or shell script which will run the similar git commands below. Go to your web app -> WebJobs> Add.
          Name: gitpushwebjob
          File upload:
          Type: Trigger
          Triggers: Scheduled
          Cron Expression: 0 30 9 * * *My cron expression will run this script every day at 930am.
          For troubleshoot, occasionally check your logs for errors. For my case, I realised I needed to do a Git pull before the entire command.

Trigger a container build.

      1. Now create a file named “DockerFile” in your code repository. The contents of the dockerfile are located over at github. For convenience sake, I’ll be pasting them below.

        #base on
        #commands already executed in the image above
        #apt-get update
        #DEBIAN_FRONTEND="noninteractive" apt-get install -y vim curl wget nano dialog
        #apt-get upgrade
        #apt-get install nginx
        #apt-get install php-fpm
        #update-rc.d nginx defaults
        #update-rc.d php7.2-fpm defaults
        CMD ["/sbin/my_init"] WORKDIR /var/www/html
        COPY / /var/www/html
        RUN ls -la /*
        EXPOSE 80
        CMD service php7.2-fpm start
        CMD service nginx start
        RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
      2. Create a new build process and with 3 task. They are below, and should have similar parameters
        1. Copy Files
        2. Build an Image. Important note, you need to “Link” Azure Container Registry before you can successfully pull the prepared image for building.
        3. Push an Image
        4. If you have successfully Build and Push the Image, you should see something similar on your Azure Portal

Creating K8s Cluster on Azure

If you would like, you may follow the guide here on creating k8s cluster on Azure

      1. az aks create --resource-group projectnamirg --name=myK8sCluster --node-count=2 --node-vm-size=Standard_B2s --kubernetes-version 1.11.1 --generate-ssh-keys --service-principal b44xxxx1-xxxx-xxxx-xxxx-cba7xxxx67b52 --client-secret Jxxxvn23xxxx/uxGGxxxxU23q/xxxxxxxx5R/1Txxxx=

      2. az aks install-cli will install the cli for kubernetes
      3. If you are using windows, you might need to do set PATH=%PATH%;C:\program files (x86)\ to allow global path variable
      4. connect kubectl to your cluster by az aks get-credentials --resource-group=projectnamirg --name=myK8sCluster
      5. create acr login via kubectl create secret docker-registry --docker-username=USERNAME --docker-password=PASSWORD --docker-email=ANY_VALID_EMAIL. Make sure you remember the variable name mysupersecretas you will need to use it later
      6. kubectl get nodes will help you check your nodes
      7. az aks browse --resource-group projectnamirg --name myK8sCluster connect to your cluster via Web UI. By default, you need to setup this tunnel to get into the management UI. If this does not work try Kubectl proxy. If you are getting some errors on the management portal, check out
      8. Want to start testing out K8S with your image? Try kubectl exec -it /bin/bash

Installing msodbc driver on Linux based docker

This gave me days of fun, as the container version Ubuntu 18, PHP 7.2 are of latest version.

Some reference are done inline, and highlight the changes in bold

# Install dependencies
apt-get install libc6 libstdc++6 libkrb5-3 libcurl4 openssl debconf unixodbc unixodbc-dev
# Manually install msodbcsql 17 and mssql-tools 17
# ODBC .deb found here ->
# Tools .deb found here ->
# ... Are they compatible?
mkdir /debs
cd /debs


dpkg -i msodbcsql17_17.2.0.1-1_amd64.deb

dpkg -i mssql-tools_17.2.0.1-1_amd64.deb

# Link tools to sqlcmd
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc
# PHP 7.2 sqlsrv pdo extension
apt-get install php-pear php7.2-dev
pecl install sqlsrv
pecl install pdo_sqlsrv
# Config php.ini for CLI & NGINX
echo "" >> $phpini
echo "# Extensions for Microsoft SQL Server Driver" >> $phpini
echo "" >> $phpini
#echo "" >> $phpini

#I've removed the line above as there are some dependencies which need to
load before
echo "" >> $phpini
echo "" >> $phpini
echo "# Extensions for Microsoft SQL Server Driver" >> $phpini
echo "" >> $phpini
#echo "" >> $phpini

#I've removed the line above as there are some dependencies which need to
load before
echo "" >> $phpini
# Restart NGINX and PHP-FPM
service php7.2-fpm restart
service nginx restart

#some dependencies of SQLCMD

apt-get install -y locales && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen

#if you encounter /opt/microsoft/msodbcsql17/lib64/ not found error, try to look for missing files by typing ldd /opt/microsoft/msodbcsql17/lib64/
PHP Startup: Unable to load dynamic library ‘’ (tried: /usr/lib/php/20170718/ (/usr/lib/php/20170718/ undefined symbol: php_pdo_register_driver)

#Lets make sure that you have your SSL installed and updated:
apt-get update
apt-get install libssl1.0.0 libssl-dev
#Now lets fix the naming of the file by creating a link:
cd /lib/x86_64-linux-gnu
ln -s
ln -s
#try out to connection
sqlcmd -S -U chunsiongtan
#make sure that "" found in /etc/php/7.2/cli/conf.d/30-pdo_sqlsrv.ini instead of php.ini


echo "" >> /etc/php/7.2/cli/conf.d/30-pdo_sqlsrv.ini

#lastly copy the same config file to fpm directory
cp /etc/php/7.2/cli/conf.d/30-pdo_sqlsrv.ini /etc/php/7.2/fpm/conf.d

if you need to check for php error, try php --info | grep error


docker commit 903d6fec4cba
docker push

configuring php-fpm with nginx


deploy image using kubernetes dashboard




pointing traffic manager to new service IP

updating dns name before using traffic manager

az network public-ip list

az network public-ip update –ids /subscriptions/xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx/resourceGroups/MC_projectnamirg_myK8sCluster_southeastasia/providers/Microsoft.Network/publicIPAddresses/kubernetes-ad0xxxxxxxfa411exxxx56aa5bd8xxxx –dns-name “myk8sclusterip”


Ingress and TLS

Published inacrazure web appcontainersdevopsk8skuduvsts

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *