I said in my last posting that I could do better with cutting down the build time. To get everything working I needed to add a lot of tasks to the BitBucket pipeline. Besides the execution time, BitBucket also needed to download the Docker Image every time, so the Docker Image size is also a factor in the overall build time. Let’s look at some things we can do to make a better Docker image to cut down the build time for the blog.

Let’s find a new base Docker image to work with. The ruby:2.1.7 is about 273 MB, the image is based on Ubuntu and comes with a lot of extra things we do not need, if we use something like the Alpine Docker images we start with a base image of 2 MB. The advantage of using an Alpine Docker image is we still have a package management system we can use at the reduced size. This will give us a good start and cut down the time needed to download the Docker image onto BitBucket systems.

So, we are starting with a clean image meaning we need to install ruby, nodejs, and java. Luckily we can just use Alpine’s package management system to install ruby and nodejs. Sadly, Java is a bit more of an issue because it needs additional packages to be installed, so after doing some online research I found a posting from Atlassian’s blog about installing Java on Alpine, https://developer.atlassian.com/blog/2015/08/minimal-java-docker-containers. I made some changes as the posting was a bit old and some packages have been moved around. You can see the final result below. One last thing I did to help cut down on the build time was pre-install all the needed Ruby Gems. This was done by copying the Gemfile and Gemfile.lock and running bundle install.

After creating the Dockerfile, I saved it into the same repository as my blog and added the repository to Docker Hub to build the image.

Here is the full Dockerfile,

FROM alpine:3.2
MAINTAINER Anthony Scotti <anthony.m.scotti@gmail.com>
# Install base packages
RUN apk update
RUN apk upgrade
RUN apk add curl tar ca-certificates bash build-base libffi-dev
RUN curl -Ls https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.21-r2/glibc-2.21-r2.apk > /tmp/glibc-2.21-r2.apk
RUN apk add --allow-untrusted /tmp/glibc-2.21-r2.apk
# Java Version
ENV JAVA_VERSION_MAJOR 8
ENV JAVA_VERSION_MINOR 45
ENV JAVA_VERSION_BUILD 14
ENV JAVA_PACKAGE jdk
# Download and unarchive Java
RUN mkdir /opt && curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie"\
http://download.oracle.com/otn-pub/java/jdk/${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-b${JAVA_VERSION_BUILD}/${JAVA_PACKAGE}-${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-linux-x64.tar.gz \
| tar -xzf - -C /opt &&\
ln -s /opt/jdk1.${JAVA_VERSION_MAJOR}.0_${JAVA_VERSION_MINOR} /opt/jdk &&\
rm -rf /opt/jdk/*src.zip \
/opt/jdk/lib/missioncontrol \
/opt/jdk/lib/visualvm \
/opt/jdk/lib/*javafx* \
/opt/jdk/jre/lib/plugin.jar \
/opt/jdk/jre/lib/ext/jfxrt.jar \
/opt/jdk/jre/bin/javaws \
/opt/jdk/jre/lib/javaws.jar \
/opt/jdk/jre/lib/desktop \
/opt/jdk/jre/plugin \
/opt/jdk/jre/lib/deploy* \
/opt/jdk/jre/lib/*javafx* \
/opt/jdk/jre/lib/*jfx* \
/opt/jdk/jre/lib/amd64/libdecora_sse.so \
/opt/jdk/jre/lib/amd64/libprism_*.so \
/opt/jdk/jre/lib/amd64/libfxplugins.so \
/opt/jdk/jre/lib/amd64/libglass.so \
/opt/jdk/jre/lib/amd64/libgstreamer-lite.so \
/opt/jdk/jre/lib/amd64/libjavafx*.so \
/opt/jdk/jre/lib/amd64/libjfx*.so
# Set environment
ENV JAVA_HOME /opt/jdk
ENV PATH ${PATH}:${JAVA_HOME}/bin
# Install ruby and ruby-bundler
RUN apk add ruby ruby-dev ruby-io-console ruby-bundler
# Install NodeJS
RUN apk add nodejs
# Clean APK cache
RUN rm -rf /var/cache/apk/*
# Preinstall jekyll and s3_website
WORKDIR /tmp
COPY Gemfile /tmp/
COPY Gemfile.lock /tmp/
RUN bundle install
view raw Dockerfile hosted with ❤ by GitHub

https://gist.github.com/amscotti/bcece7b64231c6d1e9ef1995a5848e03

I updated the bitbucket-pipelines.yml to start using the newly created Docker Image. With this Docker Image, the bitbucket-pipelines.yml becomes a lot simpler now because we no longer need to install anything, it’s now just a task of building and pushing the files to S3.

image: amscotti/jekyll-build
pipelines:
default:
- step:
script:
- bundle exec jekyll build
branches:
master:
- step:
script:
- bundle exec jekyll build
- bundle exec s3_website push

https://gist.github.com/amscotti/9b133eaa192c39f83dcb4c96752a3d15

After all the updates, the image size is now at 135 MB and has more pre-installed software and the build time is at 32 sec, which is down from about 8 mins. So, overall building our own Docker image has been a win! Being able to use any image, including your own, from Docker Hub with BitBucket Pipelines is a really nice feature and one I can see being very useful for building various projects.