Azure Web App + MySQL in a Docker Container

Continuing from my previous post on how to get a website and a MySQL db running on Azure, this post describes the Web App + MySQL in a Docker Container option. 

I've created a sample Azure Resource Manager template that will create the following in an Azure resource group:

  • A virtual machine running Ubuntu with Docker installed and a MySQL docker container running in it
  • Networking and supporting services for the VM (storage account, public IP address, virtual network, network interface, network security group)
  • A Web App and an App Service Plan for the Web App

 

The files are in the env folder in this GitHub repo:

https://github.com/nzthiago/WebAppMySQLDocker

 

Interesting bits from the ARM Template

There are some parts of the template that are worth calling out. For example, I added an extra security rule to the network security group to allow connections to the MySQL 3306 port:

{
  "name": "mysql",
  "properties": {
    "description": "Allow MySQL",
    "protocol": "Tcp",
    "sourcePortRange": "*",
    "destinationPortRange": "3306",
    "sourceAddressPrefix": "Internet",
    "destinationAddressPrefix": "*",
    "access": "Allow",
    "priority": 100,
    "direction": "Inbound"
  }
}

Docker is installed on the Ubuntu VM by using the DockerExtension extension, and docker compose is used to create and run a MySQL image. Note how I set the MySQL root password using MYSQL_ROOT_PASSWORD and the parameter passed in via the template parameters, and how I used MYSQL_DATABASE to create a new database called expressmysql-development

{
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "name": "[concat(variables('vmName'),'/', variables('extensionName'))]",
      "apiVersion": "2015-05-01-preview",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]"
      ],
      "properties": {
        "publisher": "Microsoft.Azure.Extensions",
        "type": "DockerExtension",
        "typeHandlerVersion": "1.0",
        "autoUpgradeMinorVersion": true,
        "settings": {
          "compose": {
            "db": {
              "image": "mysql",
              "ports": [
                "3306:3306"
              ],
              "volumes": [
                "/var/lib/mysql:/var/lib/mysql"
              ],
              "environment": [
                "[concat('MYSQL_ROOT_PASSWORD=', parameters('mysqlPassword'))]",
                "MYSQL_DATABASE=expressmysql-development"
              ]
            }
          }
        }
      }
    }

And the last bit I want to call out is how I'm setting up app settings on the Web App with details of the MySQL database being created as part of the same template. I'm setting a MYSQL_HOST setting by getting a reference to the fqdn from the VM, and also setting MYSQL_ROOT_PASSWORD with the password passed in via the parameters:

"appSettings":  [
  {
    "Name":  "MYSQL_HOST",
    "Value":  "[reference(concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))).dnsSettings.fqdn]"
  },
  {
    "Name":  "MYSQL_ROOT_PASSWORD",
    "Value":  "[parameters('mysqlPassword')]"
  }
]

NICE! How can I use it?

Assuming you already have an Azure subscription, you can deploy the ARM template using the CLI, PowerShell or other means.

Here's how to do it using the Azure CLI. First, make sure to install the CLI and log in to your Azure subscription using the CLI.

Next, clone the sample:

git clone https://github.com/nzthiago/WebAppMySQLDocker.git

This should download the sample into a WebAppMySQLDocker folder for you. Then browse to the env folder: 

cd WebAppMySQLDocker/env

Switch to the ARM mode of the CLI:

azure config mode arm

Next use your favorite editor to change the azuredeploy.parameters.json file with the username and password values. The mySqlPassword parameter in that file will be set to your MySQL database root user password. The adminUsername and adminPassword will be the credentials set on the ubuntu VM if you need to ssh into it.

Finally - deploy the sample. You need to pass in values for the resource group name, location, and use the -f parameter to pass in the template file and the -e parameter for the template parameters file. For example:

azure group create "thiagonodexp" "West US" -f azuredeploy.json -e azuredeploy.parameters.json

This is the result you should see, confirming the deployment has been kicked off successfully:

After a few minutes you will have all of the items created in the resource group. You can check on it from the Azure Portal:

Or you can use the azure group deployment show command in the CLI to get the status of the deployment. For example, here is the result showing that my deployment was successful (azuredeploy is the default name of a deployment if you don't pass it in as a parameter when creating the deployment):

Screen Shot 2015-11-24 at 11.55.06 AM.png

The important information in there is that ProvisioningState is Succeeded, meaning that our ARM template deployment finished successfully. 

From the Azure Portal you can see that the App Settings of your Web App. They will be configured with the MySQL container host and root password details that you need to connect to your MySQL database. These get exposed as Environment Variables to your web app code:

You can also get these values from the Azure CLI:

Now it's up to you: you can connect to your new MySQL database using the mysql command line shell, or the MySQL Workbench or other client to create tables and other artifacts. The user is root and the port is 3306 which are the default for MySQL.

Once the database is ready, create a local PHP, Node.js, .NET, Java, or Python web app, and when ready, publish your site to your new Web App via git or other ways.

Notes

This post describes a simple Web App + MySQL in a container deployment. It doesn't follow production best practices (for example, the Web App is in the limited Free tier, the MySQL database's 3306 port is exposed externally, the Ubuntu VM is using username and password instead of SSH certificates, etc). But it is a way to quickly get started if you are developing or want to test something that is based on a website and a MySQL database.

You can expand on this sample and make it production ready when needed - the basics are there!