Building a Docker Image for BitBucket Pipelines
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 |
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.