2015-05-23

This is about Zocker, a project where I learnt container technologies by doing. The approach was to recreate a simple Docker clone using FreeBSD jail mechanism and ZFS. The essential concepts were quite easy to make and the result is 1.5 kloc of sh script. I believe that we should put all the effort in Docker project and I wish that it will have FreeBSD support one day. However, for me and my limited free time it was easier to hack with an independent project.

Introduction

Operating-system-level virtualization technologies have a long history, but the Docker phenomenon has made container technologies increasingly popular today. There must be many reasons to Docker popularity, but for me the most important is standardization. Docker concepts will drive application deployment in one common direction.

To me following are the key concepts in Docker. The first is an isolated process. A container runs a single process and containers are isolated using operating-system-level virtualizatiin. A container contains also the environment of the process, that is files and operating system reources.

However, to make containers portable they are decoupled from the host operating system. All shared resources: ports and shared volumes for example, must be explicitly specified on boot.

To help this, containers contain metadata. Parameters like incoming ports, shared volumes and environment variables are defined in container's metadata. In fact the command that is run inside a container is also one of the metadata parameters. We can say that a running container is combination of a process, a filesystem and metadata.

The filesystem and metadata can be saved into an image. It is a series of incremental changes in the filesystem or metadata. The image concept is essential as new containers can be created only from images.

To simplify image creation there is a Dockerfile. It is a list of parameters that will define an image and the image can be built easily by providing the file.

To share images easily there is a repository. There is a one common Docker repository, but you can also create another one for private use.

When a container is destroyed container's state is lost if the state is not saved into an image or if a volume is not used. A volume is a shared filesystem that can be shared with the host operating system or with an anohter container. Volume mount points are also defined in container's metadata.

Containers are isolated on network level as well. Operator needs to expose ports defined in metadata in boot or he can link the containers. Linking is a way to link multiple containers together in network level and send connection information from one to another.

Simply put, a container is a process, its environment and metadata in one package. This helps in deploying application in scale. To me this concept in container technologies is more important than fast boot times.

I wanted to deploy my application using the concepts mentioned above on FreeBSD and I wrote Zocker. Zocker covers the concept of an isolated process, decoupling, metadata, an image, a Dockerfile, a repository and a volume. However, networking is different. Zocker doesn't use network stack virtualization, it simply uses an IP address per container. I also like the simple approach as now I don't need to worry about port mappings when deploying containers. The linking concept is not implemented because of the simplified networking. There are also dozens of minor differences, for example volumes can be mounted only from the host system and Zocker doesn't implement container daemonizing.
However, I want to emphasize that Zocker is not going to be a feature complete Docker clone, but it is a proof of concept tool to implement similar features.

The End Result

Zocker can be found here. Zocker has a CLI interface that tries to mimic Docker interface closely. Following tutorial goes through most of the commands. Zocker should be run as root and the examples are for tcsh shell.

Preparations

To start out we need a FreeBSD 10 (Zocker uses jail.conf) installation with /usr/src to compile a base jail.

Following creates a ZFS filesystem for testing purposes, does a git checkout and configures Zocker (replace mypool and em0 with proper values)

zocker tag

We need to tag it with tag 'base' so that rest of the examples will work.

/mypool/zocker/zocker # zocker tag 10.1-RELEASE-p9 base

zocker run

To try out the image let's fetch URL http://www.google.com. Zocker's simple networking doesn't assign network addresses automatically and we need to assign them manually to containers. Zocker configures jail tool to resolve an address using container's hostname, and to make commands zocker build or zocker run to work we need to assign resolvable hostnames. So let's have hostnames build and test in hosts file

zocker push

Images are transferred to a Zocker repository via SSH. We need to configure SSH keys for a user in server side and configure REPOSITORY variable in client side config file. After the configuration, a push will transfer all the intermediate images to a server

/mypool/zocker/zocker # zocker push apache

When there are images in a repository zocker search and zocker pull will work. There is also zocker del to delete images from a repository.

Discussion

There is a lot going on around the Docker phenomenon and I wanted to share my research. I'm impressed how easily the container concept can be implemented using ZFS and jails. Zocker is in fact a thin wrapper that doesn't add that much on top of existing technologies.

I'm open for suggestions and improvements, but please keep in mind that Zocker aims to be a simple, but functional tool to hack and learn the container concepts. The quality of code is currently not up to par and there are lot of things to fix. However, it works and I use it to manage my private systems.