Quality assurance (QA) in coding is often associated with writing applications. Coding (or automating common tasks using a structured language) however is by far not longer restricted to writing software applications. With the rise of the tooling for operations and the establishment of the DevOps culture, writing code is being done for e.g. launching your infrastructure on Amazon Web Services (Terraform), building and configuring your run time environment for your application (Docker) or managing your cluster (Kubernetes).
For code used in applications, QA is accepted as being a best practise. We lint our code to coding standards, write unittests, generate documentation and implement integration tests etc. For example Dockerfiles are often being written using “does it build ” Development or DIB. And strangely enough, Docker containers and the originating Dockerfiles are being used in state of the art (automated) Continuous Delivery pipelines without any proper QA. My advice is stop doing DIB Development and start ensuring the quality (and consistency) of your Dockerfiles.
Validating (linting) Dockerfiles
The simplest way of managing the quality of your Dockerfile is linting the Dockerfile. This will take you approximately 10 seconds using hadolint:
This will run the docker linting tool with about 50 rules applied.
Example output is displayed below:
Ensuring the quality of your code can be taken a step further by using for example rspec and serverspec.
Rspec is a BDD tool for Ruby developers which has a strong focus on facilitating test driven development. Serverspec is a suite which runs on top of rspec specifically written for testings server configurations. With using the ruby docker-api library, both are excellent for writing tests cases for your Dockerfile which ensures that your Dockerfiles matches the contract with your application. Using these tools, you can do this fully automated in a CD pipeline.
Running these tests can take significant more time as linting, because the actual docker container will be built and started.
The total built time depends on many factors, like has the image built before (and thus is likely to be cached), network speed, cpu power (compilation speed) and so forth.
The Rakefile is used as a testrunner for your rspec tests.
It will execute all files matching *_spec.rb in the tests/spec directory.
The basic configuration options for rspec can be set in a helper file, spec_helper.rb:
This file will be included by using the required keyword in top of the files containing your actual tests.
For those tests, it is advisable to split the tests in those which needs only the docker image to be built and in those which needs a running container.
Like many testsuites, rspec allows you to wrap your tests in a setup and teardown structure. Splitting the tests like this, will keep this setup and teardown structure simple.
For a simple docker container running Ubuntu with Apache installed, the following Dockerfile is created:
On the dockerfile itself we could test if ports 80 and 443 are exposed and that /etc/apache2 is declared as volume to allow easy override of the apache configuration . To test the Dockerfile an image is built using the ruby docker api.
On the actual running container we could check if we run the expected version of Ubuntu, that apache is properly installed and we are able to connect to port 80.
Port 443 should not be enabled by default, so this is checked as well.
Running the tests is done by calling rake:
Exceuting this command will give the following output: