Contents

Container and Virtual Machine: Hands-on Comparison Notes

Container and Virtual Machine: Hands-on Comparison Notes

Know the differences between a VM and a Container by following a short tutorial.

https://cdn-images-1.medium.com/max/800/1*Mg6Ii8ibJPomegYj1tn8Ag.jpeg

Source: Pixabay

Theoretical comparison

Skip this section if you already know the differences of these two technologies in theory.

I’m sure like me, you’ve read comparisons about VMs and Containers along the lines of how they differ when in comes to their architecture and their respective pros and cons. Let’s quickly do a recap.

Virtual Machine (VM)

A running software that emulates a how a bare metal machine server works. One physical machine can be shared by multiple VMs that run on top of it. Each VM requires its own Operating System and also its own CPU, memory and storage resources. Which means, the more VMs you run on your bare metal server; the more resources you need.

Container

A container is a unit of software that allows you to package and run your application as an isolated process. It is not meant to be a VM replacement. It also runs on a VM that supports Linux Containers.

In this post, let’s try to learn the difference between the two while getting our hands dirty.

The short tutorial below will answer the question:How can we show the difference between a container and a virtual machine in a “hands-on” way?

Pre-requisites

We will be using Docker for our container and Vagrant for our VM. You can skip this part if you already have these installed and setup in your machine.

Run the docker container

In your terminal window, pull Docker’s busybox image and run it as a container.

docker run -it --rm busybox

The above docker run command will automaticallysshyou into the container. The output will look like the following:

➜ ~ docker run -it --rm busyboxUnable to find image 'busybox:latest' locallylatest: Pulling from library/busyboxee153a04d683: Pull completeDigest: sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70Status: Downloaded newer image for busybox:latest/ #

Run the Vagrant VM

Open another terminal window or tab.

Downloadthis Vagrantfileby running:

curl https://raw.githubusercontent.com/ardydedase/devops/master/vagrant/Vagrantfile --output Vagrantfile

In the same directory where you have downloaded the Vagrantfile, boot up the VM by running:

vagrant up

Booting up the VM for the first time might take a few minutes. You can grab a coffee at this point.

When the VM is ready,sshinto the VM:

vagrant ssh

After you have ssh’ed into the VM,sudoas a superuser:

sudo su

Side by side comparison

Now that you have two terminal windows open side by side, let’s compare the following attributes by running the commands indicated in each terminal window (docker and vagrant).

Disk usage size

Compare the disk usage sizes of a VM and a container.

In both your Docker and Vagrant terminal, run:

du -sh /

Compare the total disk usage sizes between the two.

Docker container sample output:

/ # du -sh /1.3M /

Vagrant VM sample output:

root@vagrant-ubuntu-trusty-64:/home/vagrant# du -sh /du: cannot access '/proc/8160/task/8160/fd/4': No such file or directorydu: cannot access '/proc/8160/task/8160/fdinfo/4': No such file or directorydu: cannot access '/proc/8160/fd/4': No such file or directorydu: cannot access '/proc/8160/fdinfo/4': No such file or directory1.6G /

Refer to the returned disk usage sizes: 1.3M for Docker and 1.6G for Vagrant. Containers have way smaller total disk usage compared to VMs.

Running processes

Observe the number of processes running in a VM and a container.

In both your Docker and Vagrant terminals, run:

top

Compare the number of processes running between the two. The output for each terminal window will look something similar to the next sections.

Docker container sample output:

Mem: 761468K used, 1285664K free, 860K shrd, 104800K buff, 301180K cached
CPU: 0.0% usr 0.0% sys 0.0% nic 100% idle 0.0% io 0.0% irq 0.0% sirq
Load average: 0.01 0.04 0.01 2/413 12 
PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND 
1 0 root S 1316 0.0 1 0.0 sh 
12 1 root R 1304 0.0 1 0.0 top

Vagrant VM sample output (truncated):

top - 14:57:46 up 7:36, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 76 total, 1 running, 75 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 501576 total, 464196 used, 37380 free, 59192 buffers
KiB Swap: 0 total, 0 used, 0 free. 177056 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 
8281 root 20 0 23544 1528 1092 R 0.3 0.3 0:00.01 top 
1 root 20 0 33588 2964 1472 S 0.0 0.6 0:00.77 init 
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 
3 root 20 0 0 0 0 S 0.0 0.0 0:00.29 ksoftirqd/0 
4 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0 
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00

“/proc” folder

The*/procfolderprovides an interface to the kernel data structures of processes. This is where we can find information about the executed program. Observe what are included in their respective/proc*folders.

Inspect the process subdirectory’s folder structures by running the following command in both Docker and Vagrant terminal windows:

We will be usingselfin the succeeding sections instead of the PID to keep it simple. It references the folder of the calling process.

ls -al /proc/self/ns

Docker container sample output:

/ # ls -al /proc/self/ns
total 0
lrwxrwxrwx 1 root root 0 Sep 2 14:19 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Sep 2 14:19 ipc -> ipc:[4026532258]
lrwxrwxrwx 1 root root 0 Sep 2 14:19 mnt -> mnt:[4026532256]
lrwxrwxrwx 1 root root 0 Sep 2 14:19 net -> net:[4026532261]
lrwxrwxrwx 1 root root 0 Sep 2 14:19 pid -> pid:[4026532259]
lrwxrwxrwx 1 root root 0 Sep 2 14:19 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Sep 2 14:19 uts -> uts:[4026532257]

Vagrant VM sample output:

root@vagrant-ubuntu-trusty-64:/home/vagrant# ls -al /proc/self/nstotal 0dr-x--x--x 2 root root 0 Sep 1 03:09 .dr-xr-xr-x 9 root root 0 Sep 1 03:00 ..lrwxrwxrwx 1 root root 0 Sep 1 03:09 ipc -> ipc:[4026531839]lrwxrwxrwx 1 root root 0 Sep 1 03:09 mnt -> mnt:[4026531840]lrwxrwxrwx 1 root root 0 Sep 1 03:09 net -> net:[4026531956]lrwxrwxrwx 1 root root 0 Sep 1 03:09 pid -> pid:[4026531836]lrwxrwxrwx 1 root root 0 Sep 1 03:09 user -> user:[4026531837]lrwxrwxrwx 1 root root 0 Sep 1 03:09 uts -> uts:[4026531838]

You’ll notice that the Docker container has a Control Group orcgroupwhile the Vagrant VM does not have. A Control Group is used for resource allocation, provides hard and soft limit on resources like CPU and memory.

To further dissect what’s in a Control Group that the process belongs to:

cat /proc/self/cgroup

Docker container sample output:

/ # cat /proc/self/cgroup13:name=systemd:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe6812:pids:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe6811:hugetlb:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe6810:net_prio:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe689:perf_event:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe688:net_cls:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe687:freezer:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe686:devices:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe685:memory:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe684:blkio:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe683:cpuacct:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe682:cpu:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe681:cpuset:/docker/6dd52f68d0b4b81d3d8ee08aa2ac4c14bb464e9f4db4082121faa392e72afe68

Vagrant VM sample output:

root@vagrant-ubuntu-trusty-64:/home/vagrant# cat /proc/self/cgroup2:name=systemd:/

Conclusion

  • Containers are meant to run only the processes that it needs to run. For VMs, it needs to run everything you need in a Linux OS.
  • Containers are meant to be as lightweight as possible in terms of disk usage size and number of processes run so that it’s faster to boot up and tear down.
  • Enabling technologies as namespace likepid, ipc, uts, net, mnt, and useralong withcgroupfrom Linux are being used by Containers.

References