Jenkins in a Linux Container (Part 1)

Running Ubuntu 15.10 I wanted to get some experience on Linux Containers. Since Containers look like a nice solution for deployment, I thought to combine it with a real use case to run Jenkins (software for Continuous Integration) in a container. So first some explanation on Linux Containers followed by an introduction on Jenkins and then the real work. If you have other intentions for using a container, most of the information for creating the container can be reused.

Linux Containers

LinuX Containers also known as LXC, is a lightweight method of virtualizing Linux OS instances. The difference with Virtual Machines (VM) is that it will not virtualize a complete machine, including emulating the complete hardware, but instead uses one Linux kernel. The host kernel allows it to run so called containers, this makes it comparable fast to running it bare metal, whereas the VM is slower because it virtualizes a complete machine. VM is a nice option for running none Linux operating systems or systems with different kernels.

So what is the difference between Linux Containers vs. Docker? Since nowadays Docker is mentioned often. Docker and LXC both provide containers and are based on similar foundations. However, Docker only allows to run one process a container, whereas LXC allows multiple processes. Configure a Docker has to be conducted via their app and they use some methods to make it work for one process only. This makes the configurability of the container limited, therefore LXC has my preference.

To show the difference take the use case of running a WordPress website on Docker. It will require multiple images to run the services required by WordPress, one for Apache one for Mysql and one for Phpmyadmin. Whereas with a LXC it requires only one container. For more info on LXC vs. Docker see the explanation on Flockport.

Jenkins

As Continuous Integration becomes the norm, one of the most widely open-source and free used framework to automate building and integrating is Jenkins. It is based on Java and therefore supports multiple platforms. It comes with nice features and plugins, it supports among others Git, SVN (Version Management), has a Cppcheck and Valgrind plugin easy for embedded systems development and is configurable via a web interface. For this experiment we will be installing Jenkins version 2.0, which is currently a beta version.

The installation

There are two ways of running a container, privileged and unprivileged. The privileged containers uses root rights to run the container, whereas the unprivileged can be run by a normal user (non-root). Unprivileged containers are more limited, but are less of a threat to the host (security).

In the case of running Jenkins on a LXC, I choose for the safer option of an unprivileged container. To understand how unprivileged containers work, a little explanation on user namespaces is necessary.

User namespaces

Linux kernel with user namespaces

Linux kernel with user namespaces

User namespaces are used to let non-root users administer and create containers. When running Linux, users are registered with an userid (uid) and belong to certain groups with a groupid (gid). In Linux kernels lower than 3.8 there was only a single data structure for registering users and group relations. As of kernel 3.8 user namespaces were implemented. This can be thought of a nested data structures for users within a new namespace. You can have multiple namespaces, which are virtual spaces each beginning with uid and guid 0. Outside the namespaces the uids and guids are mapped to existing uids and gids on the host. See the diagram on the left for an example.

These user namespaces make it possible to administer Linux Containers. To add an user to a certain group in the Linux Container, requires root privileges only in the Container and not on the host therefore user namespaces were invented. In the Linux host a range of userids are allocated per host user to support this functionality. So far the theory.

Ready to install?

Installing packages in Ubuntu, is easy, with apt-get install in the terminal. To install LXC:

For creating unprivileged Linux Containers it is necessary to create a default config file in ~/.config/lxc/ this is in the home directory of the user, in my case the user embedwise:

The file default.conf looks as follows:

Looking at the first configuration rule it maps the userids of the name space, ‘u’ indicates userid, 0 is the first userid seen in the username space of the container. Next 100000 is the userid as seen on the host, Followed by the range of consecutive ids to map, namely 65536. For more explanation on these settings you can look at the man page, or type man lxc.container.conf in the terminal.

In a systemwide config file /etc/lxc/lxc-usernet, we need to make sure that the user is allowed to use the network link.

The file /etc/lxc/lxc-usernet looks as follows:

Replace embedwise with your user name. This row describes that the user embedwise can connect 2 veth (virtual ethernet) devices to the bridge lxcbr0. In other words the user embedwise can run two containers simultaneously with an ethernet connection, feel free to increase the number.

After editing these files we can finally start making and running a container:

It shows an interactive menu, where you can select a Distribution, Release and Architecture. If you already know what you want you can use a single command:

In order to run the container it was also necessary to change the rights of the ~/.local directory:

To start the container, login to the terminal of the container and to change the root password execute the following:

Provide your password for the root account of the container. In order to install Jenkins, download the Ubuntu/Debian package from the Jenkins website. I chose for beta version 2.0 to try it out.

When you try to install Jenkins with dpkg it will show a message that is misses some dependencies, with apt-get install -f it will install these dependencies for you, run dpkg again to finalize the installation. After the installation of Jenkins it also created an user called jenkins under which Jenkins is running. Use ifconfig to find out the IP address of the Linux container.

Now go back to your host system and run a web browser and use the IP address you found, including the port number 8080, in my case 10.0.3.181:8080.

You will see a web page “Getting Started, Unlock Jenkins”, this means Jenkins is running inside the container and can be reached from the host system, which is pretty cool! In part 2 we will go into more details of setting up Jenkins and running a simple build script. If there are any questions please feel free to leave a comment under this blog.

Leave a Reply

Your email address will not be published. Required fields are marked *