This post outlines one way that I’ve found to spin up an application in Docker for testing on Travis CI. I use this style of testing for a web-based word puzzle generator, such that every code change is deployed to a test environment and automatically tested in a web browser before it is merged. This setup will be most applicable to web application developers who use GitHub.
I got the idea for writing this from a few lines in the docker-compose documentation, which suggested that Docker is an easy way to perform automated testing over a running application:
$ docker-compose up -d
$ docker-compose down
This snippet was missing some setup and an example app, but these three lines do all the heavy lifting.
The Docker setup
In order to focus on the Docker setup, I made a server which simply responds to TCP requests on port 5000 with the text “Hello World”.
This file is called server.sh, and sits in a directory called foo_server:
while true; do
# Send 'Hello World' to anybody who connects on port 5000
echo "Hello World" | nc -l 5000
Alongside it, I added a Dockerfile to instruct docker to execute this tiny ‘application’ in a container, after installing the dependencies. This machine is built from the Docker-official Debian image:
ADD . /usr/share/test-server
RUN apt-get update && apt-get install --assume-yes netcat-openbsd
Lastly, a .dockerignore file is used to avoid loading the Dockerfile to the container:
# Ignore docker files
In the directory above, a simple test script, test.sh is used to see that the server is returning the expected output:
actual=`nc -v localhost 5000`
echo "Expecting: $expected"
echo "Server says: $actual"
if [ "$expected" != "$actual" ]; then
echo "Test failed"
echo "Test passed"
Alongside the test file, a file called docker-compose.yml instructs Docker to create a container out of the foo_server example, and forward port 127.0.0.1:5000 to it.
To try it out for yourself, you need a relatively recent version of Docker and docker-compose. The versions provided in Debian were not new enough to execute the examples, but the Docker project provides repos containing newer builds for Debian & Ubuntu. For my distro, the install was:
curl -sSL "https://get.docker.com/gpg" | sudo -E apt-key add -
echo "deb https://apt.dockerproject.org/repo debian-stretch main" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install docker-engine
sudo pip install docker-compose
The versions this got me were docker 1.11.2, and docker-compose 1.7.1. Straight after the install, I could deploy & test an example locally:
$ docker-compose up --build -d
$ docker-compose down
The CI setup
I’ll assume that if you’re reading this, you are familiar with the basics of Travis CI. The large block of code below is the .travis.yml file to set up the test machine, then execute the tests against a container.
# Use Ubuntu 'trusty' distribution
# Update docker-engine using Ubuntu 'trusty' apt repo
curl -sSL "https://get.docker.com/gpg" |
sudo -E apt-key add -
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" |
sudo tee -a /etc/apt/sources.list
- sudo apt-get update
sudo apt-get -o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" --assume-yes install docker-engine
- docker version
# Update docker-compose via pip
- sudo pip install docker-compose
- docker-compose version
- docker-compose up --build -d
- docker-compose down
Note: This uses Travis CI’s trusty distribution, which at the time of writing is the newest stable build platform available on Travis CI. This shipped an outdated version of Docker, which had to be installed over. Because the existing Docker was configured, I had to override a debconf prompt, which is why the apt addon syntax was not used to set up dependencies.
The build result for each commit is displayed in Travis CI:
Under this, the output of the passing test script is shown, showing what has been set up:
Using this setup in practice
Moving this from a demo setup to a real setup would be fairly simple:
- Replace the installation with a real software stack
- Replace the server run with a command to serve the application (such as a Apache HTTP, Tomcat or Node)
- Replace the tests with real tests (such as Cucumber or Selenium).
The example in the pre-amble installs a LAMP stack and tests it with Selenium in its CI build.
If your application is a bit larger, your only extra complexity will come from running multiple containers with docker-compose.
Get the code
All of these scripts in a working CI example are available on GitHub: