Trivial Travis testing via Docker
05 Nov 2019In this post I’ll show how to use the Travis continuous-integration system to test a project via Docker. This is not a description of building Docker containers using Travis. Specifically, the setup is:
- you have a project on GitHub which contains a Dockerfile specifying how to install your project’s dependencies into a Docker image
- you have some means of building and testing that project within the corresponding Docker container
- you would like this build/test to happen automatically on push.
For background on how to set up the first two steps, see a previous post about Docker.
Travis
Travis is an industry-standard continuous-integration (CI) service that is nicely integrated with GitHub. It can do all sorts of fancy pipelines, but here we’ll just get it to do one simple thing: run a command in a Docker container.
To demonstrate we’ll use the same cowsay-test repository as in the previous post.
This time let’s look at the .travis.yml
file in that repository, which is in YAML format:
language: minimal
services:
- docker
script:
- docker run -t matsen/cowsay-test /bin/bash -c "cowsay hello"
Travis has all sorts of preconfigured machines to run code in a variety of languages. In the first line, we are specifying that we want to use a “minimal” machine, which isn’t designed for a specific language. This image just has a collection of standard tools, including Docker. The second block specifies that we would like to use Docker.
The third and final block specifies what command we’d like Travis to run.
It runs cowsay hello
via bash inside the matsen/cowsay-test
Docker image from Docker Hub.
We can test this locally with a local clone of the repository. If we want to test the whole process, we can execute the
docker build -t matsen/cowsay-test .
command inside the repository, and then copy and paste the docker run
command from the .travis.yml
file (without the leading -
):
docker run -t matsen/cowsay-test /bin/bash -c "cowsay hello"
If we want to test the version that’s on Docker Hub, we can instead do docker pull -t matsen/cowsay-test
rather than the above docker build
command.
To automate this process for any repository, we just need these files committed to our repository, and to:
- set up an automated build on Docker Hub as described previously
- make an account on travis-ci.org, signing in via your GitHub account
- go to https://travis-ci.org/account/repositories and find the repository you want to test
- click on the switch to activate testing of your repository
- click on the hamburger menu button (☰) in the upper right, and select “Trigger build” using the default values
- add a Travis badge (see the cowsay-test repository for an example that makes the badge a link to your build page)
Using quay.io
Docker-the-software is great and very popular. Docker-the-company is struggling somewhat and it shows in that Docker Hub is slow and sometimes unreliable. quay.io is an alternative service that we are starting to use.
If you want to try it out, fork the cowsay-test repository on GitHub then:
- make an account on quay.io
- click on “Create New Repository” on the upper right of your user page
- name your repository in the text box
- Follow the prompts, selecting
- Public repository
- Link to a GitHub Repository Push
- Select your forked repository
- your Dockerfile is
/Dockerfile
as per the help on the right hand side - your build context is just
/
as per the help on the right hand side
- Continue to the page for your build
- Select “Start New Build”
On the Travis side, all you need to do is to add quay.io/
to the start of your Docker image name, like so:
script:
- docker run -t quay.io/matsen/cowsay-test /bin/bash -c "cowsay hello"
Adding Conda
Conda is a great cross-platform package manager that has a lot of traction. You can incorporate Conda as follows, which I’ll describe using the example astronaut-requests repository. This example uses the requests Python library to fetch the collection of astronauts currently in space.
We just need one more file, which is the environment.yml
file.
This file specifies your Conda dependencies.
It’s a helpful file for folks to have in general if they wish to install your software via conda, as they can just execute
conda env create -f environment.yml
and get a Conda environment ready for them. In the example environment.yml file I show how to combine pip and conda.
The astronaut-requests Dockerfile just builds the corresponding Conda environment:
FROM continuumio/anaconda3:2019.07
COPY environment.yml .
RUN /opt/conda/bin/conda env create -f environment.yml
Here we use the continuumio/anaconda3:2019.07
base image (using a specific tag is a good idea to avoid future breakage!).
We then copy the environment.yml
file in from the repository, and use it to make our Conda environment (note that we need to use the full path to conda
).
In our case it creates a Conda environment called requests
.
The astronaut-requests Travis YAML file just gets a tiny bit more complex. I’ll break it down:
docker run -t quay.io/matsen/astronaut-requests
runs commands in theastronaut-requests
container hosted on quay.io as before-v ${PWD}:/astronauts
mounts the current directory (containing the clone of the repository on Travis) as/astronauts
inside the container/bin/bash -c "..."
runs...
as a bash command inside the container/opt/conda/bin/conda run -n requests ...
runs...
inside therequests
Conda environment that we built in our Docker containerpython /astronauts/get-astronauts.py
is the command we are running
If we look at the Travis page for the repository we can see a JSON blob at the bottom with the current astronauts in space at the bottom. Success!
Note: conda run
is not documented as of right now on the online Conda documentation, but it’s lovely and is documented via conda run --help
on your local installation.
Wrap
That’s it! In practice, you’ll want Travis to build and test your code. You can see an example of all of this working in our libsbn repository.
I emphasize that we used Docker as a build environment and that the code is brought in from the outside. If you want to build a Docker container with the code built in, you can push the resulting Docker image to a registry.