Docker CI

This article describes how-to use RSpec and circleci for continuous integration, testing, and deployment of your docker image .


We use dockerenv-apache for all our web development work. It supports lots of development tools needed by our developers including several versions of PHP. There are some differences, however, in how the the supporting software is installed and configured based on the specific PHP version. This lead to issues where some libraries or modules were missed or not configured on other versions of php. Example: xdebug module worked fine on php55 but wasn't loaded on php53. There was no real easy way to test this other than build, spin up the container and manually test the new feature that was added. And of course, that leaves out any regression testing. The result? Developer frustration and wasted time. We needed a testing solution...

Docker Image Testing Solution

Rspec + serverspec + docker-api


  • docker 1.5 (maybe other versions work?)
  • ruby 2+
  • rubygems and the following gems:
    • rspec
    • serverspec
    • specinfra v2.12.7
    • docker-api (although the name required in the spec is actually docker... weird)
    • rake
    • yarjuf - only if you want junit reports back
    • coveralls - only if you want to integrate with coveralls

The Setup

/Dockerfile - Our dockerenv-apache Dockerfile we're testing against

.rspec - rspec config

/Gemfile - gem requirements

/Rakefile - task runner

/spec/spec_helper.rb - load in requirements

/spec/localhost/Dockerfile_spec.rb - Your tests. This is where the magic happens

Run test

Simply run rake spec from the project root


What's going on here?

All the magic happens at the top of the spec file:

require "serverspec"

gives us the ability to RSpec tests for checking server configurations

require "docker"

let's us access docker from our spec

image = Docker::Image.build_from_dir('.')

builds the image to let us run our tests agains

set :backend, :docker

sets serverspec backend to use docker (there are many backends you could use such as ssh, exec, etc)

set :docker_image,

sets the image that we just built to use for the tests

For more information on the test syntax, head over to's resource types

Taking it one step further

Continuous Integration testing with CircleCI

We now have a way to test our server image. The next step is to automate this so we can run these tests every time we commit a change. CircleCI allows us to build and use custom docker containers. Great! But there are 2 gotchas.

  1. They use LXC which doesn't support for the docker exec command. The work-around is to use gem 'specinfra', '2.12.7' specific version in your Gemfile. The newer versions run faster (since it uses docker exec rather than spinning up multiple containers) but will break on CircleCI.

  2. They use the btrfs and don't support docker rm. You'll get the following error Failed to destroy btrfs snapshot: operation not permitted. The workaround is to add the following lines at the top of your spec test file

Here is our circle.yml file:

Extra Credit

Add Coveralls Support

For fun, we added code coverage support to our /spec/spec_helper.rb file for future use. You can see the results here:

Trigger a Dockerhub build

  1. Uncheck "Active" on your automated build
  2. Turn on remote build trigger and copy the URL
  3. Create a new private env var in CircleCI containing the URL
  4. Make the appropriate curl request in a script for deployment


blog comments powered by Disqus
· By: