Even for someone who does not care about Microsoft Azure at all, I think the “Virtual Machine Extensions” concept is something pretty darn interesting and other cloud providers do not have an equivalent.
This article is about one of them: Azure Docker Extension.
First of all, you must be wondering what a VM Extension is:
What are Virtual Machine Extensions?
In Azure, we give you a way to install things or run scripts on the virtual machine instances from outside programmatically. We call these VM extensions.
Through an agent running on all Linux and Windows images, we can deliver extensions to the machines and run them to do the task they are designed for.
Extensions are often published by Microsoft or other software vendors and offered at no additional charge.
What is the use case?
Extensions are often used for:
- installing software (security, monitoring etc.)
- intervening the machine from outside (reset password/ssh key)
- running some prep scripts on the machine.
You can explore some extensions on Azure website.
In a way, extensions are like cloud-init/cloud-config. However, unlike those, Azure gives you this flexibility to add/remove extensions on the machines at any time or change their configuration.
Power of Virtual Machine Extensions
For many of those use cases, you might be just fine by installing the software or running the script yourself. However this it not easily programmable or invokeable from outside the VM from a CLI or web UI. Extensions basically give you this expressive power.
You can declaratively express extensions as resources in your deployment scripts or Azure Resource Manager templates. Check out this example, or this example.
Enter “Docker Extension”
Azure Docker Extension has two main responsibilities:
- install
docker-engine
to a machine and configure it. - if specified, start containers with
docker-compose
Docker Extension can help you configure:
- command-line arguments to docker-engine
- TLS certificates for docker client authentication
- login credentials for Docker Hub or other registries.
As of writing, Docker Extension supports many Linux distros on Azure, such as Ubuntu Server, CoreOS, CentOS and Red Hat Enterprise Linux.
Why is it useful?
(In other words, how is this different than docker-machine
or just installing
docker myself?)
Docker Extension comes really handy when you want to specify docker properties of a machine or containers a machine should run as part of your deployment model.
It is deeply integrated to Azure: Deployment of Docker Extension can be considered as a deployment failure in general and it will surface as an error on the API or CLI or the management portal if that becomes the case.
Esstentially, you can install docker and even start some containers without doing any SSH. If you want your deployment plane to be Azure API, you will not switch back and forth between Azure management tools and SSH.
Starting containers with Docker Compose is really useful: If you would like to bootstrap an orchestrator (Kubernetes, Docker Swarm) or have a base set of containers (such as monitoring, log collection) on all your machines.
You basically just convert a docker-compose.yml
to JSON format and use it as
configuration to the Docker Extension (example below) and it will
start the containers you specified.
Sample Configuration
You can use Docker Extension with no configuration at all. In this mode it will only install the Docker engine and docker-compose on the machine. Here is an example.
However, let’s say you have a virtual machine on Azure that you would like to configure the docker daemon and run some containers, such as Google’s cAdvisor for monitoring your instance.
For that, create a config.json
file:
{
"docker" : {
"options": ["--storage-driver=aufs", "--debug"],
},
"compose": {
"monitoring" : {
"image": "google/cadvisor",
"ports": ["8080:8080"],
"restart": "always",
"volumes": [
"/:/rootfs:ro", "/var/run:/var/run:rw",
"/sys:/sys:ro", "/var/lib/docker/:/var/lib/docker:ro"
]
}
}
}
and you just use this in the azure
cross-platform CLI:
azure vm extension set <vm-name> DockerExtension Microsoft.Azure.Extensions 1.* \
--public-config config.json
in a couple of minutes, your Linux VM on Azure will start installing docker and will eventually start the cAdvisor container as you requested.
You can make it part of your ARM templates and deploy with all instances you create or do a lot more creative things programmatically.
Storing Secrets
In addition to config.json
, you can have an additional configuration file to
store your secrets. These secrets could be:
- TLS keys to secure the Docker engine socket
- environment variables to docker-compose
- Credentials for Docker Hub (or other image registry) credentials.
Microsoft Azure infrastructure encrypts these fields and delivers to your instance in a secure fashion.
Secrets configuration is also json, and looks like this:
{
"certs": {
"ca": "<<base64 encoded ~/docker/ca.pem>>",
"cert": "<<base64 encoded ~/docker/cert.pem>>",
"key": "<<base64 encoded ~/docker/key.pem>>"
},
"login": {
"username": "<<docker-hub-credentials>>",
"password": "<<docker-hub-credentials>>",
"email": "<<docker-hub-credentials>>"
},
"environment" : {
"MYSQL_ROOT_PASSWORD": "<<docker-compose-will-use-this>>"
}
}
The secrets file can be specified on the azure vm extension set
command with
--private-config-path <file>
argument. The secrets file itself and all its
keys are optional.
Learn more
You can read the User Guide of the Docker Extension on GitHub.
To give a bit historical context, Azure Docker Extension was announced the day Docker 1.0 was released. It is older than almost anything in Docker ecosystem. It was initially developed by MS Open Tech.
Later on we took it over and did a rewrite in Go, added many features and made it a lot more robust. We are committed to improving it and delivering cutting edge features.
Let us know by opening issues on the GitHub repository if you have any feedback or creative use cases!
Leave your thoughts