Monday, December 15, 2014

Choose IBM’s Docker-based Container Service on Bluemix for your I/O intensive code

Roughly a week ago IBM announced a new Docker-based service[1] as part of Bluemix PaaS[2]. It is still early but the service looks very promising, especially for I/O heavy workloads like databases and analytics. This post will help you create your own container instance running on Bluemix and provide some pointers on how you can evaluate whether the I/O performance of the instances matches your application’s needs. It will also describe nuances of using boot2docker[5] if you are running Mac OSX or Windows.

Even if you are not familiar with Docker, chances are you know about virtual machines. When you order a server hosted in a cloud, in most cases you get a virtual machine instance (a guest) running on a physical server (a host) in your cloud provider’s data center. There are many advantages in getting a virtual machine (as opposed to a physical server) from a cloud provider and arguably the top one is quicker delivery. Getting access to a physical server hosted in a data center usually takes hours while you can get a virtual machine in a matter of minutes. However, many workloads like databases and analytics engines are still running on physical servers because virtual machine hypervisors introduce a non-trivial penalty on I/O operations in guest instances.

Enter Linux Containers(LXC) and Docker. Instead of virtualizing the hardware (as the case with traditional virtual machines) containers virtualize the operating system. Start up time for containers is as good or better (think seconds not minutes) than for virtual machines and the I/O overhead all but disappears. In addition, Docker makes it easier to manage both containers and their contents. Containers are not a panacea and there are situations where virtual machines make more sense but that’s a topic for another post.

In this post, you can follow along with the examples to learn whether I/O performance of Docker containers in IBM Bluemix matches your application’s needs. Before starting, make sure that you have access to Bluemix[3] and to the Container Service[4]. In short, once you have provisioned an instance of the Container Service, you should have received an email notifying you that you have been approved for access and you should be able to see an API key as described in the example here[1].

Getting Started

The instructions below describe how to use boot2docker[5] for access to a Docker installation. boot2docker deploys a VirtualBox guest with Tiny Core Linux to OSX and you’ll ssh into this guest to access docker CLI. The same approach should also work on Windows although I am yet to try it.

Start of boot2docker specific instructions

Install boot2docker as described here[5]. Make sure that the following commands work correctly

boot2docker init
boot2docker start
$(boot2docker shellinit)
Use the following command to connect to your boot2docker Tiny Core Linux guest

boot2docker ssh

Install python and the ice tool in your boot2docker guest to interface to the IBM Container Environment. The approach used in these steps to install python is specific to TinyCore Linux and shouldn’t be used on other distros.

tce-load -wi python
curl -o - | sudo python
curl -o - | sudo python
curl -O
sudo pip install

End of boot2docker specific instructions

If you are not using boot2docker, you should follow the standard ice CLI installation instructions[6]

Before proceeding, create a public/private key pair which you’ll use to connect to your container. Replace the email address below with yours. The examples below assume that you’ll save your public key file to ~/.ssh/

ssh-keygen -t rsa -C "<>"

Make sure that you have provisioned an instance of the Container Service in Bluemix and copy/paste the API key into the command below. Details on how to obtain the API key are here[1]. Also make sure that you note the registry key you specified when provisioning the Containers service. You’ll need it later in the instructions.

ice login -k <api_key> -H -R

The login command should complete with a Login Succeeded message.
Next, you will pull one of the base IBM Docker images and customize it with your own Docker file:

ice --local pull

Once the image completed downloading, you will create a Dockerfile that will customize the image with your newly created credentials (so you can ssh into it) and with sysbench scripts for performance testing.

Create a Dockerfile using your favorite editor and the following contents:

COPY .ssh/ /root/.ssh/
RUN cat /root/.ssh/ >> /root/.ssh/authorized_keys
ADD *.sh /bench/
RUN apt-get install -y sysbench

Next, create with the following contents

sysbench --test=fileio --file-total-size=$SIZE prepare
sysbench --test=fileio --file-total-size=$SIZE --file-test-mode=rndrw --init-rng=on --max-time=30 --max-requests=0 run
sysbench --test=fileio --file-total-size=$SIZE cleanup
And containing:
sysbench --test=cpu --cpu-max-prime=$PRIME run
add execute permissions to both scripts
chmod +x *.sh
At this point your custom Docker image is ready to be built. Run
ice --local build -t example/sysbench .
which should finish with a Successfully built message followed by an ID.

Push your custom Docker image to Bluemix

When you got access to the Container Service, you should have noticed a registry URL which is shown right above your API key. For an example, see here[1]. The registry URL should end with a postfix which you specified when provisioning the Containers service  . In the commands below, replace <registry_id> to ensure you are specifying your registry URL.

ice --local tag example/sysbench<registry_id>/sysbench
ice --local push<registry_id>/sysbench
ice run -n sysbench<registry_id>/sysbench

After you have completed executing the commands above, your container should be running. You can verify that by executing
ice ps
Request a public IP address from the Container Service and note its value.
ice ip request
Bind the provided public IP address to your container instance with

ice ip bind <public_ip_address> sysbench
Now you can go ahead and ssh into the container using
ssh -i ~/.ssh/id_rsa root@<public_ip_address>
Once there, notice it is running Ubuntu 14.04
lsb_release -a
on a 32 core server with Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz CPUs

cat /proc/cpuinfo
processor : 31
 vendor_id : GenuineIntel
 cpu family : 6
 model : 62
 model name : Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
Now you can also test out the I/O performance using

. /bench/ 100M
Just for a comparison, I ordered a Softlayer virtual machine (running on a Xen hypervisor) and ran the same Docker container and the benchmark there. In my experience, the I/O benchmark results were roughly twice better on the Container Service than on a Softlayer VM.You can also get a sense of relative CPU performance using
. /bench/ 5000


Benchmarks are an artificial way of measuring performance and better benchmark results don’t always mean that your application will necessarily run better or faster. However, benchmarks help understand if there exists potential for better performance and help you design or redesign your code accordingly.

In case of the Containers Service on IBM Bluemix, I/O benchmark performance results are significantly superior to those from a Softlayer virtual machine. This shouldn’t be surprising since Containers runs on bare metal Softlayer servers. However, unlike the hardware servers, Containers can be delivered to you in seconds compared to hours for bare metal. This level of responsiveness and workload flexibility enable Bluemix application designers to create exciting web applications built on novel and dynamic architectures.