Validate your Nginx configuration files easily with Docker

April 17, 2018 0 Comments

Validate your Nginx configuration files easily with Docker

 

 


This is my first post, please be indulgent and let me know if anything could be improved.

Situation

Let's suppose you have your web servers running any version of Nginx, and you are set up for automatic deployment of the Nginx config files (through Jenkins, StriderCD, TeamCity, Travis CI, Strider CD, or any other CICD tool you like) from a Git repository or any other source.

With that setup, everything runs smoothly until someone pushes a modification to the config files that has typos or errors in it, in which case you don't want these files to ever get to the Nginx servers.

To avoid such a situation, you'd want your validations to occur as soon as possible in the update process.

This happened to us a few times, so I decided to write a small script that would validate the nginx.conf files prior to allowing the deployment.

First steps

The first thing we wanted to do was to be able to validate the Nginx config files from a server with Nginx. That was pretty easy to do with this command:

nginx -c /etc/nginx/nginx.conf -t

With valid config files, it returns this:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 
nginx: configuration file /etc/nginx/nginx.conf test is successful

With invalid config files, it returns something like this:

2018/04/13 21:26:15 [emerg] 1#1: unexpected ";" in /etc/nginx/nginx.conf:155 
nginx: [emerg] unexpected ";" in /etc/nginx/nginx.conf:155
nginx: configuration file /etc/nginx/nginx.conf test failed

Dockerizing this validation

However, this requires that the person editing the config file had Nginx installed on its machine. This is not always the case, and we didn't want to install Nginx on the build server either (there could be multiple versions on different servers too...), so we turned to Docker as we already use it a lot.

After a few minutes, we were able to come up with a similar command that could run from every system that has Docker installed:

docker run --rm -t -a stdout --name my-nginx -v $PWD/config/:/etc/nginx/:ro nginx:latest nginx -c /etc/nginx/nginx.conf -t 

Docker command explained briefly:



  • --rm : Removes the container after execution completes


  • -t -a stdout : Outputs the container logs on the standard output


  • --name my-nginx : Name of the docker container


  • -v $PWD/config/:/etc/nginx/:ro : Maps the config subfolder to Nginx config folder inside the container


  • nginx:latest : Nginx image version to use from hub.docker.com


  • nginx -c /etc/nginx/nginx.conf -t : Nginx command to validate nginx.conf file

There might be some adjustments required for it to run on Docker for Windows

This assumes you have the following folder structure:


  • ./

  • ./config

  • ./config/nginx.conf

With that, everyone could run this command in the parent folder of the config directory and see if their nginx.conf file is valid or not.

Making it simpler with a bash script

Though that was already a good start, we wanted to make it so that we get a SUCCESS or a FAILED message, whether the config file was valid or not. We also wanted to be able to specify a more dynamic version for the Nginx docker image and mostly, didn't want to remember all this command.

Here is what we ended up with in a file called checkNginx.sh:

#!/bin/bash 
rootPath=$1
nginxVersion=1.13 # Could also be passed as an argument using $2 result=$(docker run --rm -t -a stdout --name my-nginx -v ${rootPath}/config/:/etc/nginx/:ro nginx:$nginxVersion nginx -c /etc/nginx/nginx.conf -t) # Look for the word successful and count the lines that have it
# This validation could be improved if needed
successful=$(echo $result | grep successful | wc -l) if [ $successful = 0 ]; then echo FAILED echo "$result" exit 1
else echo SUCCESS
fi

This script can be called using the following command:

bash checkNginx.sh $PWD

It outputs SUCCESS if everything is ok or the following if there is an error:

FAILED 
2018/04/13 21:26:15 [emerg] 1#1: unexpected ";" in /etc/nginx/nginx.conf:155
nginx: [emerg] unexpected ";" in /etc/nginx/nginx.conf:155
nginx: configuration file /etc/nginx/nginx.conf test failed

Then we were able to run this same command from the build server, at the Test phase of the deployment process and abort the deployment of the configs completely when a Nginx config file had a typo or an error in it.

This could also have been added to a pre-commit or pre-push Git hook for the repository keeping track of these configs, but so far we didn't feel the need to do so.

Thanks for reading, hope you appreciated :)


Tag cloud