Docker
Use Docker to configure, compile, and test.
Background
The provided Dockerfiles will build two Docker images:
- CMake and gcc
- CMake, gcc, and CppUTest
These can be used to easily compile both production and test code.
The source and build directories are bind-mounted to the container. This allows source code changes to be made on the host and easily compiled in the container. It also allows the build results that are generated by the container to persist after the container is stopped.
Prerequisites
- Docker v17.05+
Setup
Before you can run a Docker container, you need a Docker image. Either pull an image from DockerHub or build your own.
Pull Docker Image
Pull a pre-built image from DockerHub:
$ docker pull kevinwmatthews/gcc-cmake:8-3.13.1
$ docker pull kevinwmatthews/cpputest-gcc-cmake:v3.8-2b45d38
I like to tag each image with a name that is easy to remember:
$ docker tag kevinwmatthews/gcc-cmake:8-3.13.1 cmake
$ docker tag kevinwmatthews/cpputest-gcc-cmake:v3.8-2b45d38 cpputest
Build Docker Image
The syntax for building a Docker image is:
# docker build --tag <image_name> <relative/path/dir/with/Dockerfile/>
Specify the directory that contains the Dockerfile, not the Dockerfile itself.
I prefer to tag the image very specifically in order to track changes and then generate a user-friendly tag for use at the command line:
$ docker build --tag gcc-cmake:8-3.13.1 Dockerfiles/cmake/
$ docker tag gcc-cmake:8-3.13.1 cmake
$ docker build --tag cpputest:v3.8-2b45d38 Dockerfiles/cpputest/
$ docker tag cpputest:v3.8-2b45d38 cpputest
Run Docker Container
A docker image can be run simply using docker run <image_name>
, but we want to
customize several aspects of this container. In particular, we want to be able
to run both test and production builds.
This repo features two example .env
files, one for production and one for testing:
- test.env.example
- production.env.example
Copy and edit each to be appropriate to your system.
The generic command for starting a container is:
# ENV_FILE=<env_file> ./docker_run.sh <image_name>
Test Build
Create a .env
file for testing:
$ cp test.env.example test.env
Edit this file to be appropriate to your system. Note that Docker requires absolute paths.
Run the container with:
$ ENV_FILE=test.env ./docker_run.sh cpputest
Once inside the container, configure using:
$ cmake ../cpputest_intro
This project will compile unit tests by default.
Compile with:
$ make
CMake will run all test suites with:
$ ctest
# or
$ make test
To run individual test executables, run:
# ./bin/<test_executable>
$ ./bin/test_cpputest_intro
I prefer to colorize the tests’ output with:
$ ./bin/test_cpputest_intro -c
When finished, stop the container using:
$ exit
Production Build
It is important to distinguish between test and production builds. Unit tests often override behavior of production code with mocks, custom functions, and memory leak checks. This configuration uses a separate build directory for production builds to ensure that test code is kept separate.
Create a .env
file for production:
$ cp production.env.example production.env
Edit this file to be appropriate to your system. Note that Docker requires absolute paths.
Run the container with:
$ ENV_FILE=production.env ./docker_run.sh cmake
You can also build with the cpputest
image, but using the cmake
image
guarantees that no test code can accidentally be shipped.
Once inside the container, configure using:
$ cmake ../cpputest_intro -DCOMPILE_TESTS=OFF
Note that unit tests are explicitly disabled.
Compile with:
$ make
This project illustrates unit testing on a library so there are no production executables to run.
When finished, stop the container using:
$ exit