DEV Community

Simon Drouin
Simon Drouin

Posted on

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 :)

Top comments (4)

Collapse
 
cleydyr profile image
Cleydyr Bezerra de Albuquerque

One could also take advantage of the exit code from Docker instead of processing the output for validation.

So the script could be somethings like this

#!/bin/bash
rootPath=$1
nginxVersion=1.13  # Could also be passed as an argument using $2

docker run --rm -t -a stdout --name my-nginx -v ${rootPath}/config/:/etc/nginx/:ro nginx:$nginxVersion nginx -c /etc/nginx/nginx.conf -t

if [ $? -ne 0 ]; then
    echo FAILED
    exit 1
else
    echo SUCCESS
    exit 0
fi
Enter fullscreen mode Exit fullscreen mode
Collapse
 
dev1l profile image
DeV1L

This is a great idea! Thanks

Collapse
 
n1ru4l profile image
Laurin Quast

Great read 😊

I wonder if there is a way to check my docker container config without failing because some upstream host cannot be resolved 🤔.

Collapse
 
cleydyr profile image
Cleydyr Bezerra de Albuquerque

That was a problem I was facing as well when I used this script. In case you or anyone is looking for an answer, maybe those can help

serverfault.com/questions/700894/m...
stackoverflow.com/questions/328456...