This document serves as a tutorial guide to help developers and systems administrators understand how they may be able to begin using Docker on Microsoft Azure.
Docker is a popular open source containerization tool. It provides an open platform for developers and sysadmins to build, ship, and run distributed applications. Since Docker enables apps to be quickly assembled from components, it can eliminate much of the inherent friction between development, QA, and production environments. Many IT organizations are now using Docker because it can ship faster and run the same app, unchanged, on laptops, data center VMs, and any cloud - including Microsoft Azure.
A couple of very useful online resources that we recommend for anyone unfamiliar with Docker before diving into this process:
After you have reviewed these above Docker materials, the information below will help to get you started with the standard Docker tooling on Microsoft Azure, using cross-platform Azure command line tools. Once you have completed this tutorial, you should be ready to dive into the Docker documentation more deeply and begin using within future application development and deployment projects.
Setting up your Work Environment
In order to work through this tutorial you will need to Create a Docker Host on Microsoft Azure. Once you have a host running this tutorial will explain how to create and manage containers on the host.
Working with Docker Containers
It is now time to create the first Docker container. Please note that while we are using Azure in our example, the process from this point forward is not unique to Azure. The following steps are carried out on the client machine we configured while creating our Docker Host.
Once the Docker host has been created using the Azure CLI, standard Docker client tools will be able to create and manage Docker containers. Please refer to the Docker documentation for a comprehensive guide to the client tools and additional examples.
Connecting to the Host
The first step is to verify the connection to the host.
The following command will tell the client to connect using TLS to the host. The domain name should be the same machine name used in the command above concatenated with ".cloudapp.net". Once the client has connected to the host it will run the command "info" to retrieve additional information about our host.
docker --tls -H tcp://ubuntu-docker.cloudapp.net:4243 info
If this command fails to connect to the virtual machine, the VM may not yet be fully provisioned. Simply wait a few minutes and try again. Once the machine has been fully provisioned, the above command should generate an output similar to this:
The DOCKER_HOST environment variable
The Docker client uses the -H command line argument to identify the host to connect to. Using this argument, it is possible to manage multiple hosts from a single client machine. In addition, it is possible to use the DOCKER_HOST environment variable to reduce the amount of typing needed for each command.
To set the value of DOCKER_HOST use:
Then verify using one of the following two commands:
docker --tls -H tcp://ubuntu-docker.cloudapp.net:4243 info
docker --tls info
The following sections assume that the DOCKER_HOST environment variable has been set as per above.
Creating a Hello World Container
The following example demonstrates how to boot up a bare bones Busybox container and run a simple "echo hello world" command on it. At about 2.5 Mb in size, Busybox is one of the smallest Linux distributions available. This makes it ideal not only for very simple tests like this, but also much more.
Lots of "magic" happens behind the scenes in this next step. In essence, the Docker client will create a Busybox container on the host VM by retrieving an image of that container from the Docker Hub. The container will then start running and execute the “echo hello world” command . The container will shut down after this operation is complete. For those who wish to understand this process in more detail, please consult the Docker documentation.
The command we need to run is:
docker --tls run busybox echo hello world
Note that the "hello world" output above comes from the container running on the host (evidenced by the fact that it is printed before control returns to the client VM's shell).
In following these steps, we have both created a simple Docker container on Azure and run a first containerized “application” on Azure.
Identifying Containers on a Host
A list of all the containers on the host can be generated running the "ps" command. Recall that the Busybox container shutdown once the hello world application had completed. For this reason, so it is be necessary to also use the "-a" command line switch to ensure that the output includes all containers. Without this switch, the command will only produce a list running containers.
docker --tls ps -a
This command can be used to retrieve the ID for a specific container that you may wish to work with again. For example, using the above command in our test environment, the container ID for the Busybox container we just created is listed as "775abb48abd9":
Docker gives each container an automatically generated name. This can often be used in place of the ID and is easier to remember. In a short while, we will be using this information to manage an existing container, but first we will look at how we might modify a container.
Modifying a Container
Now it is time to do something a little more involved. To demonstrate how a container can be modified incrementally, we will start by creating a container that uses Ubuntu. Then, in a bash shell running on this container, we will create a simple hello.txt file. Finally, we will cause the container to restart and list its available files. A small example, yet it helps to show how packages and files may be managed on a Docker container, as well as how those containers may be started and stopped as needed.
Let’s begin by creating a new container using the base Ubuntu container. We will connect to this container so that we can manually run commands in a bash shell:
docker -tls run -t -i ubuntu bash
The '-t' indicates that we want to allocate a psuedo terminal, and '-i' tells Docker to keep STDIN open. Together these two switches allow us to interact with the container. After running this command, we will be in a Bash terminal on the container, rather than return to the Docker client:
On this container, touch a file with the following command:
And confirm that the file is present using:
Which should produce an output similar to this:
From the above, you can see that we have created a hello.txt file. Now, we will use the command “exit” to exit the container and return to the client machine. The container will shut down at this point, since the bash command is now completed. If we execute "ls -l" again, the client directory contents rather than the container directory contents:
In order to continue working with this same container, we will need to reference it by its ID (or name). As before, this can be accessed using the "ps" command:
docker --tls ps -a
The output of this command will include all the running and stopped containers on our host:
The ID for the container we just created is "08d2b92353c3" and its name is “jolly_mclean”.
We have the option to continue to make similar changes to an image, such as installing packages using apt-get and adding application code. Those changes can also be applied to our local copy of the image. This allows for a kind of version control system for the images. Once you have produced a version of the image that you believe is worth sharing, you can push those changes to a shared repository.
For this example, we will limit the scope to restarting and reconnecting to the container.
Using the name obtained above, we first start the container using the “docker start” command:
docker --tls start jolly_mclean
One thing that will be evident to those of you experienced running virtual machines is that the Docker container starts up significantly faster than a virtual machine. This is because the container is running inside of an already running virtual machine. Therefore, there is no need to start the operating system.
With the container up and running, we then attach to it using the “docker attach” command:
docker --tls attach jolly_mclean
Our container has been configured to run the command “bash” and operate interactively, so we can also issue additional commands. For example, to verify whether the hello.txt file is still there, type “ls hello.txt”:
To detach again, simply “exit” the bash shell, which will shut down the container as before.
It is possible to create images using a Dockerfile, to provide a set of instructions that Docker will run on the container. This makes it possible to automate the configuration of container images. There are many other options available too, since Docker works well with tools such as Puppet, Chef and Powershell..
Conclusion: Running Docker on Microsoft Azure
We created this example to demonstrate the basics of Docker on Microsoft Azure.
Using the Azure cross-platform command line tools we created a Docker host as a virtual machine on Microsoft Azure. The CLI tools also configured the Docker client to securely access and manage the containers on that host. Using the standard Docker tools we can now manage containers on this, and other Azure VMs. We are now able to leverage the full power of Docker containerization on Microsoft Azure.
If you are interested in using Docker on Azure we recommend that you now consult the Docker user guide for additional detail.