Testing Docker images
As part of my OpenALPR Docker image, I had investigated methods for testing Docker images that wouldn’t clutter the Dockerfile with dependencies or test artefacts. The approach I ended up using was creating a Bash script (or PowerShell if you’re so inclined) to start the image and then modify it into a state ready for testing, e.g. copying test data into the container. I thought I’d share what it looks like…
To provide some context around what I was testing; the image comprises of a Python script (the entry point) that feeds photos polled from a URL, which can be enhanced, to an Automatic License Plate Recognition (ALPR) library. The results from the ALPR library are then posted to a URL, and more importantly, printed to the standard output, which is monitored by the tests.
In my implementation, the ./test.sh runs the image, starts a web-server inside of the container (removing the need for an additional image or host dependencies) and then copies the test data to the web-server’s working directory to be served by the polling Python script. The docker logs are then monitored for the expected output.
#!/bin/bash
set -e
set -o pipefail
function find_in_docker_log {
CONTAINER_NAME=$1
TIMEOUT=$2
SUBSTRING=$3
COMMAND="docker logs -f $CONTAINER_NAME"
expect -c "log_user 0; set timeout $TIMEOUT; spawn $COMMAND; expect \"$SUBSTRING\" { exit 0 } timeout { exit 1 }"
}
IMAGE_NAME=single_horizontal.jpg
CONTAINER_NAME=alpr_test
# Start the container
docker run --name $CONTAINER_NAME -d sketchingdev/alpr
http://127.0.0.1/$IMAGE_NAME \ # URL to poll for photo
http://127.0.0.1/ \ # URL to post the results (not used for test)
--verbose \ # Increase verbosity to ensure data that would be posted is printed to stdout
--interval 1 # Small increment to speed up tests
# Run the image with the localhost URL to poll
docker run --name $CONTAINER_NAME -d sketchingdev/alpr http://127.0.0.1/$IMAGE_NAME http://127.0.0.1/ --verbose
# Start web-server to serve test data
docker exec -d $CONTAINER_NAME python -m SimpleHTTPServer 80
# Copy test data to the working directory for Python's HTTP Server to serve
docker cp ./test_files/$TEST_DATA_FILENAME $CONTAINER_NAME:/opt/docker-alpr/
# Wait for license plate to appear in image's output
find_in_docker_log $CONTAINER_NAME $TIMEOUT "WR62XDF"
TEST_RESULT=$?
# Report test status
docker rm -f $CONTAINER_NAME
if [ $TEST_RESULT == 0 ]; then
echo "SUCCESS"
else
echo "FAILED"
exit 1
fi
If you’re interested in seeing it in action, check out the Travis job.