08 avril 2014

Jenkins meets Docker - round 1

I'm investigating Docker usage in a Jenkins context, and would like to report here progress I made so far.



Step 1 : get docker up and running

My development laptop is running OSX, so I had to setup boot2docker. Compared to previous docker vagrant environment, this one is missing (sic) port redirection to host, so you for sure can run a container but can't access it :-\

No panic, you just have to run :

for i in {49000..49900} 
do
   VBoxManage modifyvm "boot2docker-vm" --natpf1 "tcp-port$i,tcp,,$i,,$i"
   VBoxManage modifyvm "boot2docker-vm" --natpf1 "udp-port$i,udp,,$i,,$i" 
done

Not a big deal, but I guess lot's of non-Linux users will search google for this tip. I also recommend you to run boot2docker if you're a Linux user, as it's far simpler to "drop" everything in a virtualbox instance vs cleaning up your system after you made some bad docker experiments.

Right, so docker is up and running on my MacBook. checked

Step 2 : create Docker image for jenkins slave (and use jenkins to build them, what else ?)

First thing I want to do is use Docker to manage my build environment. Jenkins for sure has various automated tools installers, but I prefer to manage this my way, with setup script stored within project SCM. With a Docker, I have a simple way to prepare build slave to match project prerequisites, with full isolation between jobs.

So, I need to setup a docker image to act as a jenkins slave. For this I need it to embed a ssh server - would be nice for jenkins to be able to use docker attach to access container, but I don't think anybody tried this yet.

Docker documentation gives you all necessary information to setup a sshd service, anyway that's not fun enough : as a Jenkins-guy, I want my environment setup to be automated and reproducible !

So, I'm using Michael Neale's docker-build-and-publish plugin to build my Dockerfile. This plugin is designed to ... build and publish docker images. Limited scope, do it well. Think about it as "my own trusted builds infrastructure"

I had to tweak my setup a few as recent docker version changed the behavior for ADD keyword. As I'm not much of a system packages fan, I used to ADD tools as tar.gz from a S3 bucket URL, but now only local files are unpacked by ADD command, so I need to first copy them to workspace so docker will expand them. I wonder docker team made such an error-prone choice, and didn't introduce an explicit EXPAND keyword, or something equivalent.

Anyway, after a dozen broken builds (sic) I got my environment setup and container ready to accept ssh connections to start a jenkins slave.

➜  ~ ssh root@localhost -p 49162
Welcome to Ubuntu 12.10 (GNU/Linux 3.13.3-tinycore64 x86_64)

 * Documentation:  https://help.ubuntu.com/
Last login: Tue Apr  8 11:05:01 2014 from 10.0.2.2
root@f720cc089b6c:~# java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
root@f720cc089b6c:~# 

Step 3 : use docker containers as jenkins slaves

Then I've setup Docker-plugin to use it later for other jobs, running on the same Docker infrastructure - at this time, docker plugin acts as a Jenkins Cloud extension, but it doesn't offer scalability. I expect to find some way to introduce an alternative design so you can get slaves provisioned by IaaS on-demand (like other Cloud plugins do) and run a container on top of it, probably by using a build wrapper ... will see.

Anyway, Docker-plugin already does the job for my initial setup, just need to know it's using a pure java docker client (jDocker, a docker-java fork - Jenkins folks use to fork anything that doesn't accept pull requests within a week), and as such only support http. So don't set your docker URL as tcp://localhost:4243 as I use to set in .bash_profile for OSX development.

I also got various configuration issues and all sort of compatibility bugs that makes the distinction between documentation and reality :) Anyway, I now can run my demo job on this custom slave environment.


[04/08/14 14:10:21] [SSH] Opening SSH connection to localhost:49192.
[04/08/14 14:10:21] [SSH] Authentication successful.
[04/08/14 14:10:21] [SSH] Checking java version of java
[04/08/14 14:10:21] [SSH] java -version returned 1.8.0.
[04/08/14 14:10:21] [SSH] Starting sftp client.
[04/08/14 14:10:21] [SSH] Copying latest slave.jar...
[04/08/14 14:10:21] [SSH] Copied 364 754 bytes.
Expanded the channel window size to 4MB
[04/08/14 14:10:21] [SSH] Starting slave process: cd "/tmp" && java  -jar slave.jar
<===[JENKINS REMOTING CAPACITY]===>channel started
Slave.jar version: 2.36
Ceci est un esclave Unix
Evacuated stdout
Slave successfully connected and online