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 and to the Container Service. 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.
The instructions below describe how to use boot2docker 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. Make sure that the following commands work correctly
Use the following command to connect to your boot2docker Tiny Core Linux guest
boot2docker init boot2docker start $(boot2docker shellinit)
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 https://bootstrap.pypa.io/get-pip.py -o - | sudo python curl https://bootstrap.pypa.io/ez_setup.py -o - | sudo python curl -O https://static-ice.ng.bluemix.net/icecli-1.0.zip sudo pip install icecli-1.0.zip
End of boot2docker specific instructions
If you are not using boot2docker, you should follow the standard ice CLI installation instructions
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/id_rsa.pub
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. Also make sure that you note the registry key you specified when provisioning the Containers service. You’ll need it later in the instructions.
ssh-keygen -t rsa -C "<firstname.lastname@example.org>"
The login command should complete with a Login Succeeded message.
ice login -k <api_key> -H https://api-ice.ng.bluemix.net/v1.0/containers -R registry-ice.ng.bluemix.net
Next, you will pull one of the base IBM Docker images and customize it with your own Docker file:
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.
ice --local pull registry-ice.ng.bluemix.net/ibmnode
Create a Dockerfile using your favorite editor and the following contents:
FROM registry-ice.ng.bluemix.net/ibmnode:latest MAINTAINER Carl Osipov COPY .ssh/id_rsa.pub /root/.ssh/ RUN cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys ADD *.sh /bench/ RUN apt-get install -y sysbench
Next, create io.sh with the following contents
And cpu.sh containing:
#!/bin/sh SIZE="$1" 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
add execute permissions to both scripts
#!/bin/sh PRIME="$1" sysbench --test=cpu --cpu-max-prime=$PRIME run
At this point your custom Docker image is ready to be built. Run
chmod +x *.sh
which should finish with a Successfully built message followed by an ID.
ice --local build -t example/sysbench .
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. 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.
After you have completed executing the commands above, your container should be running. You can verify that by executing
ice --local tag example/sysbench registry-ice.ng.bluemix.net/<registry_id>/sysbench ice --local push registry-ice.ng.bluemix.net/<registry_id>/sysbench ice run -n sysbench registry-ice.ng.bluemix.net/<registry_id>/sysbench
ice psRequest a public IP address from the Container Service and note its value.
ice ip requestBind the provided public IP address to your container instance with
ice ip bind <public_ip_address> sysbenchNow 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 -aon a 32 core server with Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz CPUs
Now you can also test out the I/O performance using
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
. /bench/io.sh 100MJust 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/cpu.sh 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.