Package Cloud Foundry java-buildpack with Docker

How I used Docker to package the CF java-buildpack in minutes

Just last week I found myself in the situation were I needed to package the Cloud Foundry Java Buildpack.
Here is why I chose Docker to package the buildpack and what was necessary to get it done both on Linux and on Windows 7 using Docker Toolbox.

Why package your own buildpack?

So why package your own buildpack you might ask yourself? I mainly had two reasons.
As you might know a Cloud Foundry buildpack is a package that is as minimal as possible and is configured to connect to the network for all dependencies1. In my target Cloud Foundry environment there is no unrestricted internet access, so I need an offline package anyway that platform ops will then make available through the cf create-buildpack command.
Furthermore I need to customize my buildpack, more specifically a configuration for the AppDynamics agent that needs to go inside my app’s containers.

Why build with Docker?

I don’t use ruby, thus I don’t have it installed. So I can’t simply run the commands the maintainers of the Cloud Foundry Java Buildpack specify here.
Since I won’t use ruby in the foreseeable future, I don’t want to invest the time to properly install it on my host system.
One of my favorite usecases for Docker is to run disposable containers to build sources with the build-environment they require without the need to manage several build-environments on the host machine directly.
So choosing Docker for this occasion seems natural to me.

Package java-buildpack with Docker

So first things first. Let us grab the java-buildpack and checkout a version tag.

git clone https://github.com/cloudfoundry/java-buildpack.git
git checkout v4.6

The next step for me was to customize the buildpack. So I added my custom-interceptors.xml in resources/app_dynamics_agent.

Build with a single command on Linux

When on Linux (running Docker directly rather then inside a VM you connect to with Docker Machine, like when using Docker Toolbox) just do this:

docker run --rm -v "$PWD":/usr/src/java-buildpack -w /usr/src/java-buildpack ruby:2.2.8 /bin/bash -c "bundle install; bundle exec rake clean package OFFLINE=true PINNED=true"

The /bin/bash -c ... part is to run multiple commands, as described here.
If you use Linux: Congratulations, you’re done!

Avoid the pitfalls on Windows

When using Windows 7 you are forced to use Docker through Docker Machine, which is installed for you with Docker Toolbox.
However the above mentioned command won’t run successfully on Windows using Docker Toolbox.
The reason is that if you are using Docker Machine on Mac or Windows, your Docker daemon has only limited access to your OS X or Windows filesystem2. But we can work around that.

First, before performing any Docker commands connect the Docker cli on your host with the Docker-Machine, which looks something like this:

docker-machine start
docker-machine env
eval $("C:/Program Files/Docker Toolbox/docker-machine.exe" env)

Your path to docker-machine.exe might be different. Make sure to use the path the docker-machine env output is telling you.
Now make sure you have git cloned java-buildpack somewhere in C:\Users\<Your_Username>. So as an example let’s say you cloned to C:\Users\USER\java-buildpack.
In that case the following command will work on Windows and package the Java Buildpack for you:

docker run --rm -v /c/Users/USER/java-buildpack:/usr/src/java-buildpack -w /usr/src/java-buildpack ruby:2.2.8 /bin/bash -c "bundle install; bundle exec rake clean package OFFLINE=true PINNED=true"

Docker saves the day

So once again Docker is really useful in helping me build source code written in languages I actually don’t use and thus don’t have the proper tools for. Instead of spending time to find out if and how I can install Ruby or rbenv I can quickly jump into building the package I need and move on with working on our own application’s source code.

Leave a Reply