Sunday, May 4, 2014

100 environments sequentially created and destroyed in 30 seconds

Consider this Blogger a temporary home for my posts that I plan to move soon to a self-hosted blog. I just wanted to get up and writing as quick as possible, and Cory House's Outlier Develoer was the kick I needed. Check back for posts on devops, .NET and Java development, some Powershell gems, and more.

Cheers!

For my first post on Docker, I wanted to give you a quick taste of just how powerful Docker and the underlying Linux kernel technology, LXC (Linux Containers) are. 

For an overview of what containers are, I will direct you to the Docker info page, but briefly, they are simply a means of achieving operating system-level virtualization. A later blog post will explain this in depth and describe some use cases. The end result, however, is an analogue to virtual machines that are lightweight and, most important for this demo, quick to provision. This will allow us to start up a container environment, run a process on it, and deprovison it one hundred times in half a minute.

To start, we'll use a fresh Ubuntu 14.04 installation, in my case on Microsoft Azure (since the virtualization is happening on the OS level, we don't have to worry about whether or not we have a bare metal host). I'll update the package repository and install docker.io

sudo apt-get update
sudo apt-get install docker.io

After this quick installation, we can run

docker.io

to see a list of our available commands. Run sounds the most exciting so lets try that. In the way that we want to use it, the run command takes two arguments: an image (think of this like a VM disk image) and a command that we want to run on the container. Docker uses a Unix socket owned by root, so we'll need to use sudo (see the Docker installation guide for more information). The command looks like this:

sudo docker.io run ubuntu echo Hello wold within a world!

"Hey, this is taking minutes! You said it's supposed to be fast!" The ubuntu image is actually an image maintained and hosted by the Docker index. Whenever you specify an image with the docker.io run command, docker looks for the image locally, and if it doesn't find it, searches the Docker index, pulling it down locally. If you try the same command again, you'll see that it completes much quicker. You can use the time command to see the execution time of a process.

time sudo docker.io run ubuntu echo Hello World!

gives me 000.229s. In two-tenths of a second on a very modest machine (Azure A1), a virtual machine is provisioned, configured, your given process is run, and the machine is deprovisioned. That's quite an improvement over a hypervisor virtual machine! 

Let's get our demo underway first, let's see what it takes to get a simple loop. In bash, we can write the following to write "Hello World!" to the console ten times:

for n in {1..10}
do
echo "Hello World!"
done

or in one line,

for n in {1..10}; do echo Hello World!; done

Instead of the trivial echo, let's have our host machine do some real work. Add our docker run command to the beginning of the echo  and bump the loop up to 100 as follows:

for n in {1..100}; do sudo docker.io run ubuntu echo "Hello World!"; done

If I add "time" to the beginning of the line, I get that it takes 28 seconds for one hundred machines to be created and destroyed one after the other, on a very light host machine.

This speed enables many great uses of Docker, for example, in a continuous integration pipeline. Though most pipelines run preliminary unit tests on a developer's check-in, devious bugs could slip through that might not get caught until a later pipeline stage where the application is deployed to a test environment. Normally, it would be less than ideal to have a developer have to wait for a traditional test environment to be provisioned to test his code on every check-in, which could take many minutes. With a docker container, however, the application could be rapidly deployed, if only for a quick smoke test of the application or even automated acceptance testing. This isn't the only benefit of containers in a continuous integration pipeline, but more on that later.

Thanks for reading and feel free to post feedback!

Wednesday, April 30, 2014

Hello world

System.out.println(Console.WriteLine(fmt.Printf(puts 'Hello World'))) | Out-Host

Check back for a real post soon!