Reproducible Builds with Docker

Reproducible Builds with Docker

Wiki’s and Readme files are the most common ways to document a build. While documenting a build is better than not documenting it, Wikis and Readme files have two flaws when used to describe a process: 1) they require humans to read them, and 2) they evolve.

Of course the fact that Wikis evolve is often seen as their biggest strength. However, when trying to reproduce an out-of-date process, up-to-date Wikis are of little help. For example, building J2V8 first requires V8 binaries, and not just any version of V8 either. J2V8 requires V8 version 3.26. Building V8 has changed significantly since 3.26 and the documentation has evolved over time. Finding an accurate set of build instructions — and all the dependencies for V8 3.26 — is a challenge even Stack Overflow can’t help with. Sometimes the documentation was tagged with the release, but setting up a system as it was last year is no easy task. Luckily when we first started this, we recorded the V8 build instructions as a Dockerfile.

docker

By recording a build as a Dockerfile anyone can build your software with a single command. By checking the Dockerfile into your git repository, the build steps for a particular version can be archived forever.

A Dockerfile not only describes the build steps, but also describes the system image required to build the software. This includes toolchain & their versions, libraries, environment variables and even the disk layout.

To experiment with this, clone the J2v8 repository from github and execute docker build from within the v8build directory:

% git clone https://github.com/eclipsesource/J2V8.git
% docker build --rm=true --no-cache -t "eclipsesource/v8-build" .

To make this even easier, the docker build was wrapped in a script that also copies the artifacts from the docker container once the build is completed using the docker cp command:

% docker cp v8build:/data/v8_3_26/out .

The J2V8 Dockerfile

Let’s review the Dockerfile:

FROM ubuntu:14.04
MAINTAINER EclipseSource 

The first line instructs Docker to use Ubuntu:14.04. While V8 may build fine on newer versions of Ubuntu, the key to these instructions is reproducibility, and we’ve done our testing on Ubuntu 14.04. Unless an explicit decision has been made to upgrade the OS, we will stick with this — feature for feature, bug for bug.

# update and upgrade
RUN apt-get update && apt-get upgrade -y && apt-get clean
# install standard toolset
RUN apt-get install -q -y git subversion make gcc bzip2 python g++ libc6-dev-i386 g++-multilib openjdk-7-jdk

A set of system dependencies are then installed — this includes svn (V8 now uses git, but we are building from their historic repo using their old SVN tags). The -y is used so the system doesn’t prompt us during the build.

ADD https://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin ./
RUN chmod a+x android-ndk-r10d-linux-x86_64.bin
RUN ./android-ndk-r10d-linux-x86_64.bin
ENV ANDROID_NDK_ROOT /android-ndk-r10d

The Android NDK is then fetched, extracted and an environment variable is set.

RUN mkdir /data
RUN cd /data && svn checkout https://v8.googlecode.com/svn/branches/3.26 v8_3_26
ENV CCFLAGS -fPIC
ENV CXXFLAGS -fPIC

The build directory is created and V8 3.26 is cloned. A few GCC flags are then set as environment variables.

# Build
RUN cd /data/v8_3_26 && make dependencies
RUN cd /data/v8_3_26 && make native i18nsupport=off
RUN cd /data/v8_3_26 && make android_arm.release i18nsupport=off
RUN cd /data/v8_3_26 && make android_ia32.release i18nsupport=off

Finally the build is performed. Newer versions of V8 don’t use this approach as a new build tool is now used. However, 3.26 built the dependencies as part of make dependencies target. This build will result in linux bits as well as Android ARM and Android x86.

Go ahead and give it a try. You can even build this on MacOS or Windows by first installing boot2docker. If you run the v8Build.sh script, the results will be copied from the container afterwards. Next I’ll document how I do the J2V8 build.

For more Tips and Tricks on Eclipse, Tabris.js and updates about J2V8, follow me on twitter.