Building Docker images on Travis.ci

Olá!

Inspired by the posts from Viktor Adam's blog, when I have some spare time I have been playing with Docker and some open source tools to build this blog.

So far I have my two little devices a Raspberry Pi and a Rock64 hosting this blog, yes, that's right, you're reading this straight from a Ghost blog behind an NGinx hosted at my home, be nice and say hi!

Allan's home devices

Appart of some details like sensible public data management and external CI usage to generate and publish Docker images that is the subject of this post, this is how my stack looks like right now. It will evolve soonish :]

Initial home stack

Sensible public data

As we can see from the description of this repo of mine on Docker hub, some environment variables are expected as parameters to create containers. Some sensible data like Cloudflare API key goes to a public repository on Github, the .env file in binary form instead of row text.

I could keep it somewhere on my local file system and use it to create containers but if I've learned something from past events is, maintaining files on my machine is the same of losing them sooner or later so, better to have them on the cloud where smarter people than me are taking care of backups.

However, how to keep this kind of data safe in a public space? For git repositories, a good option is to use Git Crypt.

Git Crypt

First, install it, following this guide.

Once you have installed it you need a key to lock and unlock the files you want, there are two options, the Symmetric Mode where you export a key and refer it to unlock your files and GPG Mode where you create a key and import the public key wherever you need to unlock files. I have decided to use Symmetric Mode, this time "after few disappointments with the GPG Mode". The setup is easy and does not require further steps after exporting the key.

Setting up git-crypt and exporting a symmetric secret key

Now on the git repository initiate, git-crypt like with a regular git init and export your symmetric key.

git-crypt init
git-crypt export-key /lab/security/git-cript-key

Now we need to create the .gitattributes at the root of the project and list the files to be encrypted, the syntax is the same used with .gitignore e.g: *.env filter=git-crypt diff=git-crypt

From this point .env will be automatically encrypted before being pushed to the repository. To unlock it in different machines, we need to run git-crypt unlock referring the secret key that we have just exported, in my case git-crypt unlock /lab/security/git-crypt-key

If the intention is to unlock this files somewhere else, is necessary to have access to this key from this other place too, the process is the same, unlock the files with the same command above.

Setting up a Trevis.ci account

At this point, we probably have something like that on your GitHub. The next step is to build images and publish them automatically when updating the repository.

Using a GitHub account, Sign Up to Trevis.ci and enable the integration for this repo.

Setting up the .travis.yml file

To tell Travis what to do, we need a .travis file at the repository root, to learn about it here to create one that works for you. Mine looks like that:

sudo: required

services:
- docker

script:
# setup QEMU
- docker run --rm --privileged multiarch/qemu-user-static:register --reset
# build images
- docker build -t ddns:$DOCKER_TAG -f Dockerfile.$DOCKER_ARCH .
# push images
- docker login -u="$DOCKER_HUB_LOGIN" -p="$DOCKER_HUB_PASSWORD"
- docker tag ddns:$DOCKER_TAG allandequeiroz/cloudflare-ddns:$DOCKER_TAG
- docker push allandequeiroz/cloudflare-ddns:$DOCKER_TAG
- >
  if [ "$LATEST" == "true" ]; then
    docker tag ddns:$DOCKER_TAG allandequeiroz/cloudflare-ddns:latest
    docker push allandequeiroz/cloudflare-ddns:latest
  fi

env:
  matrix:
  - DOCKER_TAG=arm       DOCKER_ARCH=arm       LATEST=true
  - DOCKER_TAG=amd64     DOCKER_ARCH=amd64

The environment uses a Raspberry Pi and Rock64, so is necessary to build images for arm architecture, and in case someone needs it in for an amd architecture, let's generate an amd one too, for a good karma sake.

You can ask Travis to do that defining the matrix section, this way the script part will be executed once for each line of the matrix, in this case, every time I push something new to GitHub, two new images will be generated and pushed to Docker hub.

Another interesting detail here is the ability to define environment variables, so we can push images to docker hub for example, without exposing credentials docker login -u="$DOCKER_HUB_LOGIN" -p="$DOCKER_HUB_PASSWORD"

Travis provides a settings interface where you can define environment variables and use them instead of keeping it public on your repository.

Right. Now we need to push something new to the repository or Trigger the build from More options on Travis interface, by the end we have our images ready to be pulled from Docker hub.

Travis badges

After all this effort we deserve some badges, we can get them straight from the Travis account, just point to the .svg file related to that build. Travis update it after each build so take care not to break the build :)

https://api.travis-ci.org/allandequeiroz/cloudflare-ddns.svg

Microbadger badges

To have some badges from your Docker hub account you can use Microbadger, once again Sign Up using your GitHub account and link it to your Docker Hub account, after few seconds you'll have some badges waiting for you, in this case, version the architecture and layers amount of layers of your image.

https://images.microbadger.com/badges/version/allandequeiroz/cloudflare-ddns.svg
https://images.microbadger.com/badges/image/allandequeiroz/cloudflare-ddns.svg

Showing off the badges

In the end, we can use something like the lines below to display badges on the README.md files.

[![Travis](https://api.travis-ci.org/allandequeiroz/cloudflare-ddns.svg)](https://travis-ci.org/allandequeiroz/cloudflare-ddns)

[![](https://images.microbadger.com/badges/version/allandequeiroz/cloudflare-ddns.svg)](https://microbadger.com/images/allandequeiroz/cloudflare-ddns "Get your own version badge on microbadger.com")
[![](https://images.microbadger.com/badges/image/allandequeiroz/cloudflare-ddns.svg)](https://microbadger.com/images/allandequeiroz/cloudflare-ddns "Get your own image badge on microbadger.com")

[![](https://images.microbadger.com/badges/version/allandequeiroz/cloudflare-ddns:amd64.svg)](https://microbadger.com/images/allandequeiroz/cloudflare-ddns:amd64 "Get your own version badge on microbadger.com")
[![](https://images.microbadger.com/badges/image/allandequeiroz/cloudflare-ddns:amd64.svg)](https://microbadger.com/images/allandequeiroz/cloudflare-ddns:amd64 "Get your own image badge on microbadger.com")

Travis

comments powered by Disqus